Make WordPress Core

Changeset 59951


Ignore:
Timestamp:
03/07/2025 05:53:37 PM (2 weeks ago)
Author:
flixos90
Message:

Editor: Fix unexpected behavior due to conflicting custom block template.

This changeset fixes both a visual and functional bug related to template selection in the editor that occurred when having a custom block template registered that was using the same slug as another block template already registered by the theme, including the default block templates.

Props aljullu, antonvlasenko, apermo, audrasjb, azaozz, ntsekouras.
Fixes #62319.

Location:
trunk
Files:
2 edited

Legend:

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

    r59819 r59951  
    11861186         */
    11871187        $query['slug__not_in'] = wp_list_pluck( $query_result, 'slug' );
    1188         $template_files        = _get_block_templates_files( $template_type, $query );
     1188        /*
     1189         * We need to unset the post_type query param because some templates
     1190         * would be excluded otherwise, like `page.html` when looking for
     1191         * `page` templates. We need all templates so we can exclude duplicates
     1192         * from plugin-registered templates.
     1193         * See: https://github.com/WordPress/gutenberg/issues/65584
     1194         */
     1195        $template_files_query = $query;
     1196        unset( $template_files_query['post_type'] );
     1197        $template_files = _get_block_templates_files( $template_type, $template_files_query );
    11891198        foreach ( $template_files as $template_file ) {
    1190             $query_result[] = _build_block_template_result_from_file( $template_file, $template_type );
     1199            // If the query doesn't specify a post type, or it does and the template matches the post type, add it.
     1200            if (
     1201                ! isset( $query['post_type'] ) ||
     1202                (
     1203                    isset( $template_file['postTypes'] ) &&
     1204                    in_array( $query['post_type'], $template_file['postTypes'], true )
     1205                )
     1206            ) {
     1207                $query_result[] = _build_block_template_result_from_file( $template_file, $template_type );
     1208            } elseif ( ! isset( $template_file['postTypes'] ) ) {
     1209                // The custom templates with no associated post types are available for all post types as long
     1210                // as they are not default templates.
     1211                $candidate              = _build_block_template_result_from_file( $template_file, $template_type );
     1212                $default_template_types = get_default_block_template_types();
     1213                if ( ! isset( $default_template_types[ $candidate->slug ] ) ) {
     1214                    $query_result[] = $candidate;
     1215                }
     1216            }
    11911217        }
    11921218
  • trunk/tests/phpunit/tests/blocks/getBlockTemplates.php

    r58323 r59951  
    229229        );
    230230    }
     231
     232    /**
     233     * @dataProvider data_get_block_templates_should_not_leak_plugin_registered_templates_with_default_post_type_slugs
     234     * @ticket 62319
     235     *
     236     * @covers ::get_block_templates
     237     *
     238     * @param string $template_slug Default slug for the post type.
     239     * @param string $post_type     Post type for query.
     240     * @param array  $expected      Expected template IDs.
     241     */
     242    public function test_get_block_templates_should_not_leak_plugin_registered_templates_with_default_post_type_slugs( $template_slug, $post_type, $expected ) {
     243        $template_name = 'test-plugin//' . $template_slug;
     244        $template_args = array(
     245            'content'     => 'Template content',
     246            'title'       => 'Test Template for ' . $post_type,
     247            'description' => 'Description of test template',
     248            'post_types'  => array( $post_type ),
     249        );
     250        register_block_template( $template_name, $template_args );
     251
     252        $templates = get_block_templates( array( 'post_type' => $post_type ) );
     253
     254        $this->assertSameSets(
     255            $expected,
     256            $this->get_template_ids( $templates )
     257        );
     258
     259        unregister_block_template( $template_name );
     260    }
     261
     262    /**
     263     * Data provider.
     264     *
     265     * Make sure that plugin-registered templates with default post type slugs (ie: `single` or `page`)
     266     * don't leak into `get_block_templates()`.
     267     * See: https://core.trac.wordpress.org/ticket/62319.
     268     *
     269     * @return array
     270     */
     271    public function data_get_block_templates_should_not_leak_plugin_registered_templates_with_default_post_type_slugs() {
     272        return array(
     273            'post' => array(
     274                'template_slug' => 'single',
     275                'post_type'     => 'post',
     276                'expected'      => array(
     277                    'block-theme//custom-hero-template',
     278                    'block-theme//custom-single-post-template',
     279                ),
     280            ),
     281            'page' => array(
     282                'template_slug' => 'page',
     283                'post_type'     => 'page',
     284                'expected'      => array(
     285                    'block-theme//custom-hero-template',
     286                    'block-theme//page-home',
     287                ),
     288            ),
     289        );
     290    }
    231291}
Note: See TracChangeset for help on using the changeset viewer.