Make WordPress Core


Ignore:
Timestamp:
07/02/2024 10:01:17 AM (2 years 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.