Make WordPress Core

Changeset 56673


Ignore:
Timestamp:
09/25/2023 08:42:45 AM (7 months ago)
Author:
Bernhard Reiter
Message:

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.

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.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/blocks.php

    r56649 r56673  
    745745 * @since 6.4.0
    746746 *
    747  * @param string $name Block type name including namespace.
     747 * @param string $name              Block type name including namespace.
     748 * @param string $relative_position Optional. Relative position of the hooked block. Default empty string.
    748749 * @return array Associative array of `$block_type_name => $position` pairs.
    749750 */
    750 function get_hooked_blocks( $name ) {
     751function get_hooked_blocks( $name, $relative_position = '' ) {
    751752    $block_types = WP_Block_Type_Registry::get_instance()->get_all_registered();
    752753    $hooked_blocks = array();
     
    755756            continue;
    756757        }
    757         foreach ( $block_type->block_hooks as $anchor_block_type => $relative_position ) {
    758             if ( $anchor_block_type === $name ) {
    759                 $hooked_blocks[ $block_type->name ] = $relative_position;
    760             }
     758        foreach ( $block_type->block_hooks as $anchor_block_type => $position ) {
     759            if ( $anchor_block_type !== $name ) {
     760                continue;
     761            }
     762            if ( $relative_position && $relative_position !== $position ) {
     763                continue;
     764            }
     765            $hooked_blocks[ $block_type->name ] = $position;
    761766        }
    762767    }
     
    798803        if ( $parent && ! $prev ) {
    799804            // Candidate for first-child insertion.
    800             $hooked_blocks_for_parent = get_hooked_blocks( $parent['blockName'] );
    801             foreach ( $hooked_blocks_for_parent as $hooked_block_type => $relative_position ) {
    802                 if ( 'first_child' === $relative_position ) {
    803                     $hooked_block_markup = get_comment_delimited_block_content( $hooked_block_type, array(), '' );
    804                     /** This filter is documented in wp-includes/blocks.php */
    805                     $markup .= apply_filters( 'inject_hooked_block_markup', $hooked_block_markup, $hooked_block_type, $relative_position, $parent, $context );
    806                 }
    807             }
    808         }
    809 
    810         $hooked_blocks = get_hooked_blocks( $block['blockName'] );
    811         foreach ( $hooked_blocks as $hooked_block_type => $relative_position ) {
    812             if ( 'before' === $relative_position ) {
     805            $relative_position  = 'first_child';
     806            $anchor_block_type  = $parent['blockName'];
     807            $hooked_block_types = array_keys( get_hooked_blocks( $anchor_block_type, $relative_position ) );
     808            /**
     809             * Filters the list of hooked block types for a given anchor block type and relative position.
     810             *
     811             * @since 6.4.0
     812             *
     813             * @param string[]                $hooked_block_types  The list of hooked block types.
     814             * @param string                  $relative_position   The relative position of the hooked blocks.
     815             *                                                     Can be one of 'before', 'after', 'first_child', or 'last_child'.
     816             * @param string                  $anchor_block_type   The anchor block type.
     817             * @param WP_Block_Template|array $context             The block template, template part, or pattern that the anchor block belongs to.
     818             */
     819            $hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
     820            foreach ( $hooked_block_types as $hooked_block_type ) {
    813821                $hooked_block_markup = get_comment_delimited_block_content( $hooked_block_type, array(), '' );
    814                 /**
    815                  * Filters the serialized markup of a hooked block.
    816                  *
    817                  * @since 6.4.0
    818                  *
    819                  * @param string                  $hooked_block_markup The serialized markup of the hooked block.
    820                  * @param string                  $hooked_block_type   The type of the hooked block.
    821                  * @param string                  $relative_position   The relative position of the hooked block.
    822                  *                                                     Can be one of 'before', 'after', 'first_child', or 'last_child'.
    823                  * @param array                   $block               The anchor block.
    824                  * @param WP_Block_Template|array $context             The block template, template part, or pattern that the anchor block belongs to.
    825                  */
    826                 $markup .= apply_filters( 'inject_hooked_block_markup', $hooked_block_markup, $hooked_block_type, $relative_position, $block, $context );
    827             }
     822                /** This filter is documented in wp-includes/blocks.php */
     823                $markup .= apply_filters( 'inject_hooked_block_markup', $hooked_block_markup, $hooked_block_type, $relative_position, $parent, $context );
     824            }
     825        }
     826
     827        $relative_position  = 'before';
     828        $anchor_block_type  = $block['blockName'];
     829        $hooked_block_types = array_keys( get_hooked_blocks( $anchor_block_type, $relative_position ) );
     830        /** This filter is documented in wp-includes/blocks.php */
     831        $hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
     832        foreach ( $hooked_block_types as $hooked_block_type ) {
     833            $hooked_block_markup = get_comment_delimited_block_content( $hooked_block_type, array(), '' );
     834            /**
     835             * Filters the serialized markup of a hooked block.
     836             *
     837             * @since 6.4.0
     838             *
     839             * @param string                  $hooked_block_markup The serialized markup of the hooked block.
     840             * @param string                  $hooked_block_type   The type of the hooked block.
     841             * @param string                  $relative_position   The relative position of the hooked block.
     842             *                                                     Can be one of 'before', 'after', 'first_child', or 'last_child'.
     843             * @param array                   $block               The anchor block.
     844             * @param WP_Block_Template|array $context             The block template, template part, or pattern that the anchor block belongs to.
     845             */
     846            $markup .= apply_filters( 'inject_hooked_block_markup', $hooked_block_markup, $hooked_block_type, $relative_position, $block, $context );
    828847        }
    829848
     
    861880        $markup = '';
    862881
    863         $hooked_blocks = get_hooked_blocks( $block['blockName'] );
    864         foreach ( $hooked_blocks as $hooked_block_type => $relative_position ) {
    865             if ( 'after' === $relative_position ) {
     882        $relative_position  = 'after';
     883        $anchor_block_type  = $block['blockName'];
     884        $hooked_block_types = array_keys( get_hooked_blocks( $anchor_block_type, $relative_position ) );
     885        /** This filter is documented in wp-includes/blocks.php */
     886        $hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
     887        foreach ( $hooked_block_types as $hooked_block_type ) {
     888            $hooked_block_markup = get_comment_delimited_block_content( $hooked_block_type, array(), '' );
     889            /** This filter is documented in wp-includes/blocks.php */
     890            $markup .= apply_filters( 'inject_hooked_block_markup', $hooked_block_markup, $hooked_block_type, $relative_position, $block, $context );
     891        }
     892
     893        if ( $parent && ! $next ) {
     894            // Candidate for last-child insertion.
     895            $relative_position  = 'last_child';
     896            $anchor_block_type  = $parent['blockName'];
     897            $hooked_block_types = array_keys( get_hooked_blocks( $anchor_block_type, $relative_position ) );
     898            /** This filter is documented in wp-includes/blocks.php */
     899            $hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
     900            foreach ( $hooked_block_types as $hooked_block_type ) {
    866901                $hooked_block_markup = get_comment_delimited_block_content( $hooked_block_type, array(), '' );
    867902                /** This filter is documented in wp-includes/blocks.php */
    868                 $markup .= apply_filters( 'inject_hooked_block_markup', $hooked_block_markup, $hooked_block_type, $relative_position, $block, $context );
    869             }
    870         }
    871 
    872         if ( $parent && ! $next ) {
    873             // Candidate for last-child insertion.
    874             $hooked_blocks_for_parent = get_hooked_blocks( $parent['blockName'] );
    875             foreach ( $hooked_blocks_for_parent as $hooked_block_type => $relative_position ) {
    876                 if ( 'last_child' === $relative_position ) {
    877                     $hooked_block_markup = get_comment_delimited_block_content( $hooked_block_type, array(), '' );
    878                     /** This filter is documented in wp-includes/blocks.php */
    879                     $markup .= apply_filters( 'inject_hooked_block_markup', $hooked_block_markup, $hooked_block_type, $relative_position, $parent, $context );
    880                 }
     903                $markup .= apply_filters( 'inject_hooked_block_markup', $hooked_block_markup, $hooked_block_type, $relative_position, $parent, $context );
    881904            }
    882905        }
  • trunk/tests/phpunit/tests/blocks/blockHooks.php

    r56634 r56673  
    5050            array(
    5151                'block_hooks' => array(
    52                     'tests/hooked-at-before' => 'before',
    53                     'tests/hooked-at-after'  => 'after',
     52                    'tests/hooked-at-before'           => 'before',
     53                    'tests/hooked-at-after'            => 'after',
     54                    'tests/hooked-at-before-and-after' => 'before',
    5455                ),
    5556            )
     
    5960            array(
    6061                'block_hooks' => array(
    61                     'tests/hooked-at-before'      => 'before',
    62                     'tests/hooked-at-after'       => 'after',
    63                     'tests/hooked-at-first-child' => 'first_child',
    64                     'tests/hooked-at-last-child'  => 'last_child',
     62                    'tests/hooked-at-before'           => 'before',
     63                    'tests/hooked-at-after'            => 'after',
     64                    'tests/hooked-at-before-and-after' => 'after',
     65                    'tests/hooked-at-first-child'      => 'first_child',
     66                    'tests/hooked-at-last-child'       => 'last_child',
    6567                ),
    6668            )
     
    9799            'block hooked at the last child position'
    98100        );
     101        $this->assertSame(
     102            array(
     103                'tests/injected-one' => 'before',
     104                'tests/injected-two' => 'after',
     105            ),
     106            get_hooked_blocks( 'tests/hooked-at-before-and-after' ),
     107            'block hooked before one block and after another'
     108        );
     109        $this->assertSame(
     110            array(
     111                'tests/injected-one' => 'before',
     112            ),
     113            get_hooked_blocks( 'tests/hooked-at-before-and-after', 'before' ),
     114            'block hooked before one block and after another, filtered for before'
     115        );
    99116    }
    100117}
Note: See TracChangeset for help on using the changeset viewer.