Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 34 additions & 41 deletions src/wp-includes/block-template-utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -615,17 +615,7 @@ function _build_block_template_result_from_file( $template_file, $template_type
$template->area = $template_file['area'];
}

$hooked_blocks = get_hooked_blocks();
$has_hooked_blocks = ! empty( $hooked_blocks ) || has_filter( 'hooked_block_types' );
$before_block_visitor = '_inject_theme_attribute_in_template_part_block';
$after_block_visitor = null;

if ( $has_hooked_blocks ) {
$before_block_visitor = make_before_block_visitor( $hooked_blocks, $template, 'insert_hooked_blocks_and_set_ignored_hooked_blocks_metadata' );
$after_block_visitor = make_after_block_visitor( $hooked_blocks, $template, 'insert_hooked_blocks_and_set_ignored_hooked_blocks_metadata' );
}

if ( 'wp_template_part' === $template->type && $has_hooked_blocks ) {
if ( 'wp_template_part' === $template->type ) {
/*
* In order for hooked blocks to be inserted at positions first_child and last_child in a template part,
* we need to wrap its content a mock template part block and traverse it.
Expand All @@ -635,13 +625,17 @@ function _build_block_template_result_from_file( $template_file, $template_type
array(),
$template->content
);
$content = traverse_and_serialize_blocks( parse_blocks( $content ), $before_block_visitor, $after_block_visitor );
$content = apply_block_hooks_to_content(
$content,
$template,
'insert_hooked_blocks_and_set_ignored_hooked_blocks_metadata'
);
$template->content = remove_serialized_parent_block( $content );
} else {
$template->content = traverse_and_serialize_blocks(
parse_blocks( $template->content ),
$before_block_visitor,
$after_block_visitor
$template->content = apply_block_hooks_to_content(
$template->content,
$template,
'insert_hooked_blocks_and_set_ignored_hooked_blocks_metadata'
);
}

Expand Down Expand Up @@ -1036,32 +1030,31 @@ function _build_block_template_result_from_post( $post ) {
}
}

$hooked_blocks = get_hooked_blocks();
if ( ! empty( $hooked_blocks ) || has_filter( 'hooked_block_types' ) ) {
$before_block_visitor = make_before_block_visitor( $hooked_blocks, $template, 'insert_hooked_blocks_and_set_ignored_hooked_blocks_metadata' );
$after_block_visitor = make_after_block_visitor( $hooked_blocks, $template, 'insert_hooked_blocks_and_set_ignored_hooked_blocks_metadata' );
if ( 'wp_template_part' === $template->type ) {
$existing_ignored_hooked_blocks = get_post_meta( $post->ID, '_wp_ignored_hooked_blocks', true );
$attributes = ! empty( $existing_ignored_hooked_blocks ) ? array( 'metadata' => array( 'ignoredHookedBlocks' => json_decode( $existing_ignored_hooked_blocks, true ) ) ) : array();
if ( 'wp_template_part' === $template->type ) {
$existing_ignored_hooked_blocks = get_post_meta( $post->ID, '_wp_ignored_hooked_blocks', true );
$attributes = ! empty( $existing_ignored_hooked_blocks ) ? array( 'metadata' => array( 'ignoredHookedBlocks' => json_decode( $existing_ignored_hooked_blocks, true ) ) ) : array();

/*
* In order for hooked blocks to be inserted at positions first_child and last_child in a template part,
* we need to wrap its content a mock template part block and traverse it.
*/
$content = get_comment_delimited_block_content(
'core/template-part',
$attributes,
$template->content
);
$content = traverse_and_serialize_blocks( parse_blocks( $content ), $before_block_visitor, $after_block_visitor );
$template->content = remove_serialized_parent_block( $content );
} else {
$template->content = traverse_and_serialize_blocks(
parse_blocks( $template->content ),
$before_block_visitor,
$after_block_visitor
);
}
/*
* In order for hooked blocks to be inserted at positions first_child and last_child in a template part,
* we need to wrap its content a mock template part block and traverse it.
*/
$content = get_comment_delimited_block_content(
'core/template-part',
$attributes,
$template->content
);
$content = apply_block_hooks_to_content(
$content,
$template,
'insert_hooked_blocks_and_set_ignored_hooked_blocks_metadata'
);
$template->content = remove_serialized_parent_block( $content );
} else {
$template->content = apply_block_hooks_to_content(
$template->content,
$template,
'insert_hooked_blocks_and_set_ignored_hooked_blocks_metadata'
);
}

return $template;
Expand Down
12 changes: 7 additions & 5 deletions src/wp-includes/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -1035,6 +1035,7 @@ function set_ignored_hooked_blocks_metadata( &$parsed_anchor_block, $relative_po
* Runs the hooked blocks algorithm on the given content.
*
* @since 6.6.0
* @since 6.7.0 Injects the `theme` attribute into Template Part blocks, even if no hooked blocks are registered.
* @access private
*
* @param string $content Serialized content.
Expand All @@ -1047,15 +1048,16 @@ function set_ignored_hooked_blocks_metadata( &$parsed_anchor_block, $relative_po
*/
function apply_block_hooks_to_content( $content, $context, $callback = 'insert_hooked_blocks' ) {
$hooked_blocks = get_hooked_blocks();
if ( empty( $hooked_blocks ) && ! has_filter( 'hooked_block_types' ) ) {
return $content;

$before_block_visitor = '_inject_theme_attribute_in_template_part_block';
$after_block_visitor = null;
if ( ! empty( $hooked_blocks ) || has_filter( 'hooked_block_types' ) ) {
$before_block_visitor = make_before_block_visitor( $hooked_blocks, $context, $callback );
$after_block_visitor = make_after_block_visitor( $hooked_blocks, $context, $callback );
}

$blocks = parse_blocks( $content );

$before_block_visitor = make_before_block_visitor( $hooked_blocks, $context, $callback );
$after_block_visitor = make_after_block_visitor( $hooked_blocks, $context, $callback );

return traverse_and_serialize_blocks( $blocks, $before_block_visitor, $after_block_visitor );
}

Expand Down
41 changes: 12 additions & 29 deletions src/wp-includes/class-wp-block-patterns-registry.php
Original file line number Diff line number Diff line change
Expand Up @@ -158,31 +158,6 @@ public function unregister( $pattern_name ) {
return true;
}

/**
* Prepares the content of a block pattern. If hooked blocks are registered, they get injected into the pattern,
* when they met the defined criteria.
*
* @since 6.4.0
*
* @param array $pattern Registered pattern properties.
* @param array $hooked_blocks The list of hooked blocks.
* @return string The content of the block pattern.
*/
private function prepare_content( $pattern, $hooked_blocks ) {
$content = $pattern['content'];

$before_block_visitor = '_inject_theme_attribute_in_template_part_block';
$after_block_visitor = null;
if ( ! empty( $hooked_blocks ) || has_filter( 'hooked_block_types' ) ) {
$before_block_visitor = make_before_block_visitor( $hooked_blocks, $pattern, 'insert_hooked_blocks_and_set_ignored_hooked_blocks_metadata' );
$after_block_visitor = make_after_block_visitor( $hooked_blocks, $pattern, 'insert_hooked_blocks_and_set_ignored_hooked_blocks_metadata' );
}
$blocks = parse_blocks( $content );
$content = traverse_and_serialize_blocks( $blocks, $before_block_visitor, $after_block_visitor );

return $content;
}

/**
* Retrieves the content of a registered block pattern.
*
Expand Down Expand Up @@ -221,8 +196,12 @@ public function get_registered( $pattern_name ) {
}

$pattern = $this->registered_patterns[ $pattern_name ];
$pattern['content'] = $this->get_content( $pattern_name );
$pattern['content'] = $this->prepare_content( $pattern, get_hooked_blocks() );
$content = $this->get_content( $pattern_name );
$pattern['content'] = apply_block_hooks_to_content(
$content,
$pattern,
'insert_hooked_blocks_and_set_ignored_hooked_blocks_metadata'
);

return $pattern;
}
Expand All @@ -243,8 +222,12 @@ public function get_all_registered( $outside_init_only = false ) {
$hooked_blocks = get_hooked_blocks();

foreach ( $patterns as $index => $pattern ) {
$pattern['content'] = $this->get_content( $pattern['name'], $outside_init_only );
$patterns[ $index ]['content'] = $this->prepare_content( $pattern, $hooked_blocks );
$content = $this->get_content( $pattern['name'], $outside_init_only );
$patterns[ $index ]['content'] = apply_block_hooks_to_content(
$content,
$pattern,
'insert_hooked_blocks_and_set_ignored_hooked_blocks_metadata'
);
}

return array_values( $patterns );
Expand Down
70 changes: 70 additions & 0 deletions tests/phpunit/tests/blocks/applyBlockHooksToContent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php
/**
* Tests for the apply_block_hooks_to_content function.
*
* @package WordPress
* @subpackage Blocks
*
* @since 6.7.0
*
* @group blocks
* @group block-hooks
*
* @covers ::apply_block_hooks_to_content
*/
class Tests_Blocks_ApplyBlockHooksToContent extends WP_UnitTestCase {
/**
* Set up.
*
* @ticket 61902.
*/
public static function wpSetUpBeforeClass() {
register_block_type(
'tests/hooked-block',
array(
'block_hooks' => array(
'tests/anchor-block' => 'after',
),
)
);
}

/**
* Tear down.
*
* @ticket 61902.
*/
public static function wpTearDownAfterClass() {
$registry = WP_Block_Type_Registry::get_instance();

$registry->unregister( 'tests/hooked-block' );
}

/**
* @ticket 61902
*/
public function test_apply_block_hooks_to_content_sets_theme_attribute_on_template_part_block() {
$context = new WP_Block_Template();
$context->content = '<!-- wp:template-part /-->';

$actual = apply_block_hooks_to_content( $context->content, $context, 'insert_hooked_blocks' );
$this->assertSame(
sprintf( '<!-- wp:template-part {"theme":"%s"} /-->', get_stylesheet() ),
$actual
);
}

/**
* @ticket 61902
*/
public function test_apply_block_hooks_to_content_inserts_hooked_block() {
$context = new WP_Block_Template();
$context->content = '<!-- wp:tests/anchor-block /-->';

$actual = apply_block_hooks_to_content( $context->content, $context, 'insert_hooked_blocks' );
$this->assertSame(
'<!-- wp:tests/anchor-block /--><!-- wp:tests/hooked-block /-->',
$actual
);
}
}