From b1737c662700aadbefacbb6398d72ed8fa11c7c8 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Wed, 21 Aug 2024 11:59:31 +0200 Subject: [PATCH 1/6] Block Hooks: Have apply_block_hooks_to_content inject theme attr into template parts --- src/wp-includes/blocks.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/wp-includes/blocks.php b/src/wp-includes/blocks.php index a53092e04e4d7..c0de06a8aa402 100644 --- a/src/wp-includes/blocks.php +++ b/src/wp-includes/blocks.php @@ -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. @@ -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, $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 ); - $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 ); } From ec5bef6d75e99e5eac296be9f7e3b33653c831fe Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Wed, 21 Aug 2024 12:04:38 +0200 Subject: [PATCH 2/6] Patterns: Use apply_block_hooks_to_content --- .../class-wp-block-patterns-registry.php | 41 ++++++------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/src/wp-includes/class-wp-block-patterns-registry.php b/src/wp-includes/class-wp-block-patterns-registry.php index 6317bc81e51b1..3b5f053bfd8bf 100644 --- a/src/wp-includes/class-wp-block-patterns-registry.php +++ b/src/wp-includes/class-wp-block-patterns-registry.php @@ -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. * @@ -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; } @@ -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 ); From d1db659a9fc25ac4d92877efa29172c8a53d02a1 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Wed, 21 Aug 2024 12:20:09 +0200 Subject: [PATCH 3/6] Fix arguments to visitor factories --- src/wp-includes/blocks.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/blocks.php b/src/wp-includes/blocks.php index c0de06a8aa402..a479992faa4ca 100644 --- a/src/wp-includes/blocks.php +++ b/src/wp-includes/blocks.php @@ -1052,8 +1052,8 @@ function apply_block_hooks_to_content( $content, $context, $callback = 'insert_h $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' ); + $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 ); From da44cc16a759feff636a4d9740ce99a207521d1b Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Wed, 21 Aug 2024 12:21:20 +0200 Subject: [PATCH 4/6] Templates: Use apply_block_hooks_to_content in _build_block_template_result_from_file --- src/wp-includes/block-template-utils.php | 26 +++++++++--------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/wp-includes/block-template-utils.php b/src/wp-includes/block-template-utils.php index 29007811727f6..597d40a4150ac 100644 --- a/src/wp-includes/block-template-utils.php +++ b/src/wp-includes/block-template-utils.php @@ -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. @@ -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' ); } From 1604b386979554efcf72fa45c05176fb9e83026a Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Wed, 21 Aug 2024 12:41:49 +0200 Subject: [PATCH 5/6] Templates: Use apply_block_hooks_to_content in _build_block_template_result_from_post --- src/wp-includes/block-template-utils.php | 49 ++++++++++++------------ 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/src/wp-includes/block-template-utils.php b/src/wp-includes/block-template-utils.php index 597d40a4150ac..05012fbf2235f 100644 --- a/src/wp-includes/block-template-utils.php +++ b/src/wp-includes/block-template-utils.php @@ -1030,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; From 80d0934081fe65c5320f3609611a0fe43c249218 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Fri, 27 Sep 2024 13:50:17 +0500 Subject: [PATCH 6/6] Add basic test coverage --- .../tests/blocks/applyBlockHooksToContent.php | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 tests/phpunit/tests/blocks/applyBlockHooksToContent.php diff --git a/tests/phpunit/tests/blocks/applyBlockHooksToContent.php b/tests/phpunit/tests/blocks/applyBlockHooksToContent.php new file mode 100644 index 0000000000000..61f594d011de1 --- /dev/null +++ b/tests/phpunit/tests/blocks/applyBlockHooksToContent.php @@ -0,0 +1,70 @@ + 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 = ''; + + $actual = apply_block_hooks_to_content( $context->content, $context, 'insert_hooked_blocks' ); + $this->assertSame( + sprintf( '', get_stylesheet() ), + $actual + ); + } + + /** + * @ticket 61902 + */ + public function test_apply_block_hooks_to_content_inserts_hooked_block() { + $context = new WP_Block_Template(); + $context->content = ''; + + $actual = apply_block_hooks_to_content( $context->content, $context, 'insert_hooked_blocks' ); + $this->assertSame( + '', + $actual + ); + } +}