Block Hooks: Store ignored hooked blocks metadata in anchor block.

The biggest tradeoff that was made in the implementation of Block Hooks was that they were limited to layouts (i.e. templates, template parts, and patterns) that ''didn't have any user modifications'' (see #59313 for the reason). This changeset is a preparatory step to remove this limitation, so they’ll eventually also work with user-modified layouts.

The crucial problem to solve is how to acknowledge that a user has opted to remove or persist a hooked block, so that the auto-insertion mechanism won't run again and inject an extraneous hooked block on the frontend when none is solicited.

This is achieved by storing all known blocks hooked to a given anchor block in the `metadata` attribute on that anchor block; specifically in a field called `ignoredHookedBlocks` inside of the `metadata`. Hooked blocks are only rendered on the frontend if they're absent from that field; OTOH, they're injected into that field (via the REST API) when first loaded in the editor.

This simple logic guarantees that once a user modifies a given layout, those changes are respected on the frontend; yet if a plugin that includes a hooked block is activated after those modifications have taken place, the hooked block will be rendered on the frontend. This new technique supplants the one previously used (i.e. rendering hooked blocks on the frontend only if a layout doesn't have any modifications) in a rather direct way.

Note that this changeset only introduces the new metadata field and relevant logic; it does not yet enable hooked block insertion into modified layouts. That will be done in a subsequent step (see #59646).

Props gziolo.
Closes #60008.
Built from https://develop.svn.wordpress.org/trunk@57157


git-svn-id: http://core.svn.wordpress.org/trunk@56668 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Bernhard Reiter 2023-12-04 20:26:22 +00:00
parent 04152c0b91
commit 5e795b65ef
2 changed files with 37 additions and 5 deletions

View File

@ -757,6 +757,38 @@ function get_hooked_blocks() {
return $hooked_blocks;
}
/**
* Conditionally returns the markup for a given hooked block type.
*
* Accepts two arguments: A reference to an anchor block, and the name of a hooked block type.
* If the anchor block has already been processed, and the given hooked block type is in the list
* of ignored hooked blocks, an empty string is returned.
*
* This function is meant for internal use only.
*
* @since 6.5.0
* @access private
*
* @param array $anchor_block The anchor block. Passed by reference.
* @param string $hooked_block_type The name of the hooked block type.
* @return string The markup for the given hooked block type, or an empty string if the block is ignored.
*/
function get_hooked_block_markup( &$anchor_block, $hooked_block_type ) {
if ( ! isset( $anchor_block['attrs']['metadata']['ignoredHookedBlocks'] ) ) {
$anchor_block['attrs']['metadata']['ignoredHookedBlocks'] = array();
}
if ( in_array( $hooked_block_type, $anchor_block['attrs']['metadata']['ignoredHookedBlocks'] ) ) {
return '';
}
// The following is only needed for the REST API endpoint.
// However, its presence does not affect the frontend.
$anchor_block['attrs']['metadata']['ignoredHookedBlocks'][] = $hooked_block_type;
return get_comment_delimited_block_content( $hooked_block_type, array(), '' );
}
/**
* Returns a function that injects the theme attribute into, and hooked blocks before, a given block.
*
@ -813,7 +845,7 @@ function make_before_block_visitor( $hooked_blocks, $context ) {
*/
$hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
foreach ( $hooked_block_types as $hooked_block_type ) {
$markup .= get_comment_delimited_block_content( $hooked_block_type, array(), '' );
$markup .= get_hooked_block_markup( $parent_block, $hooked_block_type );
}
}
@ -826,7 +858,7 @@ function make_before_block_visitor( $hooked_blocks, $context ) {
/** This filter is documented in wp-includes/blocks.php */
$hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
foreach ( $hooked_block_types as $hooked_block_type ) {
$markup .= get_comment_delimited_block_content( $hooked_block_type, array(), '' );
$markup .= get_hooked_block_markup( $block, $hooked_block_type );
}
return $markup;
@ -874,7 +906,7 @@ function make_after_block_visitor( $hooked_blocks, $context ) {
/** This filter is documented in wp-includes/blocks.php */
$hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
foreach ( $hooked_block_types as $hooked_block_type ) {
$markup .= get_comment_delimited_block_content( $hooked_block_type, array(), '' );
$markup .= get_hooked_block_markup( $block, $hooked_block_type );
}
if ( $parent_block && ! $next ) {
@ -888,7 +920,7 @@ function make_after_block_visitor( $hooked_blocks, $context ) {
/** This filter is documented in wp-includes/blocks.php */
$hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
foreach ( $hooked_block_types as $hooked_block_type ) {
$markup .= get_comment_delimited_block_content( $hooked_block_type, array(), '' );
$markup .= get_hooked_block_markup( $parent_block, $hooked_block_type );
}
}

View File

@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
$wp_version = '6.5-alpha-57155';
$wp_version = '6.5-alpha-57157';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.