Make WordPress Core

Changeset 57157


Ignore:
Timestamp:
12/04/2023 08:24:33 PM (5 months ago)
Author:
Bernhard Reiter
Message:

Block Hooks: Store ignored hooked blocks metadata in anchor block.

The biggest tradeoff that was made in the implementation of Block Hooks was that they were limited to layouts (i.e. templates, template parts, and patterns) that didn't have any user modifications (see #59313 for the reason). This changeset is a preparatory step to remove this limitation, so they’ll eventually also work with user-modified layouts.

The crucial problem to solve is how to acknowledge that a user has opted to remove or persist a hooked block, so that the auto-insertion mechanism won't run again and inject an extraneous hooked block on the frontend when none is solicited.

This is achieved by storing all known blocks hooked to a given anchor block in the metadata attribute on that anchor block; specifically in a field called ignoredHookedBlocks inside of the metadata. Hooked blocks are only rendered on the frontend if they're absent from that field; OTOH, they're injected into that field (via the REST API) when first loaded in the editor.

This simple logic guarantees that once a user modifies a given layout, those changes are respected on the frontend; yet if a plugin that includes a hooked block is activated after those modifications have taken place, the hooked block will be rendered on the frontend. This new technique supplants the one previously used (i.e. rendering hooked blocks on the frontend only if a layout doesn't have any modifications) in a rather direct way.

Note that this changeset only introduces the new metadata field and relevant logic; it does not yet enable hooked block insertion into modified layouts. That will be done in a subsequent step (see #59646).

Props gziolo.
Closes #60008.

Location:
trunk
Files:
1 added
3 edited

Legend:

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

    r57120 r57157  
    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.
     764 * If the anchor block has already been processed, and the given hooked block type is in the list
     765 * of ignored hooked blocks, an empty string is returned.
     766 *
     767 * This function is meant for internal use only.
     768 *
     769 * @since 6.5.0
     770 * @access private
     771 *
     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 */
     776function get_hooked_block_markup( &$anchor_block, $hooked_block_type ) {
     777    if ( ! isset( $anchor_block['attrs']['metadata']['ignoredHookedBlocks'] ) ) {
     778        $anchor_block['attrs']['metadata']['ignoredHookedBlocks'] = array();
     779    }
     780
     781    if ( in_array( $hooked_block_type, $anchor_block['attrs']['metadata']['ignoredHookedBlocks'] ) ) {
     782        return '';
     783    }
     784
     785    // The following is only needed for the REST API endpoint.
     786    // However, its presence does not affect the frontend.
     787    $anchor_block['attrs']['metadata']['ignoredHookedBlocks'][] = $hooked_block_type;
     788
     789    return get_comment_delimited_block_content( $hooked_block_type, array(), '' );
     790}
     791
     792/**
    761793 * Returns a function that injects the theme attribute into, and hooked blocks before, a given block.
    762794 *
     
    814846            $hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
    815847            foreach ( $hooked_block_types as $hooked_block_type ) {
    816                 $markup .= get_comment_delimited_block_content( $hooked_block_type, array(), '' );
     848                $markup .= get_hooked_block_markup( $parent_block, $hooked_block_type );
    817849            }
    818850        }
     
    827859        $hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
    828860        foreach ( $hooked_block_types as $hooked_block_type ) {
    829             $markup .= get_comment_delimited_block_content( $hooked_block_type, array(), '' );
     861            $markup .= get_hooked_block_markup( $block, $hooked_block_type );
    830862        }
    831863
     
    875907        $hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
    876908        foreach ( $hooked_block_types as $hooked_block_type ) {
    877             $markup .= get_comment_delimited_block_content( $hooked_block_type, array(), '' );
     909            $markup .= get_hooked_block_markup( $block, $hooked_block_type );
    878910        }
    879911
     
    889921            $hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
    890922            foreach ( $hooked_block_types as $hooked_block_type ) {
    891                 $markup .= get_comment_delimited_block_content( $hooked_block_type, array(), '' );
     923                $markup .= get_hooked_block_markup( $parent_block, $hooked_block_type );
    892924            }
    893925        }
  • trunk/tests/phpunit/tests/blocks/getHookedBlocks.php

    r56805 r57157  
    150150        );
    151151        $this->assertStringContainsString(
    152             '<!-- wp:post-content {"layout":{"type":"constrained"}} /-->'
     152            '<!-- wp:post-content {"layout":{"type":"constrained"},"metadata":{"ignoredHookedBlocks":["tests/hooked-after"]}} /-->'
    153153            . '<!-- wp:tests/hooked-after /-->',
    154154            $template->content
     
    177177        $this->assertStringContainsString(
    178178            '<!-- wp:tests/hooked-before /-->'
    179             . '<!-- wp:navigation {"layout":{"type":"flex","setCascadingProperties":true,"justifyContent":"right"}} /-->',
     179            . '<!-- wp:navigation {"layout":{"type":"flex","setCascadingProperties":true,"justifyContent":"right"},"metadata":{"ignoredHookedBlocks":["tests/hooked-before"]}} /-->',
    180180            $template->content
    181181        );
     
    216216        );
    217217        $this->assertStringContainsString(
    218             '<!-- wp:comments -->'
     218            '<!-- wp:comments {"metadata":{"ignoredHookedBlocks":["tests/hooked-first-child"]}} -->'
    219219            . '<div class="wp-block-comments">'
    220220            . '<!-- wp:tests/hooked-first-child /-->',
  • trunk/tests/phpunit/tests/blocks/wpBlockPatternsRegistry.php

    r57021 r57157  
    382382        $pattern_three['content'] .= '<!-- wp:tests/my-block /-->';
    383383
    384         $expected = array(
    385             $pattern_one,
    386             $pattern_two,
    387             $pattern_three,
    388         );
    389 
    390384        $registered = $this->registry->get_all_registered();
    391         $this->assertSame( $expected, $registered );
     385        $this->assertCount( 3, $registered );
     386        $this->assertStringEndsWith( '<!-- wp:tests/my-block /-->', $registered[1]['content'] );
     387        $this->assertStringContainsString( '"metadata":{"ignoredHookedBlocks":["tests/my-block"]}', $registered[1]['content'] );
     388        $this->assertStringEndsWith( '<!-- wp:tests/my-block /-->', $registered[2]['content'] );
     389        $this->assertStringContainsString( '"metadata":{"ignoredHookedBlocks":["tests/my-block"]}', $registered[2]['content'] );
    392390    }
    393391
     
    445443        $this->registry->register( 'test/two', $pattern_two );
    446444
    447         $pattern_one['name']    = 'test/one';
    448         $pattern_one['content'] = '<!-- wp:tests/my-block /-->' . $pattern_one['content'];
    449 
    450445        $pattern = $this->registry->get_registered( 'test/one' );
    451         $this->assertSame( $pattern_one, $pattern );
     446        $this->assertStringStartsWith( '<!-- wp:tests/my-block /-->', $pattern['content'] );
     447        $this->assertStringContainsString( '"metadata":{"ignoredHookedBlocks":["tests/my-block"]}', $pattern['content'] );
    452448    }
    453449
Note: See TracChangeset for help on using the changeset viewer.