Make WordPress Core

Changeset 56618


Ignore:
Timestamp:
09/19/2023 12:34:50 PM (3 years 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.