Make WordPress Core

Opened 4 weeks ago

Closed 3 weeks ago

#63287 closed defect (bug) (fixed)

Unexpected output from apply_block_hooks_to_content_from_post_object

Reported by: obenland's profile obenland Owned by: bernhard-reiter's profile bernhard-reiter
Milestone: 6.8.1 Priority: normal
Severity: normal Version: 6.8
Component: Editor Keywords: has-patch has-unit-tests fixed-major
Focuses: Cc:

Description

When there are blocks hooked into 'core/post-content' => 'after', it creates unbalanced tags for remove_serialized_parent_block() in apply_block_hooks_to_content_from_post_object():

<!-- wp:post-content --><!-- wp:heading {"level":1} --><h1>Hello World!</h1><!-- /wp:heading --><!-- /wp:post-content --><!-- wp:tests/hooked-block /-->

The result I'm seeing is the hooked block being removed and leaving the closing wp:post-content tag:

<!-- wp:heading {"level":1} --><h1>Hello World!</h1><!-- /wp:heading --><!-- /wp:post-content -->

I'll attach a diff with failing tests to work against.

Attachments (1)

post-content-after.diff (623 bytes) - added by obenland 4 weeks ago.
Diff to make tests fail

Download all attachments as: .zip

Change History (18)

@obenland
4 weeks ago

Diff to make tests fail

This ticket was mentioned in PR #8695 on WordPress/wordpress-develop by @jorbin.


4 weeks ago
#1

  • Keywords has-patch has-unit-tests added

#2 @jorbin
4 weeks ago

  • Component changed from General to Editor
  • Keywords has-patch has-unit-tests removed

Welcome back to trac @obenland!

I moved the patch to GH so we can all see the results of the automated tests.

#3 @edent
4 weeks ago

This also happens on non-block themes as well.

At the end of every post is <!-- /wp:post-content -->

I'm using the classic editor with a theme which doesn't use blocks.

#4 @Bernhard Reiter
4 weeks ago

I'll look into this today!

#5 @Bernhard Reiter
4 weeks ago

Right. So the crux is that the block wrapper is needed temporarily to allow for first/last child insertion into the Post Content block, as it translates between the post's ignoredHookedBlocks meta (i.e. reads from post meta and sets the corresponding block attribute on the wrapper block, and writes back to post meta based on the latter upon writing).

It's a different story for before/after insertion: If a block is inserted before or after the wrapper, it'll confuse remove_serialized_parent_block(), as @obenland pointed out.

I'll need to give this a bit more thought to figure out the correct solution. My intuition says that before/after insertion should be handled one layer higher (e.g. by the template that includes the Post Content block). In particular, I don't think that a hooked block inserted before/after a Post Content block should be stored inside its corresponding post object content. (Instead, it should probably end up next to the Post Content block, inside the containing markup.)

There are however some subtleties that we'll need to think through. For one, it raises the question where to store ignoredHookedBlocks: Continue to use the post meta, or use the containing markup's post content block delimiter?

It will probably also mean that we'll lose the ability to insert before or after post content in a non-block theme, but that's probably okay (as we wouldn't be dealing with a Post Content block strictly speaking, so there's no anchor block before or after which we could insert our hooked block).

#6 @Bernhard Reiter
4 weeks ago

  • Milestone changed from Awaiting Review to 6.8.1

This might be pesky enough of an issue to warrant a fix in 6.8.1.

This ticket was mentioned in PR #8700 on WordPress/wordpress-develop by @Bernhard Reiter.


4 weeks ago
#7

  • Keywords has-patch has-unit-tests added

WIP.

Needs additional test coverage:

  • Hooked block inserted before/after Post Content block via hooked_block_types filter.
  • Hooked block inserted in before/after position _inside_ of Post Content block.
  • Hooked block inserted before/after Post Content block contained in other context (e.g. inside a template).

Props @obenland @aaronjorbin @gziolo.

Trac ticket: https://core.trac.wordpress.org/ticket/63287

@Bernhard Reiter commented on PR #8695:


4 weeks ago
#8

Thank you @aaronjorbin and @obenland!

I've filed https://github.com/WordPress/wordpress-develop/pull/8700 to work on a fix.

#9 @jorbin
4 weeks ago

  • Version set to 6.8

@Bernhard Reiter commented on PR #8700:


4 weeks ago
#10

We should probably check what happens if the user modifies a template in the Site Editor that contains a Post Content block that has a block hooked before or after it.

@gziolo commented on PR #8700:


4 weeks ago
#11

There are some reported coding style issues. Otherwise, all tests pass including newly added coverage for the advanced use case of using hooked_block_types filter. Nice work!

#12 @Bernhard Reiter
4 weeks ago

  • Resolution set to fixed
  • Status changed from assigned to closed

In 60173:

Block Hooks: Suppress insertion next to post content wrapper block.

As of [59523], Block Hooks are applied to post content. In order to allow for insertion of a hooked block as first_child or last_child of the containing Post Content block, we wrap the block's post content (as obtained from the DB) in a temporary <!-- wp:post-content --> wrapper block, apply the Block Hooks algorithm to the resulting markup, and remove the wrapper block. (The same technique is applied for the Synced Pattern block -- see [59543] -- as well as the Navigation block.)

However, this caused a problem when a hooked block was marked for insertion before before or after a Post Content block: The logic that's supposed to remove the temporary wrapper block after the Block Hooks algorithm runs erroneously removed that hooked block's delimiter instead of the wrapper block, producing garbled markup as a result.

This changeset fixes the issue by adding a hooked_block_types filter (with PHP_INT_MAX priority) that removes any blocks hooked before or after a Post Content block, if the current context is a post object. This prevents any blocks hooked that way from being "absorbed" into the corresponding post object's content; it retains the ability to hook blocks before and after a Post Content block in any other context (e.g. a template). (The same principle is applied to Synced Pattern and Navigation blocks.)

Props obenland, jorbin, gziolo, bernhard-reiter.
Fixes #63287.

#13 @Bernhard Reiter
4 weeks ago

  • Keywords fixed-major added
  • Resolution fixed deleted
  • Status changed from closed to reopened

Re-opening to seek a second Core Committer's approval for backporting to the 6.8 branch.

#14 @edent
4 weeks ago

This also fixes the issue for non-block themes. Thank you!

This ticket was mentioned in Slack in #core by jorbin. View the logs.


3 weeks ago

This ticket was mentioned in Slack in #core by jorbin. View the logs.


3 weeks ago

#17 @jorbin
3 weeks ago

  • Resolution set to fixed
  • Status changed from reopened to closed

In 60189:

Block Hooks: Suppress insertion next to post content wrapper block.

As of [59523], Block Hooks are applied to post content. In order to allow for insertion of a hooked block as first_child or last_child of the containing Post Content block, we wrap the block's post content (as obtained from the DB) in a temporary <!-- wp:post-content --> wrapper block, apply the Block Hooks algorithm to the resulting markup, and remove the wrapper block. (The same technique is applied for the Synced Pattern block -- see [59543] -- as well as the Navigation block.)

However, this caused a problem when a hooked block was marked for insertion before before or after a Post Content block: The logic that's supposed to remove the temporary wrapper block after the Block Hooks algorithm runs erroneously removed that hooked block's delimiter instead of the wrapper block, producing garbled markup as a result.

This changeset fixes the issue by adding a hooked_block_types filter (with PHP_INT_MAX priority) that removes any blocks hooked before or after a Post Content block, if the current context is a post object. This prevents any blocks hooked that way from being "absorbed" into the corresponding post object's content; it retains the ability to hook blocks before and after a Post Content block in any other context (e.g. a template). (The same principle is applied to Synced Pattern and Navigation blocks.)

Reviewed by Jorbin.
Merges [60173] to 6.8 branch.

Props obenland, jorbin, gziolo, bernhard-reiter.
Fixes #63287.

Note: See TracTickets for help on using tickets.