Make WordPress Core

Changeset 56618


Ignore:
Timestamp:
09/19/2023 12:34:50 PM (9 months ago)
Author:
Bernhard Reiter
Message:

Blocks: Implement block insertion functions.

For #59313, we need to implement functions to insert a given parsed block into another parsed block's inner blocks, and to prepend and append to that array, respectively.

We will use those functions in combination with traverse_and_serialize_blocks (see #59327) to implement automatic insertion of hooked blocks into block templates and patterns.

Props gziolo.
Fixes #59385.

Location:
trunk
Files:
2 edited

Legend:

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

    r56610 r56618  
    762762
    763763/**
     764 * Insert a parsed block into a parent block's inner blocks.
     765 *
     766 * Given a parsed block, a block index, and a chunk index, insert another parsed block
     767 * into the parent block at the given indices.
     768 *
     769 * Note that the this mutates the parent block by inserting into the parent's `innerBlocks`
     770 * array, and by updating the parent's `innerContent` array accordingly.
     771 *
     772 * @since 6.4.0
     773 *
     774 * @param array $parent_block   The parent block.
     775 * @param int   $block_index    The index specifying the insertion position among the parent block's inner blocks.
     776 * @param int   $chunk_index    The index specifying the insertion position among the parent block's inner content chunks.
     777 * @param array $inserted_block The block to insert.
     778 * @return void
     779 */
     780function insert_inner_block( &$parent_block, $block_index, $chunk_index, $inserted_block ) {
     781    array_splice( $parent_block['innerBlocks'], $block_index, 0, array( $inserted_block ) );
     782
     783    /*
     784     * Since WP_Block::render() iterates over `inner_content` (rather than `inner_blocks`)
     785     * when rendering blocks, we also need to insert a value (`null`, to mark a block
     786     * location) into that array.
     787     */
     788    array_splice( $parent_block['innerContent'], $chunk_index, 0, array( null ) );
     789}
     790
     791/**
     792 * Prepend a parsed block to a parent block's inner blocks.
     793 *
     794 * Given a parsed block, prepend another parsed block to the parent block's inner blocks.
     795 *
     796 * Note that the this mutates the parent block by inserting into the parent's `innerBlocks`
     797 * array, and by updating the parent's `innerContent` array accordingly.
     798 *
     799 * @since 6.4.0
     800 *
     801 * @param array  $parent_block   The parent block.
     802 * @param array  $inserted_block The block to insert.
     803 * @return void
     804 */
     805function prepend_inner_block( &$parent_block, $inserted_block ) {
     806    $chunk_index = 0;
     807    for ( $index = 0; $index < count( $parent_block['innerContent'] ); $index++ ) {
     808        if ( is_null( $parent_block['innerContent'][ $index ] ) ) {
     809            $chunk_index = $index;
     810            break;
     811        }
     812    }
     813    insert_inner_block( $parent_block, 0, $chunk_index, $inserted_block );
     814}
     815
     816/**
     817 * Append a parsed block to a parent block's inner blocks.
     818 *
     819 * Given a parsed block, append another parsed block to the parent block's inner blocks.
     820 *
     821 * Note that the this mutates the parent block by inserting into the parent's `innerBlocks`
     822 * array, and by updating the parent's `innerContent` array accordingly.
     823 *
     824 * @since 6.4.0
     825 *
     826 * @param array  $parent_block   The parent block.
     827 * @param array  $inserted_block The block to insert.
     828 * @return void
     829 */
     830function append_inner_block( &$parent_block, $inserted_block ) {
     831    $chunk_index = count( $parent_block['innerContent'] );
     832    for ( $index = count( $parent_block['innerContent'] ); $index > 0; $index-- ) {
     833        if ( is_null( $parent_block['innerContent'][ $index - 1 ] ) ) {
     834            $chunk_index = $index;
     835            break;
     836        }
     837    }
     838    insert_inner_block( $parent_block, count( $parent_block['innerBlocks'] ), $chunk_index, $inserted_block );
     839}
     840
     841/**
    764842 * Given an array of attributes, returns a string in the serialized attributes
    765843 * format prepared for post content.
  • trunk/tests/phpunit/tests/blocks/blockHooks.php

    r56610 r56618  
    1818     */
    1919    public function tear_down() {
    20         $registry = WP_Block_Type_Registry::get_instance();
    21 
    22         foreach ( array( 'tests/my-block', 'tests/my-container-block' ) as $block_name ) {
     20        $registry    = WP_Block_Type_Registry::get_instance();
     21        $block_names = array(
     22            'tests/injected-one',
     23            'tests/injected-two',
     24        );
     25        foreach ( $block_names as $block_name ) {
    2326            if ( $registry->is_registered( $block_name ) ) {
    2427                $registry->unregister( $block_name );
     
    98101        );
    99102    }
     103
     104    /**
     105     * @ticket 59385
     106     *
     107     * @covers ::insert_inner_block
     108     *
     109     * @dataProvider data_insert_inner_block
     110     *
     111     * @param string $block_index     Block index to insert the block at.
     112     * @param string $expected_markup Expected markup after the block is inserted.
     113     */
     114    public function test_insert_inner_block( $block_index, $expected_markup ) {
     115        $original_markup = <<<HTML
     116<!-- wp:tests/group {"layout":{"type":"constrained"}} -->
     117    <div class="wp-block-group">
     118        <!-- wp:paragraph -->
     119            <p>Foo</p>
     120        <!-- /wp:paragraph -->
     121    </div>
     122<!-- /wp:tests/group -->
     123HTML;
     124
     125        $inserted_block = array(
     126            'blockName'    => 'tests/hooked-block',
     127            'attrs'        => array(),
     128            'innerBlocks'  => array(),
     129            'innerHTML'    => '',
     130            'innerContent' => array(),
     131        );
     132
     133        $expected = parse_blocks( $expected_markup )[0];
     134        $block    = parse_blocks( $original_markup )[0];
     135        insert_inner_block( $block, $block_index, 1, $inserted_block );
     136        $this->assertSame( $expected, $block );
     137    }
     138
     139    /**
     140     * Data provider.
     141     *
     142     * @return array[]
     143     */
     144    public function data_insert_inner_block() {
     145        $expected_before_markup = <<<HTML
     146<!-- wp:tests/group {"layout":{"type":"constrained"}} -->
     147    <div class="wp-block-group">
     148        <!-- wp:tests/hooked-block /--><!-- wp:paragraph -->
     149            <p>Foo</p>
     150        <!-- /wp:paragraph -->
     151    </div>
     152<!-- /wp:tests/group -->
     153HTML;
     154
     155        $expected_after_markup = <<<HTML
     156<!-- wp:tests/group {"layout":{"type":"constrained"}} -->
     157    <div class="wp-block-group">
     158        <!-- wp:paragraph -->
     159            <p>Foo</p>
     160        <!-- /wp:paragraph --><!-- wp:tests/hooked-block /-->
     161    </div>
     162<!-- /wp:tests/group -->
     163HTML;
     164
     165        return array(
     166            'insert before given block' => array(
     167                'block_index'     => 0,
     168                'expected_markup' => $expected_before_markup,
     169            ),
     170            'insert after given block'  => array(
     171                'block_index'     => 1,
     172                'expected_markup' => $expected_after_markup,
     173            ),
     174        );
     175    }
     176
     177    /**
     178     * @ticket 59385
     179     *
     180     * @covers ::prepend_inner_block
     181     */
     182    public function test_prepend_inner_block() {
     183        $original_markup = <<<HTML
     184<!-- wp:tests/group {"layout":{"type":"constrained"}} -->
     185    <div class="wp-block-group">
     186        <!-- wp:paragraph -->
     187            <p>Foo</p>
     188        <!-- /wp:paragraph -->
     189    </div>
     190<!-- /wp:tests/group -->
     191HTML;
     192
     193        $inserted_block = array(
     194            'blockName'    => 'tests/hooked-block',
     195            'attrs'        => array(),
     196            'innerBlocks'  => array(),
     197            'innerHTML'    => '',
     198            'innerContent' => array(),
     199        );
     200
     201        $expected_markup = <<<HTML
     202<!-- wp:tests/group {"layout":{"type":"constrained"}} -->
     203    <div class="wp-block-group">
     204        <!-- wp:tests/hooked-block /--><!-- wp:paragraph -->
     205            <p>Foo</p>
     206        <!-- /wp:paragraph -->
     207    </div>
     208<!-- /wp:tests/group -->
     209HTML;
     210
     211        $expected = parse_blocks( $expected_markup )[0];
     212        $block    = parse_blocks( $original_markup )[0];
     213        prepend_inner_block( $block, $inserted_block );
     214        $this->assertSame( $expected, $block );
     215    }
     216
     217    /**
     218     * @ticket 59385
     219     *
     220     * @covers ::append_inner_block
     221     */
     222    public function test_append_inner_block() {
     223        $original_markup = <<<HTML
     224<!-- wp:tests/group {"layout":{"type":"constrained"}} -->
     225    <div class="wp-block-group">
     226        <!-- wp:paragraph -->
     227            <p>Foo</p>
     228        <!-- /wp:paragraph -->
     229    </div>
     230<!-- /wp:tests/group -->
     231HTML;
     232
     233        $inserted_block = array(
     234            'blockName'    => 'tests/hooked-block',
     235            'attrs'        => array(),
     236            'innerBlocks'  => array(),
     237            'innerHTML'    => '',
     238            'innerContent' => array(),
     239        );
     240
     241        $expected_markup = <<<HTML
     242<!-- wp:tests/group {"layout":{"type":"constrained"}} -->
     243    <div class="wp-block-group">
     244        <!-- wp:paragraph -->
     245            <p>Foo</p>
     246        <!-- /wp:paragraph --><!-- wp:tests/hooked-block /-->
     247    </div>
     248<!-- /wp:tests/group -->
     249HTML;
     250
     251        $expected = parse_blocks( $expected_markup )[0];
     252        $block    = parse_blocks( $original_markup )[0];
     253        append_inner_block( $block, $inserted_block );
     254        $this->assertSame( $expected, $block );
     255    }
    100256}
Note: See TracChangeset for help on using the changeset viewer.