Make WordPress Core

Changeset 58291


Ignore:
Timestamp:
06/03/2024 12:03:53 PM (10 months ago)
Author:
Bernhard Reiter
Message:

Block Hooks: Move ignoredHookedBlocks metadata injection logic.

As of [57790], the Templates endpoint uses the rest_pre_insert_* filter to inject the ignoredHookedBlocks metadata attribute into anchor blocks, prior to persisting a template or template part to the database. The same principle was implemented for the Navigation endpoint (where additionally, first and last child blocks added at the top level are store in the wp_navigation post object's post meta). The required logic was added to the Navigation block's code, i.e. inside the Gutenberg code repository, and then synchronized to Core.

In order to harmonize the code between the two endpoints, this changeset introduces a new update_ignored_hooked_blocks_postmeta function, which is based on the Navigation block's block_core_navigation_update_ignore_hooked_blocks_meta, alongside a few helper functions, and hooks it to the rest_pre_insert_wp_navigation filter hook. (The Navigation block has been prepared in [58275] to add an additional conditional to check for the new update_ignored_hooked_blocks_postmeta filter so there won't be any collisions.)

Eventually, this will allow to deprecate block_core_navigation_update_ignore_hooked_blocks_meta (and some related functions), and remove the relevant code from the Navigation block. It also paves the way for some other future changes, such as inserting a hooked block as a Template Part block's first or last child (#60854).

Props tomjcafferkey, bernhard-reiter.
Fixes #60759.

Location:
trunk
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/block-template-utils.php

    r58268 r58291  
    16001600    }
    16011601
    1602     $before_block_visitor = make_before_block_visitor( $hooked_blocks, $template, 'set_ignored_hooked_blocks_metadata' );
    1603     $after_block_visitor  = make_after_block_visitor( $hooked_blocks, $template, 'set_ignored_hooked_blocks_metadata' );
    1604 
    1605     $blocks                = parse_blocks( $changes->post_content );
    1606     $changes->post_content = traverse_and_serialize_blocks( $blocks, $before_block_visitor, $after_block_visitor );
     1602    $changes->post_content = apply_block_hooks_to_content( $changes->post_content, $template, 'set_ignored_hooked_blocks_metadata' );
    16071603
    16081604    return $changes;
  • trunk/src/wp-includes/blocks.php

    r58247 r58291  
    10041004
    10051005/**
     1006 * Runs the hooked blocks algorithm on the given content.
     1007 *
     1008 * @since 6.6.0
     1009 * @access private
     1010 *
     1011 * @param string $content Serialized content.
     1012 * @param WP_Block_Template|WP_Post|array $context       A block template, template part, `wp_navigation` post object,
     1013 *                                                       or pattern that the blocks belong to.
     1014 * @param callable                        $callback      A function that will be called for each block to generate
     1015 *                                                       the markup for a given list of blocks that are hooked to it.
     1016 *                                                       Default: 'insert_hooked_blocks'.
     1017 * @return string The serialized markup.
     1018 */
     1019function apply_block_hooks_to_content( $content, $context, $callback = 'insert_hooked_blocks' ) {
     1020    $hooked_blocks = get_hooked_blocks();
     1021    if ( empty( $hooked_blocks ) && ! has_filter( 'hooked_block_types' ) ) {
     1022        return $content;
     1023    }
     1024
     1025    $blocks = parse_blocks( $content );
     1026
     1027    $before_block_visitor = make_before_block_visitor( $hooked_blocks, $context, $callback );
     1028    $after_block_visitor  = make_after_block_visitor( $hooked_blocks, $context, $callback );
     1029
     1030    return traverse_and_serialize_blocks( $blocks, $before_block_visitor, $after_block_visitor );
     1031}
     1032
     1033/**
     1034 * Accepts the serialized markup of a block and its inner blocks, and returns serialized markup of the inner blocks.
     1035 *
     1036 * @since 6.6.0
     1037 * @access private
     1038 *
     1039 * @param string $serialized_block The serialized markup of a block and its inner blocks.
     1040 * @return string The serialized markup of the inner blocks.
     1041 */
     1042function remove_serialized_parent_block( $serialized_block ) {
     1043    $start = strpos( $serialized_block, '-->' ) + strlen( '-->' );
     1044    $end   = strrpos( $serialized_block, '<!--' );
     1045    return substr( $serialized_block, $start, $end - $start );
     1046}
     1047
     1048/**
     1049 * Updates the wp_postmeta with the list of ignored hooked blocks where the inner blocks are stored as post content.
     1050 * Currently only supports `wp_navigation` post types.
     1051 *
     1052 * @since 6.6.0
     1053 * @access private
     1054 *
     1055 * @param stdClass $post Post object.
     1056 * @return stdClass The updated post object.
     1057 */
     1058function update_ignored_hooked_blocks_postmeta( $post ) {
     1059    /*
     1060     * In this scenario the user has likely tried to create a navigation via the REST API.
     1061     * In which case we won't have a post ID to work with and store meta against.
     1062     */
     1063    if ( empty( $post->ID ) ) {
     1064        return $post;
     1065    }
     1066
     1067    /**
     1068     * Skip meta generation when consumers intentionally update specific Navigation fields
     1069     * and omit the content update.
     1070     */
     1071    if ( ! isset( $post->post_content ) ) {
     1072        return $post;
     1073    }
     1074
     1075    /**
     1076     * Skip meta generation when the post content is not a navigation block.
     1077     */
     1078    if ( ! isset( $post->post_type ) || 'wp_navigation' !== $post->post_type ) {
     1079        return $post;
     1080    }
     1081
     1082    $attributes = array();
     1083
     1084    $ignored_hooked_blocks = get_post_meta( $post->ID, '_wp_ignored_hooked_blocks', true );
     1085    if ( ! empty( $ignored_hooked_blocks ) ) {
     1086        $ignored_hooked_blocks  = json_decode( $ignored_hooked_blocks, true );
     1087        $attributes['metadata'] = array(
     1088            'ignoredHookedBlocks' => $ignored_hooked_blocks,
     1089        );
     1090    }
     1091
     1092    $markup = get_comment_delimited_block_content(
     1093        'core/navigation',
     1094        $attributes,
     1095        $post->post_content
     1096    );
     1097
     1098    $serialized_block = apply_block_hooks_to_content( $markup, get_post( $post->ID ), 'set_ignored_hooked_blocks_metadata' );
     1099    $root_block       = parse_blocks( $serialized_block )[0];
     1100
     1101    $ignored_hooked_blocks = isset( $root_block['attrs']['metadata']['ignoredHookedBlocks'] )
     1102        ? $root_block['attrs']['metadata']['ignoredHookedBlocks']
     1103        : array();
     1104
     1105    if ( ! empty( $ignored_hooked_blocks ) ) {
     1106        $existing_ignored_hooked_blocks = get_post_meta( $post->ID, '_wp_ignored_hooked_blocks', true );
     1107        if ( ! empty( $existing_ignored_hooked_blocks ) ) {
     1108            $existing_ignored_hooked_blocks = json_decode( $existing_ignored_hooked_blocks, true );
     1109            $ignored_hooked_blocks          = array_unique( array_merge( $ignored_hooked_blocks, $existing_ignored_hooked_blocks ) );
     1110        }
     1111        update_post_meta( $post->ID, '_wp_ignored_hooked_blocks', json_encode( $ignored_hooked_blocks ) );
     1112    }
     1113
     1114    $post->post_content = remove_serialized_parent_block( $serialized_block );
     1115    return $post;
     1116}
     1117
     1118/*
    10061119 * Returns the markup for blocks hooked to the given anchor block in a specific relative position and then
    10071120 * adds a list of hooked block types to an anchor block's ignored hooked block types.
    10081121 *
    10091122 * This function is meant for internal use only.
    1010  *
    1011  * @since 6.6.0
    1012  * @access private
    10131123 *
    10141124 * @param array                           $parsed_anchor_block The anchor block, in parsed block array format.
     
    10201130 */
    10211131function insert_hooked_blocks_and_set_ignored_hooked_blocks_metadata( &$parsed_anchor_block, $relative_position, $hooked_blocks, $context ) {
    1022     $markup = insert_hooked_blocks( $parsed_anchor_block, $relative_position, $hooked_blocks, $context );
     1132    $markup  = insert_hooked_blocks( $parsed_anchor_block, $relative_position, $hooked_blocks, $context );
    10231133    $markup .= set_ignored_hooked_blocks_metadata( $parsed_anchor_block, $relative_position, $hooked_blocks, $context );
    10241134
  • trunk/src/wp-includes/default-filters.php

    r57920 r58291  
    758758add_filter( 'rest_pre_insert_wp_template_part', 'inject_ignored_hooked_blocks_metadata_attributes' );
    759759
     760// Update ignoredHookedBlocks postmeta for wp_navigation post type.
     761add_filter( 'rest_pre_insert_wp_navigation', 'update_ignored_hooked_blocks_postmeta' );
     762
    760763unset( $filter, $action );
Note: See TracChangeset for help on using the changeset viewer.