Make WordPress Core

Changeset 57019


Ignore:
Timestamp:
10/27/2023 06:16:05 PM (12 months ago)
Author:
flixos90
Message:

Themes: Skip wrapping block template for singular content with a main query loop when the template was injected from outside the current theme.

As a follow up to [56507], this fixes a bug that could occur for instance when plugins hijack the block template detection process to inject their own block template with entirely custom logic.

Props afragen, hellofromTonya, costdev, mukesh27, huzaifaalmesbah, flixos90.
Fixes #59736.
See #58154.

Location:
trunk
Files:
3 edited

Legend:

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

    r56507 r57019  
    209209 * @since 5.8.0
    210210 *
     211 * @global string   $_wp_current_template_id
    211212 * @global string   $_wp_current_template_content
    212213 * @global WP_Embed $wp_embed
     
    216217 */
    217218function get_the_block_template_html() {
    218     global $_wp_current_template_content, $wp_embed, $wp_query;
     219    global $_wp_current_template_id, $_wp_current_template_content, $wp_embed, $wp_query;
    219220
    220221    if ( ! $_wp_current_template_content ) {
     
    243244     * loop, it would not cause errors since it would use a cloned instance and go through the same loop of a single
    244245     * post, within the actual main query loop.
     246     *
     247     * This special logic should be skipped if the current template does not come from the current theme, in which case
     248     * it has been injected by a plugin by hijacking the block template loader mechanism. In that case, entirely custom
     249     * logic may be applied which is unpredictable and therefore safer to omit this special handling on.
    245250     */
    246     if ( is_singular() && 1 === $wp_query->post_count && have_posts() ) {
     251    if (
     252        $_wp_current_template_id &&
     253        str_starts_with( $_wp_current_template_id, get_stylesheet() . '//' ) &&
     254        is_singular() &&
     255        1 === $wp_query->post_count &&
     256        have_posts()
     257    ) {
    247258        while ( have_posts() ) {
    248259            the_post();
  • trunk/tests/phpunit/tests/block-template.php

    r57009 r57019  
    2020
    2121    public function tear_down() {
    22         global $_wp_current_template_content;
    23         unset( $_wp_current_template_content );
     22        global $_wp_current_template_id, $_wp_current_template_content;
     23        unset( $_wp_current_template_id, $_wp_current_template_content );
    2424
    2525        parent::tear_down();
     
    194194     *
    195195     * @ticket 58154
     196     * @ticket 59736
    196197     * @covers ::get_the_block_template_html
    197198     */
    198199    public function test_get_the_block_template_html_enforces_singular_query_loop() {
    199         global $_wp_current_template_content, $wp_query, $wp_the_query;
     200        global $_wp_current_template_id, $_wp_current_template_content, $wp_query, $wp_the_query;
    200201
    201202        // Register test block to log `in_the_loop()` results.
     
    208209        $wp_the_query = $wp_query;
    209210
     211        // Force a template ID that is for the current stylesheet.
     212        $_wp_current_template_id = get_stylesheet() . '//single';
    210213        // Use block template that just renders post title and the above test block.
    211214        $_wp_current_template_content = '<!-- wp:post-title /--><!-- wp:test/in-the-loop-logger /-->';
     
    228231     */
    229232    public function test_get_the_block_template_html_does_not_generally_enforce_loop() {
    230         global $_wp_current_template_content, $wp_query, $wp_the_query;
     233        global $_wp_current_template_id, $_wp_current_template_content, $wp_query, $wp_the_query;
    231234
    232235        // Register test block to log `in_the_loop()` results.
     
    248251        );
    249252        $wp_the_query = $wp_query;
     253
     254        // Force a template ID that is for the current stylesheet.
     255        $_wp_current_template_id = get_stylesheet() . '//home';
    250256
    251257        /*
     
    278284
    279285    /**
     286     * Tests that `get_the_block_template_html()` does not start the main query loop when on a template that is not from the current theme.
     287     *
     288     * @ticket 58154
     289     * @ticket 59736
     290     * @covers ::get_the_block_template_html
     291     */
     292    public function test_get_the_block_template_html_skips_singular_query_loop_when_non_theme_template() {
     293        global $_wp_current_template_id, $_wp_current_template_content, $wp_query, $wp_the_query;
     294
     295        // Register test block to log `in_the_loop()` results.
     296        $in_the_loop_logs = array();
     297        $this->register_in_the_loop_logger_block( $in_the_loop_logs );
     298
     299        // Set main query to single post.
     300        $post_id      = self::factory()->post->create( array( 'post_title' => 'A single post' ) );
     301        $wp_query     = new WP_Query( array( 'p' => $post_id ) );
     302        $wp_the_query = $wp_query;
     303
     304        // Force a template ID that is not for the current stylesheet.
     305        $_wp_current_template_id = 'some-plugin-slug//single';
     306        // Use block template that just renders post title and the above test block.
     307        $_wp_current_template_content = '<!-- wp:post-title /--><!-- wp:test/in-the-loop-logger /-->';
     308
     309        $output = get_the_block_template_html();
     310        $this->unregister_in_the_loop_logger_block();
     311        $this->assertSame( array( false ), $in_the_loop_logs, 'Main query loop was triggered despite a custom block template outside the current theme being used' );
     312    }
     313
     314    /**
    280315     * @ticket 58319
    281316     *
  • trunk/tests/phpunit/tests/media.php

    r56694 r57019  
    8080     */
    8181    public function tear_down() {
     82        global $_wp_current_template_id, $_wp_current_template_content;
     83        unset( $_wp_current_template_id, $_wp_current_template_content );
     84
    8285        parent::tear_down();
    8386
     
    39733976     */
    39743977    public function test_wp_filter_content_tags_does_not_lazy_load_first_image_in_block_theme() {
    3975         global $_wp_current_template_content, $wp_query, $wp_the_query, $post;
     3978        global $_wp_current_template_id, $_wp_current_template_content, $wp_query, $wp_the_query, $post;
    39763979
    39773980        // Do not add srcset, sizes, or decoding attributes as they are irrelevant for this test.
     
    40024005        $post         = get_post( self::$post_ids['publish'] );
    40034006
     4007        // Force a template ID that is for the current stylesheet.
     4008        $_wp_current_template_id      = get_stylesheet() . '//single';
    40044009        $_wp_current_template_content = '<!-- wp:post-content /-->';
    40054010
     
    40214026     */
    40224027    public function test_wp_filter_content_tags_does_not_lazy_load_first_featured_image_in_block_theme() {
    4023         global $_wp_current_template_content, $wp_query, $wp_the_query, $post;
     4028        global $_wp_current_template_id, $_wp_current_template_content, $wp_query, $wp_the_query, $post;
    40244029
    40254030        // Do not add srcset, sizes, or decoding attributes as they are irrelevant for this test.
     
    40704075        $post         = get_post( self::$post_ids['publish'] );
    40714076
     4077        // Force a template ID that is for the current stylesheet.
     4078        $_wp_current_template_id      = get_stylesheet() . '//single';
    40724079        $_wp_current_template_content = '<!-- wp:post-featured-image /--> <!-- wp:post-content /-->';
    40734080
     
    40884095     */
    40894096    public function test_wp_filter_content_tags_does_not_lazy_load_images_in_header() {
    4090         global $_wp_current_template_content;
     4097        global $_wp_current_template_id, $_wp_current_template_content;
    40914098
    40924099        // Do not add srcset, sizes, or decoding attributes as they are irrelevant for this test.
     
    41234130        wp_set_post_terms( $footer_post_id, get_stylesheet(), 'wp_theme' );
    41244131
     4132        // Force a template ID that is for the current stylesheet.
     4133        $_wp_current_template_id      = get_stylesheet() . '//single';
    41254134        $_wp_current_template_content = '<!-- wp:template-part {"slug":"header","theme":"' . get_stylesheet() . '","tagName":"header"} /--><!-- wp:template-part {"slug":"footer","theme":"' . get_stylesheet() . '","tagName":"footer"} /-->';
    41264135
Note: See TracChangeset for help on using the changeset viewer.