Make WordPress Core

Changeset 62864


Ignore:
Timestamp:
07/28/2026 05:39:16 AM (17 hours ago)
Author:
ramonopoly
Message:

`
Layout: avoid resolving global settings for blocks with no layout output

This commit moves the global settings lookup in wp_render_layout_support_flag() below an early return for blocks with no layout support and no style attribute. Resolving settings on a cold cache queries the user's wp_global_styles post, which fires the_posts; a callback on that hook that renders blocks re-enters the filter and recurses without a base case.

Developed in: https://github.com/WordPress/wordpress-develop/pull/12729(https://github.com/WordPress/wordpress-develop/pull/12729)

Props ramonopoly, andrewserong.

Fixes #65741.

Location:
trunk
Files:
2 edited

Legend:

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

    r62801 r62864  
    956956        static $global_styles = null;
    957957
    958         $block_type               = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
    959         $block_supports_layout    = block_has_support( $block_type, 'layout', false ) || block_has_support( $block_type, '__experimentalLayout', false );
    960         $style_attr               = $block['attrs']['style'] ?? array();
     958        $block_type            = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
     959        $block_supports_layout = block_has_support( $block_type, 'layout', false ) || block_has_support( $block_type, '__experimentalLayout', false );
     960        $style_attr            = $block['attrs']['style'] ?? array();
     961        /*
     962         * A block with no layout support and no style attribute at all cannot
     963         * produce layout output, so return before resolving global settings.
     964         *
     965         * Resolving settings is not read-only: on a cold cache it queries the
     966         * user's `wp_global_styles` post, which fires `the_posts`. A callback on
     967         * that hook that renders blocks re-enters this filter, and the content it
     968         * renders at that point is the global styles post itself, which parses to a
     969         * single block with no name and no attributes. Without this return that
     970         * block resolves settings again and the recursion has no base case.
     971         */
     972        if ( ! $block_supports_layout && empty( $style_attr ) ) {
     973                return $block_content;
     974        }
     975
    961976        $global_settings          = wp_get_global_settings();
    962977        $viewport_settings        = $global_settings['viewport'] ?? null;
  • trunk/tests/phpunit/tests/block-supports/layout.php

    r62801 r62864  
    11251125                );
    11261126        }
     1127
     1128        /**
     1129         * Tests that layout support returns early, without resolving global settings,
     1130         * for a block that cannot produce any layout output.
     1131         *
     1132         * Resolving global settings reads the user's `wp_global_styles` post with a
     1133         * `WP_Query`, which fires `the_posts`. A callback on that hook that renders
     1134         * blocks re-enters this filter, so the bail-out has to happen before the
     1135         * lookup or the recursion has no base case.
     1136         *
     1137         * @ticket 65741
     1138         *
     1139         * @covers ::wp_render_layout_support_flag
     1140         */
     1141        public function test_layout_support_flag_returns_early_before_resolving_global_settings() {
     1142                $user_data_resolutions = 0;
     1143                add_filter(
     1144                        'wp_theme_json_data_user',
     1145                        static function ( $theme_json ) use ( &$user_data_resolutions ) {
     1146                                ++$user_data_resolutions;
     1147                                return $theme_json;
     1148                        }
     1149                );
     1150
     1151                // A block with no layout support and no child layout, as produced by
     1152                // parsing content that has no block delimiters.
     1153                $block_content = '<p>Not a block.</p>';
     1154                $block         = array(
     1155                        'blockName' => null,
     1156                        'attrs'     => array(),
     1157                );
     1158
     1159                // Start from a cold cache, as on a front-end request.
     1160                wp_clean_theme_json_cache();
     1161
     1162                $this->assertSame(
     1163                        $block_content,
     1164                        wp_render_layout_support_flag( $block_content, $block ),
     1165                        'Block content should be returned unchanged when the block has no layout support.'
     1166                );
     1167                $this->assertSame(
     1168                        0,
     1169                        $user_data_resolutions,
     1170                        'Global settings should not be resolved for a block that cannot produce layout output.'
     1171                );
     1172
     1173                // A block that does support layout still resolves global settings, which
     1174                // confirms the assertion above is not passing because of a warm cache.
     1175                wp_clean_theme_json_cache();
     1176
     1177                wp_render_layout_support_flag(
     1178                        '<div class="wp-block-group"></div>',
     1179                        array(
     1180                                'blockName' => 'core/group',
     1181                                'attrs'     => array( 'layout' => array( 'type' => 'constrained' ) ),
     1182                        )
     1183                );
     1184
     1185                $this->assertGreaterThan(
     1186                        0,
     1187                        $user_data_resolutions,
     1188                        'Global settings should still be resolved for a block that supports layout.'
     1189                );
     1190        }
    11271191}
Note: See TracChangeset for help on using the changeset viewer.