Make WordPress Core

Opened 5 months ago

Closed 2 months ago

#62716 closed defect (bug) (fixed)

Block Hooks: Absorb logic to set ignored hooked blocks post meta into `apply_block_hooks_to_content`

Reported by: bernhard-reiter's profile Bernhard Reiter Owned by: bernhard-reiter's profile Bernhard Reiter
Milestone: 6.8 Priority: normal
Severity: normal Version:
Component: General Keywords: has-patch gutenberg-merge
Focuses: Cc:

Description

Per [59523] and [59543], Block Hooks are applied to post content and synced patterns, respectively.

In order to allow inserting hooked blocks as first and last children of a Post Content block (core/post-content), synced pattern (core/block), Template Part block (core/template-part, [60854]), and Navigation block (core/navigation), the block markup gathered from the corresponding post type is temporarily wrapped in a "virtual" instance of the respective block type. That temporary wrapper block furthermore has its metadata.ignoredHookedBlocks attribute set based on the corresponding post meta from the DB.

The Block Hooks algorithm is then applied to the full markup (including the wrapper block), thus reading and/or updating the block wrapper's metadata.ignoredHookedBlocks. (During a write operation, that metadata is then synced back to the post meta in the DB). Finally, the wrapper block is removed.

This pattern -- first introduced for the Navigation block -- is now repeated across a number of block types. It has been suggested by @gziolo that we absorb it into apply_block_hooks_to_content.

Change History (22)

#1 @gziolo
5 months ago

Thank you for opening this ticket!

#2 @Bernhard Reiter
4 months ago

Looks like we'll need to prioritize this to fix a bug I introduced when enabling Block Hooks for post content, see https://github.com/WordPress/gutenberg/issues/68605#issuecomment-2618970655.

#3 @Bernhard Reiter
4 months ago

  • Milestone changed from Awaiting Review to 6.8
  • Type changed from enhancement to defect (bug)

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


3 months ago
#4

  • Keywords has-patch added

@Mamaduka commented on PR #8212:


3 months ago
#5

Adding a unit test for unhappy paths might be a good idea. When post_content returns something different due to the filter.

@Mamaduka commented on PR #8212:


3 months ago
#6

@ockham, is this ready for review?

@Bernhard Reiter commented on PR #8212:


3 months ago
#7

@ockham, is this ready for review?

Not quite yet -- I still need to increase test coverage, and audit other callsites of apply_block_hooks_to_content to see if they should be changed to call apply_block_hooks_to_content_from_post_object instead.

I won't be able to work on this PR this week, but I'll continue work next week. I hope that works for you time-wise, @Mamaduka?

@Mamaduka commented on PR #8212:


3 months ago
#8

Thanks, @ockham!

That timeline should be okay for now. We just need to make sure this is merged before Beta 1.

#9 @joemcgill
3 months ago

  • Keywords gutenberg-merge added

Adding the gutenberg-merge keyword since this is related to changes from https://github.com/WordPress/gutenberg/pull/68926.

A note for any reviewers, this fixes issues noted in #61074 which effect the display of post content:

I've confirmed that I can reproduce the issue described in the second link and confirmed that the current PR (in progress) addresses the issue.

@Bernhard Reiter commented on PR #8212:


3 months ago
#10

Switching back to draft mode since I might've encountered a bug while testing.

@Bernhard Reiter commented on PR #8212:


3 months ago
#11

Note that when testing this with a block theme (e.g. TT5), hooked blocks in the first_child or last_child positions of the Post Content block will be inserted twice. E.g. when using this plugin for testing:

https://github.com/user-attachments/assets/76538206-0d7c-4511-bc10-131b0d4213d8

This problem will go away once changes to the Post Content block that were made in https://github.com/WordPress/gutenberg/pull/68926 are synced over to Core.

<details>
<summary>
You can simulate this by applying this patch.
</summary>

  • src/wp-includes/blocks/post-content.php

    diff --git a/src/wp-includes/blocks/post-content.php b/src/wp-includes/blocks/post-content.php
    index e0a06b7217..25be880cc4 100644
    a b function render_block_core_post_content( $attributes, $content, $block ) { 
    4646                $content .= wp_link_pages( array( 'echo' => 0 ) );
    4747        }
    4848
    49         $ignored_hooked_blocks = get_post_meta( $post_id, '_wp_ignored_hooked_blocks', true );
    50         if ( ! empty( $ignored_hooked_blocks ) ) {
    51                 $ignored_hooked_blocks  = json_decode( $ignored_hooked_blocks, true );
    52                 $attributes['metadata'] = array(
    53                         'ignoredHookedBlocks' => $ignored_hooked_blocks,
    54                 );
    55         }
    56 
    57         // Wrap in Post Content block so the Block Hooks algorithm can insert blocks
    58         // that are hooked as first or last child of `core/post-content`.
    59         $content = get_comment_delimited_block_content(
    60                 'core/post-content',
    61                 $attributes,
    62                 $content
    63         );
    64 
    65         // We need to remove the `core/post-content` block wrapper after the Block Hooks algorithm,
    66         // but before `do_blocks` runs, as it would otherwise attempt to render the same block again --
    67         // thus recursing infinitely.
    68         add_filter( 'the_content', 'remove_serialized_parent_block', 8 );
    69 
    7049        /** This filter is documented in wp-includes/post-template.php */
    7150        $content = apply_filters( 'the_content', str_replace( ']]>', ']]&gt;', $content ) );
    7251        unset( $seen_ids[ $post_id ] );
    7352
    74         remove_filter( 'the_content', 'remove_serialized_parent_block', 8 );
    75 
    7653        if ( empty( $content ) ) {
    7754                return '';
    7855        }

</details>

https://github.com/user-attachments/assets/cfd99ad0-9381-4837-b257-3ecb6308f9ce

@Bernhard Reiter commented on PR #8212:


3 months ago
#12

Heads-up, I'm thinking to include changes from https://github.com/WordPress/gutenberg/pull/69241 in this. (Should take a couple of minutes only.)

@Bernhard Reiter commented on PR #8212:


3 months ago
#13

Heads-up, I'm thinking to include changes from WordPress/gutenberg#69241 in this. (Should take a couple of minutes only.)

Done: https://github.com/WordPress/wordpress-develop/pull/8212/commits/970eef515bb910bf8c68a1414a8637263a67763b

#14 @Bernhard Reiter
3 months ago

  • Owner set to Bernhard Reiter
  • Resolution set to fixed
  • Status changed from new to closed

In 59838:

Block Hooks: Add function to encapsulate wrapping in ad-hoc parent.

Introduce a new function, apply_block_hooks_to_content_from_post_object, to colocate the logic used to temporarily wrap content in a parent block (with ignoredHookedBlocks information fetched from post meta) alongside the call to apply_block_hooks_to_content. Fetching that information from post meta is required for all block types that get their content from post objects, i.e. Post Content, Synced Pattern, and Navigation blocks.

Additionally, the newly introduced function contains logic to ensure that insertion of a hooked block into the first_child or last_child position of a given Post Content block works, even if that block only contains "classic" markup (i.e. no blocks).

Props bernhard-reiter, gziolo, mamaduka.
Fixes #61074, #62716.

#15 @johnjamesjacoby
3 months ago

  • Resolution fixed deleted
  • Status changed from closed to reopened

Seeing this notice running PHP version 8.4:

Deprecated: apply_block_hooks_to_content_from_post_object(): Implicitly marking parameter $post as nullable is deprecated, the explicit nullable type must be used instead in /wp-includes/blocks.php on line 1163

Recommend to remove the WP_Post type hint.

(I had to double-check, but a search through the core code revealed we only use the WP_Post $post pattern in docs; not in function definition parameters.)

#16 @johnjamesjacoby
3 months ago

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

In 59839:

Block Hooks: Remove WP_Post type hint.

This change prevents a PHP deprecation notice in the new apply_block_hooks_to_content_from_post_object() function, introduced in r59838.

Fixes #62716.

#17 @jorbin
3 months ago

  • Resolution fixed deleted
  • Status changed from closed to reopened

We can still get the benefit of the type hint by making it nullable instead of removing it all together. This will work down to php7.1 which is below the minimum WP version.

See https://3v4l.org/1Mdrl for the deprecation and https://3v4l.org/o764l for the nullable version

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


3 months ago
#18

We can still get the benefit of the type hint by making it nullable instead of removing it all together. This will work down to php7.1 which is below the minimum WP version.

See https://3v4l.org/1Mdrl for the deprecation and https://3v4l.org/o764l for the nullable version

Originally added in https://core.trac.wordpress.org/changeset/59838 Removed in https://core.trac.wordpress.org/changeset/59839

#19 @johnjamesjacoby
3 months ago

We can still get the benefit of the type hint by making it nullable instead of removing it all together. This will work down to php7.1 which is below the minimum WP version.

That syntax does get used on ints & arrays in a few random'ish places (SimplePie, wp_getimagesize(), etc...); just not with objects (and specifically not with ?WP_Post).

I'm not confident this ticket is the best place to introduce type hinting on a $post parameter that gets run through the_content. Hypothetically, plugins using the the_content filter on a non-WP_Post object would now fatal error when it would not previously, and that seems unintentional.

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


2 months ago

#21 @audrasjb
2 months ago

@jorbin do you think it's still realistic to keep this ticket in the milestone? About the PR added for further improvements, should we rather open a new ticket for these changes and close this one as fixed?

#22 @jorbin
2 months ago

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

@audrasjb Being that we should get it decided during this milestone (since adding a typehint to already released code could be a backcompat break), I don't think a new ticket would be helpful.

Nullable object hints are used in the Interactivity API and HTML API code so restoring them here wouldn't be something that has never been done before.

That said, I did a search to see what plugins applying filters to the content are doing and some are passing various things as the second param, so this would break sites running those plugins. Therefore, re-closing this.

Note: See TracTickets for help on using tickets.