Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 81 additions & 20 deletions src/wp-includes/block-supports/layout.php
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ function wp_register_layout_support( $block_type ) {
* @param bool $has_block_gap_support Optional. Whether the theme has support for the block gap. Default false.
* @param string|string[]|null $gap_value Optional. The block gap value to apply. Default null.
* @param bool $should_skip_gap_serialization Optional. Whether to skip applying the user-defined value set in the editor. Default false.
* @param string $fallback_gap_value Optional. The block gap value to apply. Default '0.5em'.
* @param string|array $fallback_gap_value Optional. The block gap value to apply. If it's an array expected properties are "top" and/or "left". Default '0.5em'.
* @param array|null $block_spacing Optional. Custom spacing set on the block. Default null.
* @return string CSS styles on success. Else, empty string.
*/
Expand Down Expand Up @@ -427,7 +427,12 @@ function wp_get_layout_style( $selector, $layout, $has_block_gap_support = false
foreach ( $gap_sides as $gap_side ) {
$process_value = $gap_value;
if ( is_array( $gap_value ) ) {
$process_value = $gap_value[ $gap_side ] ?? $fallback_gap_value;
if ( is_array( $fallback_gap_value ) ) {
$fallback_value = $fallback_gap_value[ $gap_side ] ?? reset( $fallback_gap_value );
} else {
$fallback_value = $fallback_gap_value;
}
$process_value = $gap_value[ $gap_side ] ?? $fallback_value;
}
// Get spacing CSS variable from preset value if provided.
if ( is_string( $process_value ) && str_contains( $process_value, 'var:preset|spacing|' ) ) {
Expand Down Expand Up @@ -490,21 +495,14 @@ function wp_get_layout_style( $selector, $layout, $has_block_gap_support = false
}
}
} elseif ( 'grid' === $layout_type ) {
if ( ! empty( $layout['columnCount'] ) ) {
$layout_styles[] = array(
'selector' => $selector,
'declarations' => array( 'grid-template-columns' => 'repeat(' . $layout['columnCount'] . ', minmax(0, 1fr))' ),
);
/*
* If the gap value is an array, we use the "left" value because it represents the vertical gap, which
* is the relevant one for computation of responsive grid columns.
*/
if ( is_array( $fallback_gap_value ) ) {
$responsive_gap_value = $fallback_gap_value['left'] ?? reset( $fallback_gap_value );
} else {
$minimum_column_width = ! empty( $layout['minimumColumnWidth'] ) ? $layout['minimumColumnWidth'] : '12rem';

$layout_styles[] = array(
'selector' => $selector,
'declarations' => array(
'grid-template-columns' => 'repeat(auto-fill, minmax(min(' . $minimum_column_width . ', 100%), 1fr))',
'container-type' => 'inline-size',
),
);
$responsive_gap_value = $fallback_gap_value;
}

if ( $has_block_gap_support && isset( $gap_value ) ) {
Expand All @@ -514,7 +512,12 @@ function wp_get_layout_style( $selector, $layout, $has_block_gap_support = false
foreach ( $gap_sides as $gap_side ) {
$process_value = $gap_value;
if ( is_array( $gap_value ) ) {
$process_value = $gap_value[ $gap_side ] ?? $fallback_gap_value;
if ( is_array( $fallback_gap_value ) ) {
$fallback_value = $fallback_gap_value[ $gap_side ] ?? reset( $fallback_gap_value );
} else {
$fallback_value = $fallback_gap_value;
}
$process_value = $gap_value[ $gap_side ] ?? $fallback_value;
}
// Get spacing CSS variable from preset value if provided.
if ( is_string( $process_value ) && str_contains( $process_value, 'var:preset|spacing|' ) ) {
Expand All @@ -524,14 +527,58 @@ function wp_get_layout_style( $selector, $layout, $has_block_gap_support = false
}
$combined_gap_value .= "$process_value ";
}
$gap_value = trim( $combined_gap_value );
$gap_value = trim( $combined_gap_value );
$responsive_gap_value = $gap_value;
}

if ( null !== $gap_value && ! $should_skip_gap_serialization ) {
// Ensure 0 values have a unit so they work in calc().
if ( '0' === $responsive_gap_value || 0 === $responsive_gap_value ) {
$responsive_gap_value = '0px';
}

if ( ! empty( $layout['columnCount'] ) && ! empty( $layout['minimumColumnWidth'] ) ) {
$max_value = 'max(min(' . $layout['minimumColumnWidth'] . ', 100%), (100% - (' . $responsive_gap_value . ' * (' . $layout['columnCount'] . ' - 1))) /' . $layout['columnCount'] . ')';
$layout_styles[] = array(
'selector' => $selector,
'declarations' => array(
'grid-template-columns' => 'repeat(auto-fill, minmax(' . $max_value . ', 1fr))',
'container-type' => 'inline-size',
),
);
if ( ! empty( $layout['rowCount'] ) ) {
$layout_styles[] = array(
'selector' => $selector,
'declarations' => array( 'gap' => $gap_value ),
'declarations' => array( 'grid-template-rows' => 'repeat(' . $layout['rowCount'] . ', minmax(1rem, auto))' ),
);
}
} elseif ( ! empty( $layout['columnCount'] ) ) {
$layout_styles[] = array(
'selector' => $selector,
'declarations' => array( 'grid-template-columns' => 'repeat(' . $layout['columnCount'] . ', minmax(0, 1fr))' ),
);
if ( ! empty( $layout['rowCount'] ) ) {
$layout_styles[] = array(
'selector' => $selector,
'declarations' => array( 'grid-template-rows' => 'repeat(' . $layout['rowCount'] . ', minmax(1rem, auto))' ),
);
}
} else {
$minimum_column_width = ! empty( $layout['minimumColumnWidth'] ) ? $layout['minimumColumnWidth'] : '12rem';

$layout_styles[] = array(
'selector' => $selector,
'declarations' => array(
'grid-template-columns' => 'repeat(auto-fill, minmax(min(' . $minimum_column_width . ', 100%), 1fr))',
'container-type' => 'inline-size',
),
);
}

if ( $has_block_gap_support && null !== $gap_value && ! $should_skip_gap_serialization ) {
$layout_styles[] = array(
'selector' => $selector,
'declarations' => array( 'gap' => $gap_value ),
);
}
}

Expand Down Expand Up @@ -568,6 +615,8 @@ function wp_get_layout_style( $selector, $layout, $has_block_gap_support = false
* @return string Filtered block content.
*/
function wp_render_layout_support_flag( $block_content, $block ) {
static $global_styles = null;

$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
$block_supports_layout = block_has_support( $block_type, 'layout', false ) || block_has_support( $block_type, '__experimentalLayout', false );
$child_layout = $block['attrs']['style']['layout'] ?? null;
Expand Down Expand Up @@ -804,6 +853,18 @@ function wp_render_layout_support_flag( $block_content, $block ) {
$block_gap = $global_settings['spacing']['blockGap'] ?? null;
$has_block_gap_support = isset( $block_gap );

// Get default blockGap value from global styles for use in layouts like grid.
// Check block-specific styles first, then fall back to root styles.
$block_name = $block['blockName'] ?? '';
if ( null === $global_styles ) {
$global_styles = wp_get_global_styles();
}
$global_block_gap_value = $global_styles['blocks'][ $block_name ]['spacing']['blockGap'] ?? ( $global_styles['spacing']['blockGap'] ?? null );

if ( null !== $global_block_gap_value ) {
$fallback_gap_value = $global_block_gap_value;
}

/*
* Generates a unique ID based on all the data required to obtain the
* corresponding layout style. Keeps the CSS class names the same
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

<div class="wp-block-columns has-3-columns is-layout-flex wp-container-1d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-columns has-3-columns is-layout-flex wp-container-1f761849 wp-block-columns-is-layout-flex">

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Columns block hashes changed due to updates this PR makes to flex layout gap calculation,


<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

<div class="wp-block-columns has-3-columns is-layout-flex wp-container-1d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-columns has-3-columns is-layout-flex wp-container-1f761849 wp-block-columns-is-layout-flex">

<p class="layout-column-1">Column One, Paragraph One</p>

Expand Down
36 changes: 23 additions & 13 deletions tests/phpunit/tests/block-supports/layout.php
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ public function data_layout_support_flag_renders_classnames_on_wrapper() {
),
),
),
'expected_output' => '<div class="wp-block-group is-horizontal is-nowrap is-layout-flex wp-container-core-group-is-layout-67f0b8e2 wp-block-group-is-layout-flex"></div>',
'expected_output' => '<div class="wp-block-group is-horizontal is-nowrap is-layout-flex wp-container-core-group-is-layout-ee7b5020 wp-block-group-is-layout-flex"></div>',
),
'single wrapper block layout with grid type' => array(
'args' => array(
Expand All @@ -312,7 +312,7 @@ public function data_layout_support_flag_renders_classnames_on_wrapper() {
),
),
),
'expected_output' => '<div class="wp-block-group is-layout-grid wp-container-core-group-is-layout-9649a0d9 wp-block-group-is-layout-grid"></div>',
'expected_output' => '<div class="wp-block-group is-layout-grid wp-container-core-group-is-layout-9d260ee2 wp-block-group-is-layout-grid"></div>',
),
'skip classname output if block does not support layout and there are no child layout classes to be output' => array(
'args' => array(
Expand Down Expand Up @@ -542,9 +542,19 @@ public function test_layout_support_flag_renders_consistent_container_hash( $blo
$processor = new WP_HTML_Tag_Processor( $output );
$processor->next_tag();

$this->assertTrue(
$processor->has_class( $expected_class ),
"Expected class '$expected_class' not found in the rendered output, probably because of a different hash."
// Extract the actual container class from the output for better error messages.
$actual_class = '';
foreach ( $processor->class_list() as $class_name ) {
if ( str_starts_with( $class_name, 'wp-container-core-group-is-layout-' ) ) {
$actual_class = $class_name;
break;
}
}

$this->assertEquals(
$expected_class,
$actual_class,
'Expected class not found in the rendered output, probably because of a different hash.'
);
}

Expand All @@ -566,7 +576,7 @@ public function data_layout_support_flag_renders_consistent_container_hash() {
),
),
),
'expected_class' => 'wp-container-core-group-is-layout-c5c7d83f',
'expected_class' => 'wp-container-core-group-is-layout-a6248535',
),
'default type block gap 24px' => array(
'block_attributes' => array(
Expand All @@ -579,7 +589,7 @@ public function data_layout_support_flag_renders_consistent_container_hash() {
),
),
),
'expected_class' => 'wp-container-core-group-is-layout-634f0b9d',
'expected_class' => 'wp-container-core-group-is-layout-61b496ee',
),
'constrained type justified left' => array(
'block_attributes' => array(
Expand All @@ -588,7 +598,7 @@ public function data_layout_support_flag_renders_consistent_container_hash() {
'justifyContent' => 'left',
),
),
'expected_class' => 'wp-container-core-group-is-layout-12dd3699',
'expected_class' => 'wp-container-core-group-is-layout-54d22900',
),
'constrained type justified right' => array(
'block_attributes' => array(
Expand All @@ -597,7 +607,7 @@ public function data_layout_support_flag_renders_consistent_container_hash() {
'justifyContent' => 'right',
),
),
'expected_class' => 'wp-container-core-group-is-layout-f1f2ed93',
'expected_class' => 'wp-container-core-group-is-layout-2910ada7',
),
'flex type horizontal' => array(
'block_attributes' => array(
Expand All @@ -607,7 +617,7 @@ public function data_layout_support_flag_renders_consistent_container_hash() {
'flexWrap' => 'nowrap',
),
),
'expected_class' => 'wp-container-core-group-is-layout-2487dcaa',
'expected_class' => 'wp-container-core-group-is-layout-f5d79bea',
),
'flex type vertical' => array(
'block_attributes' => array(
Expand All @@ -616,15 +626,15 @@ public function data_layout_support_flag_renders_consistent_container_hash() {
'orientation' => 'vertical',
),
),
'expected_class' => 'wp-container-core-group-is-layout-fe9cc265',
'expected_class' => 'wp-container-core-group-is-layout-2c90304e',
),
'grid type' => array(
'block_attributes' => array(
'layout' => array(
'type' => 'grid',
),
),
'expected_class' => 'wp-container-core-group-is-layout-478b6e6b',
'expected_class' => 'wp-container-core-group-is-layout-5a23bf8e',
),
'grid type 3 columns' => array(
'block_attributes' => array(
Expand All @@ -633,7 +643,7 @@ public function data_layout_support_flag_renders_consistent_container_hash() {
'columnCount' => 3,
),
),
'expected_class' => 'wp-container-core-group-is-layout-d3b710ac',
'expected_class' => 'wp-container-core-group-is-layout-cda6dc4f',
),
);
}
Expand Down
Loading