Skip to content
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

Remove the_content filter for block_template_parts #20343

Conversation

johnstonphilip
Copy link
Contributor

@johnstonphilip johnstonphilip commented Feb 20, 2020

Description

This PR fixes #20342, where content filtered to the_content appears after every block template part is output.

How has this been tested?

  1. Create a block-based theme, with the header.html and footer.html in the block-template-parts directory, and the index.html file pulling those in.
  2. Add this code to a custom plugin:
function my_content_after_the_content( $the_content ) {
	return $the_content .
	'<div class="sharing_icons">I am hooked to the_content, to appear after every output of the_content</div>';
}
 add_filter( 'the_content', 'my_content_after_the_content' );
  1. View a post.
  2. Notice you see the hooked output after each template_part is shown.

Types of changes

Bug fix.

Screenshots:

Before:

Screen Shot 2020-02-20 at 2 36 18 PM

After:

Screen Shot 2020-02-20 at 2 58 38 PM

Checklist:

  • [✔] My code is tested.
  • [✔] My code follows the WordPress code style.
  • [✔] My code follows the accessibility standards.
  • [✔] My code has proper inline documentation.
  • [✔] I've included developer documentation if appropriate.
  • [✔] I've updated all React Native files affected by any refactorings/renamings in this PR.

@@ -32,7 +32,7 @@ function render_block_core_template_part( $attributes ) {
if ( is_null( $content ) ) {
return 'Template Part Not Found';
}
return apply_filters( 'the_content', str_replace( ']]>', ']]&gt;', $content ) );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this filter is needed to run dynamic blocks, shortcuts and other things in the content of the template part, what's the reason behind removing it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@youknowriad I attempted to explain the problem in my description. Here's a screenshot that hopefully illustrates it:

https://user-images.githubusercontent.com/7538525/74973542-975e8800-53f1-11ea-9bdf-73a0cabdbea0.png

Imagine those red boxes are Social Sharing buttons, or purchase buttons from an ecommerce plugin (Easy Digital Downloads does this for example). You'll get duplicate output on the screen after every template part.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really think that's an issue though, is it? You're just running the hook on all post types (all contents)?

An alternative here would be to have another the_template_content or something like that, that does the same thing as the_content but excludes third-party the_content filters maybe.

i believe if we don't run the filter now, dynamic blocks inside template parts don't work properly right (I didn't test, just a guess) (among other things maybe, embeds, shortcodes...)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@youknowriad While we definitely can't use the_content here due to many plugins authors using that for custom outputs over the years, I believe you're correct that we do need to do the same processing on the return. We should likely introduce a new filter like the one you described. How about calling it the_template_part to make it specific for this context? If you agree I can add that to this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense but I'd love thoughts from other folks cc @epiqueras @mcsf @azaozz
Also, I'm thinking some of these filters are not needed because they will apply after the fact to the output of the template part too on the parent template get_the_content calls. (depends on the priority I guess)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@youknowriad You are correct that dynamic blocks and shortcodes do not work in the header.html file with this PR.

I took another shot at this here, where I've added a new/dedicated filter, instead of removing it entirely:
#20344

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@epiqueras That works as well. Added here: 729a613

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest we manually run the filters

Yeah, should be "good enough" for testing. The prepend_attachment can be removed. It is an ancient hack (from WP 2.0) for when an attachment post is displayed. Doesn't do anything if the current post is not an attachment:

	$post = get_post();

	if ( empty( $post->post_type ) || 'attachment' !== $post->post_type ) {
		return $content;
	}

However this brings another question: most of these "display filters" are intended to run on the front-end for post_content and expect things like $post = get_post(); (i.e. the PHP global $post to be set) in order to work. Even if core doesn't rely on the global, some plugins will. Seems this will need some "special handling" for when the new filter for template parts is added.

Copy link
Contributor

@epiqueras epiqueras left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching this!

@epiqueras epiqueras merged commit 2f85f89 into WordPress:master Feb 21, 2020
@github-actions github-actions bot added this to the Gutenberg 7.6 milestone Feb 21, 2020
@azaozz
Copy link
Contributor

azaozz commented Feb 21, 2020

Uh, sorry, a bit late to the party :)

An alternative here would be to have another (filter) the_template_content or something like that, that does the same thing as the_content but excludes third-party the_content filters maybe.

Yeah, thinking that'd be best. The old filter is generally expected to run only on post_content (including when auto-generatig excerpt), and is used in many plugins. It shouldn't be reused in other contexts.

Also, I'm thinking some of these filters are not needed

Big +1. The template parts only support blocks. Things like wpautop and out-of-block/old-style shortcode processing don't seem to make sense. Looking at the default filters:

add_filter( 'the_content', 'do_blocks', 9 );
add_filter( 'the_content', 'wptexturize' );
add_filter( 'the_content', 'convert_smilies', 20 );
add_filter( 'the_content', 'wpautop' );
add_filter( 'the_content', 'shortcode_unautop' );
add_filter( 'the_content', 'prepend_attachment' );
add_filter( 'the_content', 'wp_make_content_images_responsive' );
add_filter( 'the_content', 'do_shortcode', 11 );

only do_blocks, wptexturize, convert_smilies, and wp_make_content_images_responsive would be needed. The rest are handled per-block , and wpautop is (should be?) redundant.

@johnstonphilip
Copy link
Contributor Author

@azaozz I tested removing each thing you mentioned. Here are the results of each:

Removing wpautop (Results in problem ❌)

Result: Results in broken double-line-to-paragraphs in the header.html output
Conclusion: It should remain here.
Screenshots:
Screen Shot 2020-02-21 at 9 07 51 AM

Screen Shot 2020-02-21 at 9 08 08 AM

Removing prepend_attachment (Seems to be okay ✅)

Result: Nothing seems to break with this removed, since this is targeted to viewing attachment posts. I can't think of a scenario where you would be setting the global $post to be an attachment ID within a post_template_part, but if anyone can think of a reason that might need to happen, that would be an argument for this staying here.
Conclusion: It can be removed.

Removing do_shortcode (Results in problem ❌)

Result: Results in broken shortcodes in post_template_part(s)
Conclusion: It should remain here.
Screenshots:
Screen Shot 2020-02-21 at 9 00 26 AM
Screen Shot 2020-02-21 at 9 09 14 AM

In conclusion, I think we can remove prepend_attachment, but none of the other filters. I will submit a PR for that and follow up here.

@epiqueras
Copy link
Contributor

Thanks for the sleuthing!

@azaozz
Copy link
Contributor

azaozz commented Feb 21, 2020

I tested removing each thing you mentioned.

Yeah, this is partially a "review" of how things work or don't work in template parts. You're right, here's not the best place. Haven't had the time yet, but will definitely try to find the discussion(s) for these.

Removing wpautop: Results in broken double-line-to-paragraphs in the header.html

If double line breaks have to be converted to paragraph tags, why would you expect that to happen dynamically on the front-end? This is intended for when editing HTML in plain textarea (no JavaScript involved at all). Is it even possible to do in a block inside the editor?

Removing do_shortcode: Results in broken shortcodes in post_template_part(s)

Same thing, why would template parts support this ancient, buggy, inefficient way to bypass dynamic blocks?

Both wpautop and shortcodes have to work in post_content for historical reasons. But they don't make much sense outside of post_content. Supporting them in template HTML doesn't seem good.

@johnstonphilip
Copy link
Contributor Author

johnstonphilip commented Feb 21, 2020

@azaozz Good points. Looking at it again, I agree about wpautop.

But for shortcodes, unless we remove the shortcode block from Gutenberg, people can still use shortcodes, and that will include in their header. Without calling do_shortcode, shortcodes in the shortcode block do not render.

Screen Shot 2020-02-21 at 2 34 15 PM

For wpautop, I tested the Classic Editor block to make sure it wouldn't require wpautop, and it does not, as it converted my multi-line breaks to <p> before saving to the db.

I don't think there are any other "legacy" style blocks that would require wpautop either, so I think we should remove wpautop.

@azaozz
Copy link
Contributor

azaozz commented Feb 21, 2020

I don't think there are any other "legacy" style blocks that would require wpautop either

Yeah, don't think autop is used anywhere else. (Also thinking it's about time to review the classic block and remove it from there too. The part that strips the <p> tags is used in only one edge case as far as I remember).

But for shortcodes, unless we remove the shortcode block from Gutenberg...

The shortcode block is back-compat for when editing post_content. Don't see a good reason for it to be supported in any other context. Don't think it can be removed from Gutenberg (at least not yet) but thinking it doesn't make sense for template parts. There's a way to filter the available blocks according to context (if I remember right).

@johnstonphilip
Copy link
Contributor Author

@azaozz after giving it a lot of thought and discussing with a few people, I agree that shortcodes could be removed from block template parts.

I took a shot at that here:
#20452

However, I was not able to find a way to conditionally filter the available blocks based on context like you described.

There's a way to filter the available blocks according to context (if I remember right).

@epiqueras
Copy link
Contributor

blockType.parent lets you define the set of blocks where a block should be allowed, and there were proposals for it to support negatives like !core/group, but nothing concrete.

$content = wpautop( $content );
$content = shortcode_unautop( $content );
$content = prepend_attachment( $content );
$content = wp_make_content_images_responsive( $content );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that this triggers a warning on WordPress trunk

Capture d’écran 2020-04-09 à 5 23 32 PM

We should probably update to use the latest behavior instead

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@youknowriad PR opened: #21514

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Output hooked to the_content is output after template parts in Block Based Themes
4 participants