Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
Add backport for the bugfix
  • Loading branch information
cbravobernal committed Nov 3, 2022
commit e4bbc98c74da31aeb1f0c8f749d0b741c283a091
52 changes: 52 additions & 0 deletions src/wp-includes/class-wp-theme-json.php
Original file line number Diff line number Diff line change
Expand Up @@ -1925,6 +1925,53 @@ public function get_styles_block_nodes() {
return static::get_block_nodes( $this->theme_json );
}

/**
* Returns a filtered declarations array if there is a separator block with only a background
* style defined in theme.json by adding a color attribute to reflect the changes in the front.
*
* @since 6.1.0
*
* @param array $declarations List of declarations.
*
* @return array $declarations List of declarations filtered.
*/
private static function update_separator_declarations( $declarations ) {
$background_matches = array_values(
array_filter(
$declarations,
function( $declaration ) {
return 'background-color' === $declaration['name'];
}
)
);
Copy link
Contributor

Choose a reason for hiding this comment

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

I committed something similar a few months back, and learned that array_filter goes over every item in the array. Refactoring these as foreachs with a break after the first found instance is a nice little optimization.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm there are multiple array_filter()s iterating over the same dataset. This means the entire dataset is iterated each and every array_filter() in this method.

Combining all of the array_filter() circuits into one iterator, such as foreach(), means the $declarations array is walked 1 time instead of N times (N = each array_filter()).

Granted, this means refactoring and re-testing the code to be more performant. Likely not something that can happen before 6.1.1-RC.

Copy link
Contributor

Choose a reason for hiding this comment

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

@hellofromtonya I've refactored this to match your suggestions(at least as best as I understand them).

How does this look to you now? Any further improvements we can make?

Copy link
Member

Choose a reason for hiding this comment

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

@dream-encode I agree with @hellofromtonya, I think we can avoid using array_filter() here entirely and rather use a single foreach. Worth adding that also array_values() has a cost which we can avoid as well.

Given that #3555 is focused on optimizing performance by reducing excessive usage of array functions, it would feel counterproductive if we at the same time introduced new ones here.

IMO we can even have only a single foreach loop for the entire method, iterating through $declarations and checking for all three things (the first background-color value, whether there are border-color matches, and whether there are color matches).

if ( ! empty( $background_matches && isset( $background_matches[0]['value'] ) ) ) {
$border_color_matches = array_values(
array_filter(
$declarations,
function( $declaration ) {
return 'border-color' === $declaration['name'];
}
)
);
$text_color_matches = array_values(
array_filter(
$declarations,
function( $declaration ) {
return 'color' === $declaration['name'];
}
)
);
if ( empty( $border_color_matches ) && empty( $text_color_matches ) ) {
$declarations[] = array(
'name' => 'color',
'value' => $background_matches[0]['value'],
);
}
}

return $declarations;
}

/**
* An internal method to get the block nodes from a theme.json file.
*
Expand Down Expand Up @@ -2101,6 +2148,11 @@ function( $pseudo_selector ) use ( $selector ) {
}
}

// Update declarations if there are separators with only background color defined.
if ( '.wp-block-separator' === $selector ) {
$declarations = static::update_separator_declarations( $declarations );
}

// 2. Generate and append the rules that use the general selector.
$block_rules .= static::to_ruleset( $selector, $declarations );

Expand Down
114 changes: 114 additions & 0 deletions tests/phpunit/tests/theme/wpThemeJson.php
Original file line number Diff line number Diff line change
Expand Up @@ -3997,4 +3997,118 @@ function data_set_spacing_sizes_when_invalid() {
),
);
}

/**
* @ticket 56903
*/
function test_update_separator_declarations() {
// If only background is defined, test that includes border-color to the style so it is applied on the front end.
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'styles' => array(
'blocks' => array(
'core/separator' => array(
'color' => array(
'background' => 'blue',
),
),
),
),
),
'default'
);
$expected = 'body { margin: 0;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-block-separator{background-color: blue;color: blue;}';
$stylesheet = $theme_json->get_stylesheet( array( 'styles' ) );
$this->assertEquals( $expected, $stylesheet );

// If background and text are defined, do not include border-color, as text color is enough.
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'styles' => array(
'blocks' => array(
'core/separator' => array(
'color' => array(
'background' => 'blue',
'text' => 'red',
),
),
),
),
),
'default'
);
$expected = 'body { margin: 0;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-block-separator{background-color: blue;color: red;}';
$stylesheet = $theme_json->get_stylesheet( array( 'styles' ) );
$this->assertEquals( $expected, $stylesheet );

// If only text is defined, do not include border-color, as by itself is enough.
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'styles' => array(
'blocks' => array(
'core/separator' => array(
'color' => array(
'text' => 'red',
),
),
),
),
),
'default'
);
$expected = 'body { margin: 0;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-block-separator{color: red;}';
$stylesheet = $theme_json->get_stylesheet( array( 'styles' ) );
$this->assertEquals( $expected, $stylesheet );

// If background, text, and border-color are defined, include everything, CSS specifity will decide which to apply.
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'styles' => array(
'blocks' => array(
'core/separator' => array(
'color' => array(
'background' => 'blue',
'text' => 'red',
),
'border' => array(
'color' => 'pink',
),
),
),
),
),
'default'
);
$expected = 'body { margin: 0;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-block-separator{background-color: blue;border-color: pink;color: red;}';
$stylesheet = $theme_json->get_stylesheet( array( 'styles' ) );
$this->assertEquals( $expected, $stylesheet );

// If background and border color are defined, include everything, CSS specifity will decide which to apply.
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'styles' => array(
'blocks' => array(
'core/separator' => array(
'color' => array(
'background' => 'blue',
),
'border' => array(
'color' => 'pink',
),
),
),
),
),
'default'
);
$expected = 'body { margin: 0;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-block-separator{background-color: blue;border-color: pink;}';
$stylesheet = $theme_json->get_stylesheet( array( 'styles' ) );
$this->assertEquals( $expected, $stylesheet );

}
}