Make WordPress Core


Ignore:
Timestamp:
01/25/2024 01:46:49 PM (9 months ago)
Author:
Bernhard Reiter
Message:

Block Hooks: Introduce a new hooked_block_{$block_type} filter.

Add a new hooked_block_{$block_type} filter that allows modifying a hooked block (in parsed block format) prior to insertion, while providing read access to its anchor block (in the same format).

This allows block authors to e.g. set a hooked block's attributes, or its inner blocks; the filter can peruse information about the anchor block when doing so. As such, this filter provides a solution to both #59572 and #60126.

The new filter is designed to strike a good balance and separation of concerns with regard to the existing `hooked_block_types` filter, which allows addition or removal of a block to the list of hooked blocks for a given anchor block -- all of which are identified only by their block types. This new filter, on the other hand, only applies to one hooked block at a time, and allows modifying the entire (parsed) hooked block; it also gives (read) access to the parsed anchor block.

Props gziolo, tomjcafferkey, andrewserong, isabel_brison, timbroddin, yansern.
Fixes #59572, #60126.

File:
1 edited

Legend:

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

    r57157 r57354  
    759759
    760760/**
    761  * Conditionally returns the markup for a given hooked block type.
    762  *
    763  * Accepts two arguments: A reference to an anchor block, and the name of a hooked block type.
     761 * Conditionally returns the markup for a given hooked block.
     762 *
     763 * Accepts three arguments: A hooked block, its type, and a reference to an anchor block.
    764764 * If the anchor block has already been processed, and the given hooked block type is in the list
    765765 * of ignored hooked blocks, an empty string is returned.
    766766 *
     767 * The hooked block type is specified separately as it's possible that a filter might've modified
     768 * the hooked block such that `$hooked_block['blockName']` does no longer reflect the original type.
     769 *
    767770 * This function is meant for internal use only.
    768771 *
     
    770773 * @access private
    771774 *
    772  * @param array   $anchor_block      The anchor block. Passed by reference.
    773  * @param string  $hooked_block_type The name of the hooked block type.
    774  * @return string The markup for the given hooked block type, or an empty string if the block is ignored.
    775  */
    776 function get_hooked_block_markup( &$anchor_block, $hooked_block_type ) {
     775 * @param array  $hooked_block      The hooked block, represented as a parsed block array.
     776 * @param string $hooked_block_type The type of the hooked block. This could be different from
     777 *                                  $hooked_block['blockName'], as a filter might've modified the latter.
     778 * @param array  $anchor_block      The anchor block, represented as a parsed block array.
     779 *                                  Passed by reference.
     780 * @return string The markup for the given hooked block, or an empty string if the block is ignored.
     781 */
     782function get_hooked_block_markup( $hooked_block, $hooked_block_type, &$anchor_block ) {
    777783    if ( ! isset( $anchor_block['attrs']['metadata']['ignoredHookedBlocks'] ) ) {
    778784        $anchor_block['attrs']['metadata']['ignoredHookedBlocks'] = array();
     
    787793    $anchor_block['attrs']['metadata']['ignoredHookedBlocks'][] = $hooked_block_type;
    788794
    789     return get_comment_delimited_block_content( $hooked_block_type, array(), '' );
     795    return serialize_block( $hooked_block );
     796}
     797
     798/**
     799 * Returns the markup for blocks hooked to the given anchor block in a specific relative position.
     800 *
     801 * @since 6.5.0
     802 * @access private
     803 *
     804 * @param array                   $parsed_anchor_block The anchor block, in parsed block array format.
     805 * @param string                  $relative_position   The relative position of the hooked blocks.
     806 *                                                     Can be one of 'before', 'after', 'first_child', or 'last_child'.
     807 * @param array                   $hooked_blocks       An array of hooked block types, grouped by anchor block and relative position.
     808 * @param WP_Block_Template|array $context             The block template, template part, or pattern that the anchor block belongs to.
     809 * @return string
     810 */
     811function insert_hooked_blocks( &$parsed_anchor_block, $relative_position, $hooked_blocks, $context ) {
     812    $anchor_block_type  = $parsed_anchor_block['blockName'];
     813    $hooked_block_types = isset( $hooked_blocks[ $anchor_block_type ][ $relative_position ] )
     814        ? $hooked_blocks[ $anchor_block_type ][ $relative_position ]
     815        : array();
     816
     817    /**
     818     * Filters the list of hooked block types for a given anchor block type and relative position.
     819     *
     820     * @since 6.4.0
     821     *
     822     * @param string[]                $hooked_block_types The list of hooked block types.
     823     * @param string                  $relative_position  The relative position of the hooked blocks.
     824     *                                                    Can be one of 'before', 'after', 'first_child', or 'last_child'.
     825     * @param string                  $anchor_block_type  The anchor block type.
     826     * @param WP_Block_Template|array $context            The block template, template part, or pattern that the anchor block belongs to.
     827     */
     828    $hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
     829
     830    $markup = '';
     831    foreach ( $hooked_block_types as $hooked_block_type ) {
     832        $parsed_hooked_block = array(
     833            'blockName'    => $hooked_block_type,
     834            'attrs'        => array(),
     835            'innerBlocks'  => array(),
     836            'innerContent' => array(),
     837        );
     838
     839        /**
     840         * Filters the parsed block array for a given hooked block.
     841         *
     842         * @since 6.5.0
     843         *
     844         * @param array                   $parsed_hooked_block The parsed block array for the given hooked block type.
     845         * @param string                  $relative_position   The relative position of the hooked block.
     846         * @param array                   $parsed_anchor_block The anchor block, in parsed block array format.
     847         * @param WP_Block_Template|array $context             The block template, template part, or pattern that the anchor block belongs to.
     848         */
     849        $parsed_hooked_block = apply_filters( "hooked_block_{$hooked_block_type}", $parsed_hooked_block, $relative_position, $parsed_anchor_block, $context );
     850
     851        // It's possible that the `hooked_block_{$hooked_block_type}` filter returned a block of a different type,
     852        // so we need to pass the original $hooked_block_type as well.
     853        $markup .= get_hooked_block_markup( $parsed_hooked_block, $hooked_block_type, $parsed_anchor_block );
     854    }
     855
     856    return $markup;
    790857}
    791858
     
    827894        if ( $parent_block && ! $prev ) {
    828895            // Candidate for first-child insertion.
    829             $relative_position  = 'first_child';
    830             $anchor_block_type  = $parent_block['blockName'];
    831             $hooked_block_types = isset( $hooked_blocks[ $anchor_block_type ][ $relative_position ] )
    832                 ? $hooked_blocks[ $anchor_block_type ][ $relative_position ]
    833                 : array();
    834 
    835             /**
    836              * Filters the list of hooked block types for a given anchor block type and relative position.
    837              *
    838              * @since 6.4.0
    839              *
    840              * @param string[]                $hooked_block_types  The list of hooked block types.
    841              * @param string                  $relative_position   The relative position of the hooked blocks.
    842              *                                                     Can be one of 'before', 'after', 'first_child', or 'last_child'.
    843              * @param string                  $anchor_block_type   The anchor block type.
    844              * @param WP_Block_Template|array $context             The block template, template part, or pattern that the anchor block belongs to.
    845              */
    846             $hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
    847             foreach ( $hooked_block_types as $hooked_block_type ) {
    848                 $markup .= get_hooked_block_markup( $parent_block, $hooked_block_type );
    849             }
    850         }
    851 
    852         $relative_position  = 'before';
    853         $anchor_block_type  = $block['blockName'];
    854         $hooked_block_types = isset( $hooked_blocks[ $anchor_block_type ][ $relative_position ] )
    855             ? $hooked_blocks[ $anchor_block_type ][ $relative_position ]
    856             : array();
    857 
    858         /** This filter is documented in wp-includes/blocks.php */
    859         $hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
    860         foreach ( $hooked_block_types as $hooked_block_type ) {
    861             $markup .= get_hooked_block_markup( $block, $hooked_block_type );
    862         }
     896            $markup .= insert_hooked_blocks( $parent_block, 'first_child', $hooked_blocks, $context );
     897        }
     898
     899        $markup .= insert_hooked_blocks( $block, 'before', $hooked_blocks, $context );
    863900
    864901        return $markup;
     
    896933     */
    897934    return function ( &$block, &$parent_block = null, $next = null ) use ( $hooked_blocks, $context ) {
    898         $markup = '';
    899 
    900         $relative_position  = 'after';
    901         $anchor_block_type  = $block['blockName'];
    902         $hooked_block_types = isset( $hooked_blocks[ $anchor_block_type ][ $relative_position ] )
    903                 ? $hooked_blocks[ $anchor_block_type ][ $relative_position ]
    904                 : array();
    905 
    906         /** This filter is documented in wp-includes/blocks.php */
    907         $hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
    908         foreach ( $hooked_block_types as $hooked_block_type ) {
    909             $markup .= get_hooked_block_markup( $block, $hooked_block_type );
    910         }
     935        $markup = insert_hooked_blocks( $block, 'after', $hooked_blocks, $context );
    911936
    912937        if ( $parent_block && ! $next ) {
    913938            // Candidate for last-child insertion.
    914             $relative_position  = 'last_child';
    915             $anchor_block_type  = $parent_block['blockName'];
    916             $hooked_block_types = isset( $hooked_blocks[ $anchor_block_type ][ $relative_position ] )
    917                 ? $hooked_blocks[ $anchor_block_type ][ $relative_position ]
    918                 : array();
    919 
    920             /** This filter is documented in wp-includes/blocks.php */
    921             $hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
    922             foreach ( $hooked_block_types as $hooked_block_type ) {
    923                 $markup .= get_hooked_block_markup( $parent_block, $hooked_block_type );
    924             }
     939            $markup .= insert_hooked_blocks( $parent_block, 'last_child', $hooked_blocks, $context );
    925940        }
    926941
Note: See TracChangeset for help on using the changeset viewer.