-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Avoid double-processing post content when parsing block template HTML #3549
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: trunk
Are you sure you want to change the base?
Changes from all commits
abba2ae
a810c7e
3a89988
ae0a332
f49d532
ac75d2f
61f2f21
0ea23a3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -235,16 +235,61 @@ function get_the_block_template_html() { | |||||||||||||
| return; | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| // Record all post content strings into this list to avoid double parsing. | ||||||||||||||
| $parsed_post_content = array(); | ||||||||||||||
| add_filter( | ||||||||||||||
| 'render_block_core/post-content', | ||||||||||||||
| function( $block_content ) use ( &$parsed_post_content ) { | ||||||||||||||
| $parsed_post_content[] = $block_content; | ||||||||||||||
| return $block_content; | ||||||||||||||
| }, | ||||||||||||||
| PHP_INT_MAX | ||||||||||||||
| ); | ||||||||||||||
|
|
||||||||||||||
| $content = $wp_embed->run_shortcode( $_wp_current_template_content ); | ||||||||||||||
| $content = $wp_embed->autoembed( $content ); | ||||||||||||||
| $content = do_blocks( $content ); | ||||||||||||||
|
|
||||||||||||||
| // Replace all post content within the template with a temporary placeholder so that the post content is not | ||||||||||||||
| // unnecessarily processed again. See https://core.trac.wordpress.org/ticket/55996. | ||||||||||||||
|
Comment on lines
+253
to
+254
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Should use the multiline comment format here. |
||||||||||||||
| if ( ! empty( $parsed_post_content ) ) { | ||||||||||||||
| // Ensure a placeholder is used that is not already present in the content. | ||||||||||||||
| $content_placeholder = '<!-- wp-post-content-placeholder-%d -->'; | ||||||||||||||
| $existing_placeholder_count = 0; | ||||||||||||||
| while ( preg_match( '/' . sprintf( $content_placeholder, '[0-9]+' ) . '/', $content ) ) { | ||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't love using a while loop and regex ( preg_match ) here. Is there no way we could do a single regex and loop through all the matching blocks?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems like it should be possible with |
||||||||||||||
| $existing_placeholder_count++; | ||||||||||||||
| $content_placeholder = '<!-- wp' . $existing_placeholder_count . '-post-content-placeholder-%d -->'; | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| foreach ( $parsed_post_content as $i => $post_content ) { | ||||||||||||||
| $pos = strpos( $content, $post_content ); | ||||||||||||||
| if ( false !== $pos ) { | ||||||||||||||
|
Comment on lines
+265
to
+266
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we use |
||||||||||||||
| $content = substr_replace( $content, sprintf( $content_placeholder, $i ), $pos, strlen( $post_content ) ); | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| $content = wptexturize( $content ); | ||||||||||||||
| $content = convert_smilies( $content ); | ||||||||||||||
| $content = shortcode_unautop( $content ); | ||||||||||||||
| $content = wp_filter_content_tags( $content ); | ||||||||||||||
| $content = wp_filter_content_tags( $content, 'the_block_template' ); | ||||||||||||||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change is a bit unrelated, but since here this function is called outside of any filter, it is crucial to manually provide a
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's do this in another commit. No need to block this change as of this ticket. |
||||||||||||||
| $content = do_shortcode( $content ); | ||||||||||||||
| $content = str_replace( ']]>', ']]>', $content ); | ||||||||||||||
|
|
||||||||||||||
| // Now that the template has been fully processed, add back in all post content. | ||||||||||||||
| if ( ! empty( $parsed_post_content ) ) { | ||||||||||||||
| $content = str_replace( | ||||||||||||||
| array_map( | ||||||||||||||
| function( $i ) use ( $content_placeholder ) { | ||||||||||||||
| return sprintf( $content_placeholder, $i ); | ||||||||||||||
| }, | ||||||||||||||
| array_keys( $parsed_post_content ) | ||||||||||||||
| ), | ||||||||||||||
| $parsed_post_content, | ||||||||||||||
| $content | ||||||||||||||
| ); | ||||||||||||||
|
Comment on lines
+281
to
+290
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would not say this is specially readable. Any chance we could just use a simple for each loop here? It would mean not requiring this function.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That sounds like a good idea. Also, while not huge in real terms, using foreach ( $parsed_post_content as $item_number => $replacement ) {
$content = str_replace(
sprintf( $content_placeholder, $item_number ),
$replacement,
$content
);
} |
||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| // Wrap block template in .wp-site-blocks to allow for specific descendant styles | ||||||||||||||
| // (e.g. `.wp-site-blocks > *`). | ||||||||||||||
| return '<div class="wp-site-blocks">' . $content . '</div>'; | ||||||||||||||
|
|
||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we do this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WordPress/gutenberg#44995 does exactly what you are suggesting. @felixarntz informed me that it does not actually fix the problem, and nor does your similar implementation #3833.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
He did not seem at all interested in assisting with a solution based on filter removal, even after I informed him that his implementation would break shortcodes. I just don't have the familiarity with
wp_filter_content_tagsto know how to implement it correctly, and all I can tell is that the$contextvariable needs to be set to'the_content'for it to work as intended.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As noted in my PR, even after applying this PR, filters are applied double, as image filter is applied in template_part funciton.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not talking about the same thing. It's not because of the template part, it's because there are conditions that require the the
$contextvariable to be set to'the_content'rather than'the_block_template_html', and I'm not sure of the ramifications of changing the condition to allow a different value or explicitly passing'the_content'to make the condition pass. If @felixarntz is willing to assist in this area then we might be able to use WordPress/gutenberg#44995 as the solution instead of putting up with his messy implementation.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@spacedmonkey Removing the filters around the
do_blocks()call is only a partial solution. This "record before, reinstate after" approach is the only one that solves both "double execution problem" and also the "avoid all execution problem" as discussed at length in 55996.If I need to open another ticket on Trac so that the "avoid all execution problem" is considered of equal importance to the "double execution problem" then I guess I'll do that :) In the meantime, this approach is the one that works for both problems.