Make WordPress Core


Ignore:
Timestamp:
07/02/2024 10:01:17 AM (18 months ago)
Author:
Bernhard Reiter
Message:

Block Hooks: Allow child insertion into Template Part block.

The Block Hooks mechanism was previously extended to allow insertion of a block as a Navigation block's first or last child. This was implemented by storing the ignoredHookedBlocks array in the corresponding wp_navigation post's post meta (instead of a metadata attribute on the anchor block).

This changeset extends that mechanism to Template Part blocks, by storing said metadata in the corresponding wp_template_part post's post meta, thus allowing extenders to use Block Hooks to insert a block as a Template Part block's first or last child, respectively.

Props tomjcafferkey, bernhard-reiter.
Fixes #60854.

File:
1 edited

Legend:

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

    r58409 r58614  
    607607    }
    608608
     609    $hooked_blocks        = get_hooked_blocks();
     610    $has_hooked_blocks    = ! empty( $hooked_blocks ) || has_filter( 'hooked_block_types' );
    609611    $before_block_visitor = '_inject_theme_attribute_in_template_part_block';
    610612    $after_block_visitor  = null;
    611     $hooked_blocks        = get_hooked_blocks();
    612     if ( ! empty( $hooked_blocks ) || has_filter( 'hooked_block_types' ) ) {
     613
     614    if ( $has_hooked_blocks ) {
    613615        $before_block_visitor = make_before_block_visitor( $hooked_blocks, $template, 'insert_hooked_blocks_and_set_ignored_hooked_blocks_metadata' );
    614616        $after_block_visitor  = make_after_block_visitor( $hooked_blocks, $template, 'insert_hooked_blocks_and_set_ignored_hooked_blocks_metadata' );
    615617    }
    616     $blocks            = parse_blocks( $template->content );
    617     $template->content = traverse_and_serialize_blocks( $blocks, $before_block_visitor, $after_block_visitor );
     618
     619    if ( 'wp_template_part' === $template->type && $has_hooked_blocks ) {
     620        /**
     621         * In order for hooked blocks to be inserted at positions first_child and last_child in a template part,
     622         * we need to wrap its content a mock template part block and traverse it.
     623         */
     624        $content           = get_comment_delimited_block_content(
     625            'core/template-part',
     626            array(),
     627            $template->content
     628        );
     629        $content           = traverse_and_serialize_blocks( parse_blocks( $content ), $before_block_visitor, $after_block_visitor );
     630        $template->content = remove_serialized_parent_block( $content );
     631    } else {
     632        $template->content = traverse_and_serialize_blocks(
     633            parse_blocks( $template->content ),
     634            $before_block_visitor,
     635            $after_block_visitor
     636        );
     637    }
    618638
    619639    return $template;
     
    9991019        $before_block_visitor = make_before_block_visitor( $hooked_blocks, $template, 'insert_hooked_blocks_and_set_ignored_hooked_blocks_metadata' );
    10001020        $after_block_visitor  = make_after_block_visitor( $hooked_blocks, $template, 'insert_hooked_blocks_and_set_ignored_hooked_blocks_metadata' );
    1001         $blocks               = parse_blocks( $template->content );
    1002         $template->content    = traverse_and_serialize_blocks( $blocks, $before_block_visitor, $after_block_visitor );
     1021        if ( 'wp_template_part' === $template->type ) {
     1022            $existing_ignored_hooked_blocks = get_post_meta( $post->ID, '_wp_ignored_hooked_blocks', true );
     1023            $attributes                     = ! empty( $existing_ignored_hooked_blocks ) ? array( 'metadata' => array( 'ignoredHookedBlocks' => json_decode( $existing_ignored_hooked_blocks, true ) ) ) : array();
     1024
     1025            /**
     1026             * In order for hooked blocks to be inserted at positions first_child and last_child in a template part,
     1027             * we need to wrap its content a mock template part block and traverse it.
     1028             */
     1029            $content           = get_comment_delimited_block_content(
     1030                'core/template-part',
     1031                $attributes,
     1032                $template->content
     1033            );
     1034            $content           = traverse_and_serialize_blocks( parse_blocks( $content ), $before_block_visitor, $after_block_visitor );
     1035            $template->content = remove_serialized_parent_block( $content );
     1036        } else {
     1037            $template->content = traverse_and_serialize_blocks(
     1038                parse_blocks( $template->content ),
     1039                $before_block_visitor,
     1040                $after_block_visitor
     1041            );
     1042        }
    10031043    }
    10041044
     
    16121652    }
    16131653
    1614     $changes->post_content = apply_block_hooks_to_content( $changes->post_content, $template, 'set_ignored_hooked_blocks_metadata' );
     1654    if ( 'wp_template_part' === $post->post_type ) {
     1655        $attributes                     = array();
     1656        $existing_ignored_hooked_blocks = isset( $post->ID ) ? get_post_meta( $post->ID, '_wp_ignored_hooked_blocks', true ) : '';
     1657
     1658        if ( ! empty( $existing_ignored_hooked_blocks ) ) {
     1659            $attributes['metadata'] = array(
     1660                'ignoredHookedBlocks' => json_decode( $existing_ignored_hooked_blocks, true ),
     1661            );
     1662        }
     1663
     1664        $content = get_comment_delimited_block_content(
     1665            'core/template-part',
     1666            $attributes,
     1667            $changes->post_content
     1668        );
     1669        $content = apply_block_hooks_to_content( $content, $template, 'set_ignored_hooked_blocks_metadata' );
     1670        $changes->post_content = remove_serialized_parent_block( $content );
     1671
     1672        $wrapper_block_markup  = extract_serialized_parent_block( $content );
     1673        $wrapper_block         = parse_blocks( $wrapper_block_markup )[0];
     1674        $ignored_hooked_blocks = $wrapper_block['attrs']['metadata']['ignoredHookedBlocks'] ?? array();
     1675        if ( ! empty( $ignored_hooked_blocks ) ) {
     1676            if ( ! isset( $changes->meta_input ) ) {
     1677                $changes->meta_input = array();
     1678            }
     1679            $changes->meta_input['_wp_ignored_hooked_blocks'] = wp_json_encode( $ignored_hooked_blocks );
     1680        }
     1681    } else {
     1682        $changes->post_content = apply_block_hooks_to_content( $changes->post_content, $template, 'set_ignored_hooked_blocks_metadata' );
     1683    }
    16151684
    16161685    return $changes;
Note: See TracChangeset for help on using the changeset viewer.