Make WordPress Core


Ignore:
Timestamp:
09/30/2024 12:21:31 PM (10 months 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.