Skip to content

Commit e1d2179

Browse files
Editor: fix grid layout for style variations defining blockGap.
Ensures the grid block columns computation takes into account any blockGap value output by an active block style variation. Props isabel_brison, mukesh27, westonruter, andrewserong. Fixes #64624. git-svn-id: https://develop.svn.wordpress.org/trunk@61655 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 1580811 commit e1d2179

2 files changed

Lines changed: 195 additions & 2 deletions

File tree

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

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,37 @@
66
* @since 5.8.0
77
*/
88

9+
/**
10+
* Gets the first style variation name from a className string that matches a registered style.
11+
*
12+
* @since 7.0.0
13+
*
14+
* @param string $class_name CSS class string for a block.
15+
* @param array<string, array<string, mixed>> $registered_styles Currently registered block styles.
16+
* @return string|null The name of the first registered variation, or null if none found.
17+
*/
18+
function wp_get_block_style_variation_name_from_registered_style( string $class_name, array $registered_styles = array() ): ?string {
19+
if ( ! $class_name ) {
20+
return null;
21+
}
22+
23+
$registered_names = array_filter( array_column( $registered_styles, 'name' ) );
24+
25+
$prefix = 'is-style-';
26+
$length = strlen( $prefix );
27+
28+
foreach ( explode( ' ', $class_name ) as $class ) {
29+
if ( str_starts_with( $class, $prefix ) ) {
30+
$variation = substr( $class, $length );
31+
if ( 'default' !== $variation && in_array( $variation, $registered_names, true ) ) {
32+
return $variation;
33+
}
34+
}
35+
}
36+
37+
return null;
38+
}
39+
940
/**
1041
* Returns layout definitions, keyed by layout type.
1142
*
@@ -854,12 +885,26 @@ function wp_render_layout_support_flag( $block_content, $block ) {
854885
$has_block_gap_support = isset( $block_gap );
855886

856887
// Get default blockGap value from global styles for use in layouts like grid.
857-
// Check block-specific styles first, then fall back to root styles.
888+
// Check style variation first, then block-specific styles, then fall back to root styles.
858889
$block_name = $block['blockName'] ?? '';
859890
if ( null === $global_styles ) {
860891
$global_styles = wp_get_global_styles();
861892
}
862-
$global_block_gap_value = $global_styles['blocks'][ $block_name ]['spacing']['blockGap'] ?? ( $global_styles['spacing']['blockGap'] ?? null );
893+
894+
// Check if the block has an active style variation with a blockGap value.
895+
// Only check the registry if the className contains a variation class to avoid unnecessary lookups.
896+
$variation_block_gap_value = null;
897+
$block_class_name = $block['attrs']['className'] ?? '';
898+
if ( $block_class_name && str_contains( $block_class_name, 'is-style-' ) && $block_name ) {
899+
$styles_registry = WP_Block_Styles_Registry::get_instance();
900+
$registered_styles = $styles_registry->get_registered_styles_for_block( $block_name );
901+
$variation_name = wp_get_block_style_variation_name_from_registered_style( $block_class_name, $registered_styles );
902+
if ( $variation_name ) {
903+
$variation_block_gap_value = $global_styles['blocks'][ $block_name ]['variations'][ $variation_name ]['spacing']['blockGap'] ?? null;
904+
}
905+
}
906+
907+
$global_block_gap_value = $variation_block_gap_value ?? $global_styles['blocks'][ $block_name ]['spacing']['blockGap'] ?? $global_styles['spacing']['blockGap'] ?? null;
863908

864909
if ( null !== $global_block_gap_value ) {
865910
$fallback_gap_value = $global_block_gap_value;

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

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,22 @@ public function set_up() {
4242
// Clear caches.
4343
wp_clean_themes_cache();
4444
unset( $GLOBALS['wp_themes'] );
45+
46+
/*
47+
* Register a style variation with a custom blockGap value for testing.
48+
*/
49+
register_block_style(
50+
'core/group',
51+
array(
52+
'name' => 'custom-gap',
53+
'label' => 'Custom Gap',
54+
'style_data' => array(
55+
'spacing' => array(
56+
'blockGap' => '99px',
57+
),
58+
),
59+
)
60+
);
4561
}
4662

4763
public function tear_down() {
@@ -54,6 +70,11 @@ public function tear_down() {
5470

5571
wp_clean_themes_cache();
5672
unset( $GLOBALS['wp_themes'] );
73+
74+
// Clean up variation test data.
75+
unregister_block_style( 'core/group', 'custom-gap' );
76+
WP_Theme_JSON_Resolver::clean_cached_data();
77+
5778
parent::tear_down();
5879
}
5980

@@ -727,4 +748,131 @@ public function data_layout_classname_with_custom_blocks() {
727748
),
728749
);
729750
}
751+
752+
/**
753+
* Tests that block style variations with blockGap values are applied to layout styles.
754+
*
755+
* @ticket 64624
756+
* @covers ::wp_render_layout_support_flag
757+
*/
758+
public function test_layout_support_flag_uses_variation_block_gap_value() {
759+
switch_theme( 'block-theme' );
760+
761+
$block_content = '<div class="wp-block-group is-style-custom-gap"></div>';
762+
$block = array(
763+
'blockName' => 'core/group',
764+
'attrs' => array(
765+
'className' => 'is-style-custom-gap',
766+
'layout' => array(
767+
'type' => 'grid',
768+
'columnCount' => 3,
769+
'minimumColumnWidth' => '12rem',
770+
),
771+
),
772+
'innerBlocks' => array(),
773+
'innerHTML' => '<div class="wp-block-group is-style-custom-gap"></div>',
774+
'innerContent' => array(
775+
'<div class="wp-block-group is-style-custom-gap"></div>',
776+
),
777+
);
778+
779+
wp_render_layout_support_flag( $block_content, $block );
780+
781+
// Get the generated CSS from the style engine.
782+
$actual_stylesheet = wp_style_engine_get_stylesheet_from_context( 'block-supports', array( 'prettify' => false ) );
783+
784+
// The CSS grid declaration should contain the variation's blockGap value of 99px.
785+
$this->assertStringContainsString(
786+
'grid-template-columns:repeat(auto-fill, minmax(max(min(12rem, 100%), (100% - (99px * (3 - 1))) /3), 1fr))',
787+
$actual_stylesheet,
788+
'Generated CSS should contain the variation blockGap value of 99px.'
789+
);
790+
}
791+
792+
/**
793+
* Tests that wp_get_block_style_variation_name_from_registered_style correctly extracts variation names from class strings.
794+
*
795+
* @ticket 64624
796+
* @covers ::wp_get_block_style_variation_name_from_registered_style
797+
*
798+
* @dataProvider data_get_block_style_variation_name_from_registered_style
799+
*
800+
* @param string $class_name CSS class string to test.
801+
* @param array $registered_styles Registered block styles.
802+
* @param string|null $expected_result Expected variation name or null.
803+
*/
804+
public function test_get_block_style_variation_name_from_registered_style( $class_name, $registered_styles, $expected_result ) {
805+
$result = wp_get_block_style_variation_name_from_registered_style( $class_name, $registered_styles );
806+
$this->assertSame( $expected_result, $result );
807+
}
808+
809+
/**
810+
* Data provider for test_get_block_style_variation_name_from_registered_style.
811+
*
812+
* @return array
813+
*/
814+
public function data_get_block_style_variation_name_from_registered_style() {
815+
return array(
816+
'empty class name' => array(
817+
'class_name' => '',
818+
'registered_styles' => array(),
819+
'expected_result' => null,
820+
),
821+
'no matching registered styles' => array(
822+
'class_name' => 'is-style-shadowed wp-block-button',
823+
'registered_styles' => array(
824+
array( 'name' => 'rounded' ),
825+
array( 'name' => 'outlined' ),
826+
),
827+
'expected_result' => null,
828+
),
829+
'single matching variation found' => array(
830+
'class_name' => 'wp-block-button is-style-rounded',
831+
'registered_styles' => array(
832+
array( 'name' => 'rounded' ),
833+
array( 'name' => 'outlined' ),
834+
),
835+
'expected_result' => 'rounded',
836+
),
837+
'ignores default style only' => array(
838+
'class_name' => 'is-style-default wp-block-button',
839+
'registered_styles' => array(
840+
array( 'name' => 'default' ),
841+
array( 'name' => 'rounded' ),
842+
),
843+
'expected_result' => null,
844+
),
845+
'ignores default and returns next variation' => array(
846+
'class_name' => 'is-style-default is-style-rounded wp-block-button',
847+
'registered_styles' => array(
848+
array( 'name' => 'default' ),
849+
array( 'name' => 'rounded' ),
850+
array( 'name' => 'outlined' ),
851+
),
852+
'expected_result' => 'rounded',
853+
),
854+
'returns first matching variation when multiple present' => array(
855+
'class_name' => 'is-style-shadowed is-style-rounded',
856+
'registered_styles' => array(
857+
array( 'name' => 'rounded' ),
858+
array( 'name' => 'outlined' ),
859+
array( 'name' => 'shadowed' ),
860+
),
861+
'expected_result' => 'shadowed',
862+
),
863+
'empty registered styles array' => array(
864+
'class_name' => 'is-style-rounded',
865+
'registered_styles' => array(),
866+
'expected_result' => null,
867+
),
868+
'registered styles with missing name property' => array(
869+
'class_name' => 'is-style-outlined wp-block-button',
870+
'registered_styles' => array(
871+
array( 'label' => 'Rounded' ),
872+
array( 'name' => 'outlined' ),
873+
),
874+
'expected_result' => 'outlined',
875+
),
876+
);
877+
}
730878
}

0 commit comments

Comments
 (0)