diff --git a/src/wp-includes/block-template-utils.php b/src/wp-includes/block-template-utils.php index f974f6efbd9a5..d8562764447a1 100644 --- a/src/wp-includes/block-template-utils.php +++ b/src/wp-includes/block-template-utils.php @@ -1168,9 +1168,35 @@ function get_block_templates( $query = array(), $template_type = 'wp_template' ) * over the theme-provided ones, so we skip querying and building them. */ $query['slug__not_in'] = wp_list_pluck( $query_result, 'slug' ); - $template_files = _get_block_templates_files( $template_type, $query ); + /* + * We need to unset the post_type query param because some templates + * would be excluded otherwise, like `page.html` when looking for + * `page` templates. We need all templates so we can exclude duplicates + * from plugin-registered templates. + * See: https://github.com/WordPress/gutenberg/issues/65584 + */ + $template_files_query = $query; + unset( $template_files_query['post_type'] ); + $template_files = _get_block_templates_files( $template_type, $template_files_query ); foreach ( $template_files as $template_file ) { - $query_result[] = _build_block_template_result_from_file( $template_file, $template_type ); + // The custom templates with no associated post types are available for all post types. + if ( isset( $query['post_type'] ) && ! isset( $template_file['postTypes'] ) ) { + $candidate = _build_block_template_result_from_file( $template_file, $template_type ); + $default_template_types = get_default_block_template_types(); + if ( ! isset( $default_template_types[ $candidate->slug ] ) ) { + $query_result[] = $candidate; + } + } elseif ( + // If the query doesn't specify a post type, or it does and the template has the post type, add it. + ! isset( $query['post_type'] ) || + ( + isset( $query['post_type'] ) && + isset( $template_file['postTypes'] ) && + in_array( $query['post_type'], $template_file['postTypes'], true ) + ) + ) { + $query_result[] = _build_block_template_result_from_file( $template_file, $template_type ); + } } if ( 'wp_template' === $template_type ) { diff --git a/tests/phpunit/tests/blocks/getBlockTemplates.php b/tests/phpunit/tests/blocks/getBlockTemplates.php index 4db9093aae4a2..341c93c10fa78 100644 --- a/tests/phpunit/tests/blocks/getBlockTemplates.php +++ b/tests/phpunit/tests/blocks/getBlockTemplates.php @@ -228,4 +228,62 @@ public function data_get_block_templates_should_respect_posttypes_property() { ), ); } + + /** + * @dataProvider data_get_block_templates_should_not_leak_plugin_registered_templates_with_default_post_type_slugs + * @ticket 62319 + * + * @param string $template_slug Default slug for the post type. + * @param string $post_type Post type for query. + * @param array $expected Expected template IDs. + */ + public function test_get_block_templates_should_not_leak_plugin_registered_templates_with_default_post_type_slugs( $template_slug, $post_type, $expected ) { + $template_name = 'test-plugin//' . $template_slug; + $template_args = array( + 'content' => 'Template content', + 'title' => 'Test Template for ' . $post_type, + 'description' => 'Description of test template', + 'post_types' => array( $post_type ), + ); + register_block_template( $template_name, $template_args ); + + $templates = get_block_templates( array( 'post_type' => $post_type ) ); + + $this->assertSameSets( + $expected, + $this->get_template_ids( $templates ) + ); + + unregister_block_template( $template_name ); + } + + /** + * Data provider. + * + * Make sure that plugin-registered templates with default post type slugs (ie: `single` or `page`) + * don't leak into `get_block_templates()`. + * See: https://core.trac.wordpress.org/ticket/62319. + * + * @return array + */ + public function data_get_block_templates_should_not_leak_plugin_registered_templates_with_default_post_type_slugs() { + return array( + 'post' => array( + 'template_slug' => 'single', + 'post_type' => 'post', + 'expected' => array( + 'block-theme//custom-hero-template', + 'block-theme//custom-single-post-template', + ), + ), + 'page' => array( + 'template_slug' => 'page', + 'post_type' => 'page', + 'expected' => array( + 'block-theme//custom-hero-template', + 'block-theme//page-home', + ), + ), + ); + } }