From ffb8b430725bed776d7a52ec87de717a363e8319 Mon Sep 17 00:00:00 2001 From: Bernhard Reiter Date: Mon, 25 Sep 2023 08:44:22 +0000 Subject: [PATCH] Blocks: Introduce filter to allow easy addition of hooked blocks. Introduce a `hooked_block_types` filter that allows easier conditional addition (or removal) of hooked blocks for a given anchor block and relative position. {{{#!php function insert_shopping_cart_hooked_block( $hooked_blocks, $position, $anchor_block, $context ) { if ( 'after' === $position && 'core/navigation' === $anchor_block && /** $context is header template part **/ ) { $hooked_blocks[] = 'mycommerce/shopping-cart'; } return $hooked_blocks; } add_filter( 'hooked_block_types', 'insert_shopping_cart_hooked_block', 10, 4 ); }}} Props gziolo, nerrad, dmsnell, ndiego. Fixes #59424. Built from https://develop.svn.wordpress.org/trunk@56673 git-svn-id: http://core.svn.wordpress.org/trunk@56185 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/blocks.php | 111 ++++++++++++++++++++++++---------------- wp-includes/version.php | 2 +- 2 files changed, 68 insertions(+), 45 deletions(-) diff --git a/wp-includes/blocks.php b/wp-includes/blocks.php index 4b39ff2400..ef844fbcbe 100644 --- a/wp-includes/blocks.php +++ b/wp-includes/blocks.php @@ -744,20 +744,25 @@ function get_dynamic_block_names() { * * @since 6.4.0 * - * @param string $name Block type name including namespace. + * @param string $name Block type name including namespace. + * @param string $relative_position Optional. Relative position of the hooked block. Default empty string. * @return array Associative array of `$block_type_name => $position` pairs. */ -function get_hooked_blocks( $name ) { +function get_hooked_blocks( $name, $relative_position = '' ) { $block_types = WP_Block_Type_Registry::get_instance()->get_all_registered(); $hooked_blocks = array(); foreach ( $block_types as $block_type ) { if ( ! property_exists( $block_type, 'block_hooks' ) || ! is_array( $block_type->block_hooks ) ) { continue; } - foreach ( $block_type->block_hooks as $anchor_block_type => $relative_position ) { - if ( $anchor_block_type === $name ) { - $hooked_blocks[ $block_type->name ] = $relative_position; + foreach ( $block_type->block_hooks as $anchor_block_type => $position ) { + if ( $anchor_block_type !== $name ) { + continue; } + if ( $relative_position && $relative_position !== $position ) { + continue; + } + $hooked_blocks[ $block_type->name ] = $position; } } return $hooked_blocks; @@ -797,34 +802,48 @@ function make_before_block_visitor( $context ) { if ( $parent && ! $prev ) { // Candidate for first-child insertion. - $hooked_blocks_for_parent = get_hooked_blocks( $parent['blockName'] ); - foreach ( $hooked_blocks_for_parent as $hooked_block_type => $relative_position ) { - if ( 'first_child' === $relative_position ) { - $hooked_block_markup = get_comment_delimited_block_content( $hooked_block_type, array(), '' ); - /** This filter is documented in wp-includes/blocks.php */ - $markup .= apply_filters( 'inject_hooked_block_markup', $hooked_block_markup, $hooked_block_type, $relative_position, $parent, $context ); - } + $relative_position = 'first_child'; + $anchor_block_type = $parent['blockName']; + $hooked_block_types = array_keys( get_hooked_blocks( $anchor_block_type, $relative_position ) ); + /** + * Filters the list of hooked block types for a given anchor block type and relative position. + * + * @since 6.4.0 + * + * @param string[] $hooked_block_types The list of hooked block types. + * @param string $relative_position The relative position of the hooked blocks. + * Can be one of 'before', 'after', 'first_child', or 'last_child'. + * @param string $anchor_block_type The anchor block type. + * @param WP_Block_Template|array $context The block template, template part, or pattern that the anchor block belongs to. + */ + $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 ) { + $hooked_block_markup = get_comment_delimited_block_content( $hooked_block_type, array(), '' ); + /** This filter is documented in wp-includes/blocks.php */ + $markup .= apply_filters( 'inject_hooked_block_markup', $hooked_block_markup, $hooked_block_type, $relative_position, $parent, $context ); } } - $hooked_blocks = get_hooked_blocks( $block['blockName'] ); - foreach ( $hooked_blocks as $hooked_block_type => $relative_position ) { - if ( 'before' === $relative_position ) { - $hooked_block_markup = get_comment_delimited_block_content( $hooked_block_type, array(), '' ); - /** - * Filters the serialized markup of a hooked block. - * - * @since 6.4.0 - * - * @param string $hooked_block_markup The serialized markup of the hooked block. - * @param string $hooked_block_type The type of the hooked block. - * @param string $relative_position The relative position of the hooked block. - * Can be one of 'before', 'after', 'first_child', or 'last_child'. - * @param array $block The anchor block. - * @param WP_Block_Template|array $context The block template, template part, or pattern that the anchor block belongs to. - */ - $markup .= apply_filters( 'inject_hooked_block_markup', $hooked_block_markup, $hooked_block_type, $relative_position, $block, $context ); - } + $relative_position = 'before'; + $anchor_block_type = $block['blockName']; + $hooked_block_types = array_keys( get_hooked_blocks( $anchor_block_type, $relative_position ) ); + /** 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 ) { + $hooked_block_markup = get_comment_delimited_block_content( $hooked_block_type, array(), '' ); + /** + * Filters the serialized markup of a hooked block. + * + * @since 6.4.0 + * + * @param string $hooked_block_markup The serialized markup of the hooked block. + * @param string $hooked_block_type The type of the hooked block. + * @param string $relative_position The relative position of the hooked block. + * Can be one of 'before', 'after', 'first_child', or 'last_child'. + * @param array $block The anchor block. + * @param WP_Block_Template|array $context The block template, template part, or pattern that the anchor block belongs to. + */ + $markup .= apply_filters( 'inject_hooked_block_markup', $hooked_block_markup, $hooked_block_type, $relative_position, $block, $context ); } return $markup; @@ -860,24 +879,28 @@ function make_after_block_visitor( $context ) { return function( &$block, $parent = null, $next = null ) use ( $context ) { $markup = ''; - $hooked_blocks = get_hooked_blocks( $block['blockName'] ); - foreach ( $hooked_blocks as $hooked_block_type => $relative_position ) { - if ( 'after' === $relative_position ) { - $hooked_block_markup = get_comment_delimited_block_content( $hooked_block_type, array(), '' ); - /** This filter is documented in wp-includes/blocks.php */ - $markup .= apply_filters( 'inject_hooked_block_markup', $hooked_block_markup, $hooked_block_type, $relative_position, $block, $context ); - } + $relative_position = 'after'; + $anchor_block_type = $block['blockName']; + $hooked_block_types = array_keys( get_hooked_blocks( $anchor_block_type, $relative_position ) ); + /** 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 ) { + $hooked_block_markup = get_comment_delimited_block_content( $hooked_block_type, array(), '' ); + /** This filter is documented in wp-includes/blocks.php */ + $markup .= apply_filters( 'inject_hooked_block_markup', $hooked_block_markup, $hooked_block_type, $relative_position, $block, $context ); } if ( $parent && ! $next ) { // Candidate for last-child insertion. - $hooked_blocks_for_parent = get_hooked_blocks( $parent['blockName'] ); - foreach ( $hooked_blocks_for_parent as $hooked_block_type => $relative_position ) { - if ( 'last_child' === $relative_position ) { - $hooked_block_markup = get_comment_delimited_block_content( $hooked_block_type, array(), '' ); - /** This filter is documented in wp-includes/blocks.php */ - $markup .= apply_filters( 'inject_hooked_block_markup', $hooked_block_markup, $hooked_block_type, $relative_position, $parent, $context ); - } + $relative_position = 'last_child'; + $anchor_block_type = $parent['blockName']; + $hooked_block_types = array_keys( get_hooked_blocks( $anchor_block_type, $relative_position ) ); + /** 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 ) { + $hooked_block_markup = get_comment_delimited_block_content( $hooked_block_type, array(), '' ); + /** This filter is documented in wp-includes/blocks.php */ + $markup .= apply_filters( 'inject_hooked_block_markup', $hooked_block_markup, $hooked_block_type, $relative_position, $parent, $context ); } } diff --git a/wp-includes/version.php b/wp-includes/version.php index bb2c56183d..9d9a6077df 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -16,7 +16,7 @@ * * @global string $wp_version */ -$wp_version = '6.4-alpha-56672'; +$wp_version = '6.4-alpha-56673'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.