Make WordPress Core


Ignore:
Timestamp:
09/30/2024 12:21:31 PM (2 years ago)
Author:
Bernhard Reiter
Message:

Block Hooks: Respect "multiple": false in hooked blocks.

If a prospective hooked block has its multiple block-supports field set to false (thus allowing only one instance of the block to be present), ensure that:

  1. Only one instance of the block will be inserted if it's not yet present in the current context.
  2. The block will not be inserted at all if an instance of it is already present in the current context.

As always in Block Hooks parlance, "context" denotes the containing template, template part, pattern, or navigation post that a hooked block is supposed to be inserted into.

The markup of a webpage that uses a Block Theme typically comprises a number of such contexts -- one template and any number of template parts, patterns, and navigation posts. Note that the limitation imposed by this changeset only applies on a per-context basis, so it's still possible that the resulting page contains more than one instance of a hooked block with "multiple": false set, as each context could contribute up to one such instance.

Props bernhard-reiter, jonsurrell, gziolo.
Fixes #61902.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/blocks/applyBlockHooksToContent.php

    r59101 r59124  
    2828                        )
    2929                );
     30
     31                register_block_type(
     32                        'tests/hooked-block-with-multiple-false',
     33                        array(
     34                                'block_hooks' => array(
     35                                        'tests/other-anchor-block' => 'after',
     36                                ),
     37                                'supports'    => array(
     38                                        'multiple' => false,
     39                                ),
     40                        )
     41                );
     42
     43                register_block_type(
     44                        'tests/dynamically-hooked-block-with-multiple-false',
     45                        array(
     46                                'supports' => array(
     47                                        'multiple' => false,
     48                                ),
     49                        )
     50                );
    3051        }
    3152
    … …  
    3960
    4061                $registry->unregister( 'tests/hooked-block' );
     62                $registry->unregister( 'tests/hooked-block-with-multiple-false' );
     63                $registry->unregister( 'tests/dynamically-hooked-block-with-multiple-false' );
    4164        }
    4265
    … …  
    6891                );
    6992        }
     93
     94        /**
     95         * @ticket 61902
     96         */
     97        public function test_apply_block_hooks_to_content_respect_multiple_false() {
     98                $context          = new WP_Block_Template();
     99                $context->content = '<!-- wp:tests/hooked-block-with-multiple-false /--><!-- wp:tests/other-anchor-block /-->';
     100
     101                $actual = apply_block_hooks_to_content( $context->content, $context, 'insert_hooked_blocks' );
     102                $this->assertSame(
     103                        '<!-- wp:tests/hooked-block-with-multiple-false /--><!-- wp:tests/other-anchor-block /-->',
     104                        $actual
     105                );
     106        }
     107
     108        /**
     109         * @ticket 61902
     110         */
     111        public function test_apply_block_hooks_to_content_respect_multiple_false_after_inserting_once() {
     112                $context          = new WP_Block_Template();
     113                $context->content = '<!-- wp:tests/other-anchor-block /--><!-- wp:tests/other-block /--><!-- wp:tests/other-anchor-block /-->';
     114
     115                $actual = apply_block_hooks_to_content( $context->content, $context, 'insert_hooked_blocks' );
     116                $this->assertSame(
     117                        '<!-- wp:tests/other-anchor-block /--><!-- wp:tests/hooked-block-with-multiple-false /--><!-- wp:tests/other-block /--><!-- wp:tests/other-anchor-block /-->',
     118                        $actual
     119                );
     120        }
     121
     122        /**
     123         * @ticket 61902
     124         */
     125        public function test_apply_block_hooks_to_content_respect_multiple_false_with_filter() {
     126                $filter = function ( $hooked_block_types, $relative_position, $anchor_block_type ) {
     127                        if ( 'tests/yet-another-anchor-block' === $anchor_block_type && 'after' === $relative_position ) {
     128                                $hooked_block_types[] = 'tests/dynamically-hooked-block-with-multiple-false';
     129                        }
     130
     131                        return $hooked_block_types;
     132                };
     133
     134                $context          = new WP_Block_Template();
     135                $context->content = '<!-- wp:tests/dynamically-hooked-block-with-multiple-false /--><!-- wp:tests/yet-another-anchor-block /-->';
     136
     137                add_filter( 'hooked_block_types', $filter, 10, 3 );
     138                $actual = apply_block_hooks_to_content( $context->content, $context, 'insert_hooked_blocks' );
     139                remove_filter( 'hooked_block_types', $filter, 10 );
     140
     141                $this->assertSame(
     142                        '<!-- wp:tests/dynamically-hooked-block-with-multiple-false /--><!-- wp:tests/yet-another-anchor-block /-->',
     143                        $actual
     144                );
     145        }
     146
     147        /**
     148         * @ticket 61902
     149         */
     150        public function test_apply_block_hooks_to_content_respect_multiple_false_after_inserting_once_with_filter() {
     151                $filter = function ( $hooked_block_types, $relative_position, $anchor_block_type ) {
     152                        if ( 'tests/yet-another-anchor-block' === $anchor_block_type && 'after' === $relative_position ) {
     153                                $hooked_block_types[] = 'tests/dynamically-hooked-block-with-multiple-false';
     154                        }
     155
     156                        return $hooked_block_types;
     157                };
     158
     159                $context          = new WP_Block_Template();
     160                $context->content = '<!-- wp:tests/yet-another-anchor-block /--><!-- wp:tests/other-block /--><!-- wp:tests/yet-another-anchor-block /-->';
     161
     162                add_filter( 'hooked_block_types', $filter, 10, 3 );
     163                $actual = apply_block_hooks_to_content( $context->content, $context, 'insert_hooked_blocks' );
     164                remove_filter( 'hooked_block_types', $filter, 10 );
     165
     166                $this->assertSame(
     167                        '<!-- wp:tests/yet-another-anchor-block /--><!-- wp:tests/dynamically-hooked-block-with-multiple-false /--><!-- wp:tests/other-block /--><!-- wp:tests/yet-another-anchor-block /-->',
     168                        $actual
     169                );
     170        }
    70171}
Note: See TracChangeset for help on using the changeset viewer.