Skip to content

Commit bb7e7e8

Browse files
authored
Merge branch 'WordPress:trunk' into trunk
2 parents 0423b19 + 0ccf72e commit bb7e7e8

2 files changed

Lines changed: 82 additions & 3 deletions

File tree

‎src/wp-includes/block-supports/layout.php‎

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -955,9 +955,24 @@ function wp_get_layout_style( $selector, $layout, $has_block_gap_support = false
955955
function wp_render_layout_support_flag( $block_content, $block ) {
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;
963978
$responsive_media_queries = WP_Theme_JSON::get_viewport_media_queries( $viewport_settings );

‎tests/phpunit/tests/block-supports/layout.php‎

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,4 +1124,68 @@ public function test_layout_support_flag_with_non_string_class_name() {
11241124
'Layout support should render the expected markup when className is not a string'
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
}

0 commit comments

Comments
 (0)