Make WordPress Core

09/21/2023 04:16:05 PM (5 months ago)
Bernhard Reiter

Blocks: Implement automatic block insertion into Block Hooks.

Block Hooks allow a third-party block to specify a position relative to a given block into which it will then be automatically inserted (e.g. a "Like" button block can ask to be inserted after the Post Content block, or an eCommerce shopping cart block can ask to be inserted after the Navigation block).

The underlying idea is to provide an extensibility mechanism for Block Themes, in analogy to WordPress' Hooks concept that has allowed extending Classic Themes through filters and actions.

The two core tenets for Block Hooks are:

  1. Insertion into the frontend should happen right after a plugin containing a hooked block is activated (i.e. the user isn't required to insert the block manually in the editor first); similarly, disabling the plugin should remove the hooked block from the frontend.
  2. The user has the ultimate power to customize that automatic insertion: The hooked block is also visible in the editor, and the user's decision to persist, dismiss (i.e. remove), customize, or move it will be respected (and reflected on the frontend).

To account for both tenets, the tradeoff was made to limit automatic block insertion to unmodified templates (and template parts, respectively). The reason for this is that the simplest way of storing the information whether a block has been persisted to (or dismissed from) a given template (or part) is right in the template markup.

To accommodate for that tradeoff, UI controls (toggles) are being added to increase visibility of hooked blocks, and to allow for their later insertion into templates (or parts) that already have been modified by the user.

For hooked blocks to appear both in the frontend and in the editor (see tenet number 2), they need to be inserted into both the frontend markup and the REST API (templates and patterns endpoints) equally. As a consequence, this means that automatic insertion couldn't (only) be implemented at block render stage, as for the editor, the serialized (but unrendered) markup needs to be modified.

Furthermore, hooked blocks also have to be inserted into block patterns. Since practically no filters exist for the patterns registry, this has to be done in the registry's get_registered and get_all_registered methods.

Props gziolo.
Fixes #59313.

1 edited


  • trunk/src/wp-includes/class-wp-block-patterns-registry.php

    r55693 r56649  
    166166        }
    168         return $this->registered_patterns[ $pattern_name ];
     168        $pattern              = $this->registered_patterns[ $pattern_name ];
     169        $blocks               = parse_blocks( $pattern['content'] );
     170        $before_block_visitor = make_before_block_visitor( $pattern );
     171        $after_block_visitor  = make_after_block_visitor( $pattern );
     172        $pattern['content']   = traverse_and_serialize_blocks( $blocks, $before_block_visitor, $after_block_visitor );
     174        return $pattern;
    169175    }
    179185     */
    180186    public function get_all_registered( $outside_init_only = false ) {
    181         return array_values(
     187        $patterns = array_values(
    182188            $outside_init_only
    183189                ? $this->registered_patterns_outside_init
    184190                : $this->registered_patterns
    185191        );
     193        foreach ( $patterns as $index => $pattern ) {
     194            $blocks                        = parse_blocks( $pattern['content'] );
     195            $before_block_visitor          = make_before_block_visitor( $pattern );
     196            $after_block_visitor           = make_after_block_visitor( $pattern );
     197            $patterns[ $index ]['content'] = traverse_and_serialize_blocks( $blocks, $before_block_visitor, $after_block_visitor );
     198        }
     199        return $patterns;
    186200    }
Note: See TracChangeset for help on using the changeset viewer.