Skip to content

Commit

Permalink
Backport from WordPress Core: improve performance of WP_Theme_JSON::m…
Browse files Browse the repository at this point in the history
…erge when merging background styles (#66002)

Backporting the current state of WordPress/wordpress-develop#7486 and adding tests.

Co-authored-by: ramonjd <[email protected]>
Co-authored-by: mukeshpanchal27 <[email protected]>
Co-authored-by: felixarntz <[email protected]>
Co-authored-by: andrewserong < [email protected]>
Co-authored-by: joemcgill < [email protected]>
  • Loading branch information
6 people authored and ciampo committed Oct 14, 2024
1 parent d3d11b1 commit 5dedf71
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 37 deletions.
106 changes: 69 additions & 37 deletions lib/class-wp-theme-json-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -2723,9 +2723,12 @@ private static function update_separator_declarations( $declarations ) {
*
* @param array $theme_json The theme.json converted to an array.
* @param array $selectors Optional list of selectors per block.
* @param array $options An array of options to facilitate filtering node generation
* The options currently supported are:
* - `include_block_style_variations` which includes CSS for block style variations.
* @param array $options {
* Optional. An array of options for now used for internal purposes only (may change without notice).
*
* @type bool $include_block_style_variations Includes nodes for block style variations. Default false.
* @type bool $include_node_paths_only Return only block nodes node paths. Default false.
* }
* @return array The block nodes in theme.json.
*/
private static function get_block_nodes( $theme_json, $selectors = array(), $options = array() ) {
Expand All @@ -2740,56 +2743,81 @@ private static function get_block_nodes( $theme_json, $selectors = array(), $opt
return $nodes;
}

foreach ( $theme_json['styles']['blocks'] as $name => $node ) {
$selector = null;
if ( isset( $selectors[ $name ]['selector'] ) ) {
$selector = $selectors[ $name ]['selector'];
}
$include_variations = $options['include_block_style_variations'] ?? false;
$include_node_paths_only = $options['include_node_paths_only'] ?? false;

$duotone_selector = null;
if ( isset( $selectors[ $name ]['duotone'] ) ) {
$duotone_selector = $selectors[ $name ]['duotone'];
}
foreach ( $theme_json['styles']['blocks'] as $name => $node ) {
$node_path = array( 'styles', 'blocks', $name );
if ( $include_node_paths_only ) {
$nodes[] = array(
'path' => $node_path,
);
} else {
$selector = null;
if ( isset( $selectors[ $name ]['selector'] ) ) {
$selector = $selectors[ $name ]['selector'];
}

$feature_selectors = null;
if ( isset( $selectors[ $name ]['selectors'] ) ) {
$feature_selectors = $selectors[ $name ]['selectors'];
}
$duotone_selector = null;
if ( isset( $selectors[ $name ]['duotone'] ) ) {
$duotone_selector = $selectors[ $name ]['duotone'];
}

$variation_selectors = array();
$include_variations = $options['include_block_style_variations'] ?? false;
if ( $include_variations && isset( $node['variations'] ) ) {
foreach ( $node['variations'] as $variation => $node ) {
$variation_selectors[] = array(
'path' => array( 'styles', 'blocks', $name, 'variations', $variation ),
'selector' => $selectors[ $name ]['styleVariations'][ $variation ],
);
$feature_selectors = null;
if ( isset( $selectors[ $name ]['selectors'] ) ) {
$feature_selectors = $selectors[ $name ]['selectors'];
}
}

$nodes[] = array(
'name' => $name,
'path' => array( 'styles', 'blocks', $name ),
'selector' => $selector,
'selectors' => $feature_selectors,
'duotone' => $duotone_selector,
'variations' => $variation_selectors,
'css' => $selector,
);
$variation_selectors = array();

if ( $include_variations && isset( $node['variations'] ) ) {
foreach ( $node['variations'] as $variation => $node ) {
$variation_selectors[] = array(
'path' => array( 'styles', 'blocks', $name, 'variations', $variation ),
'selector' => $selectors[ $name ]['styleVariations'][ $variation ],
);
}
}

$nodes[] = array(
'name' => $name,
'path' => $node_path,
'selector' => $selector,
'selectors' => $feature_selectors,
'duotone' => $duotone_selector,
'variations' => $variation_selectors,
'css' => $selector,
);
}
if ( isset( $theme_json['styles']['blocks'][ $name ]['elements'] ) ) {
foreach ( $theme_json['styles']['blocks'][ $name ]['elements'] as $element => $node ) {
$node_path = array( 'styles', 'blocks', $name, 'elements', $element );
if ( $include_node_paths_only ) {
$nodes[] = array(
'path' => $node_path,
);
continue;
}

$nodes[] = array(
'path' => array( 'styles', 'blocks', $name, 'elements', $element ),
'path' => $node_path,
'selector' => $selectors[ $name ]['elements'][ $element ],
);

// Handle any pseudo selectors for the element.
if ( isset( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element ] ) ) {
foreach ( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element ] as $pseudo_selector ) {
if ( isset( $theme_json['styles']['blocks'][ $name ]['elements'][ $element ][ $pseudo_selector ] ) ) {
$node_path = array( 'styles', 'blocks', $name, 'elements', $element );
if ( $include_node_paths_only ) {
$nodes[] = array(
'path' => $node_path,
);
continue;
}

$nodes[] = array(
'path' => array( 'styles', 'blocks', $name, 'elements', $element ),
'path' => $node_path,
'selector' => static::append_to_selector( $selectors[ $name ]['elements'][ $element ], $pseudo_selector ),
);
}
Expand Down Expand Up @@ -3264,7 +3292,11 @@ public function merge( $incoming ) {
* some values provide exceptions, namely style values that are
* objects and represent unique definitions for the style.
*/
$style_nodes = static::get_styles_block_nodes();
$style_nodes = static::get_block_nodes(
$this->theme_json,
array(),
array( 'include_node_paths_only' => true )
);
foreach ( $style_nodes as $style_node ) {
$path = $style_node['path'];
/*
Expand Down
52 changes: 52 additions & 0 deletions phpunit/class-wp-theme-json-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -5726,4 +5726,56 @@ public function test_opt_in_to_block_style_variations() {

$this->assertEquals( $expected, $button_variations );
}

/**
* This test covers `get_block_nodes` with the `$include_node_paths_only` option.
* When `true`, `$include_node_paths_only` should return only the paths of the block nodes.
*/
public function test_return_block_node_paths() {
$theme_json = new ReflectionClass( 'WP_Theme_JSON_Gutenberg' );

$func = $theme_json->getMethod( 'get_block_nodes' );
$func->setAccessible( true );

$theme_json = array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'styles' => array(
'typography' => array(
'fontSize' => '16px',
),
'blocks' => array(
'core/button' => array(
'color' => array(
'background' => 'red',
),
),
'core/group' => array(
'elements' => array(
'link' => array(
'color' => array(
'background' => 'blue',
),
),
),
),
),
),
);

$block_nodes = $func->invoke( null, $theme_json, array(), array( 'include_node_paths_only' => true ) );

$expected = array(
array(
'path' => array( 'styles', 'blocks', 'core/button' ),
),
array(
'path' => array( 'styles', 'blocks', 'core/group' ),
),
array(
'path' => array( 'styles', 'blocks', 'core/group', 'elements', 'link' ),
),
);

$this->assertEquals( $expected, $block_nodes );
}
}

0 comments on commit 5dedf71

Please sign in to comment.