Block Editor: Update color merging algorithm.

The npm packages in use were published a few hours ago, which include some changes to how we manage colors. This commit adds the corresponding PHP changes.

Props nosolosw.
See #53175.
Built from https://develop.svn.wordpress.org/trunk@50977


git-svn-id: http://core.svn.wordpress.org/trunk@50586 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
jorgefilipecosta
2021-05-24 18:57:55 +00:00
parent 0a75462702
commit 9b67649f40
3 changed files with 114 additions and 42 deletions

View File

@@ -1017,34 +1017,82 @@ class WP_Theme_JSON {
*
* @param WP_Theme_JSON $incoming Data to merge.
*/
public function merge( $incoming ) {
public function merge( $incoming, $update_or_remove = 'remove' ) {
$incoming_data = $incoming->get_raw_data();
$existing_data = $this->theme_json;
// The array_replace_recursive algorithm merges at the leaf level.
// For leaf values that are arrays it will use the numeric indexes for replacement.
$this->theme_json = array_replace_recursive( $this->theme_json, $incoming_data );
/*
* The array_replace_recursive algorithm merges at the leaf level.
* For leaf values that are arrays it will use the numeric indexes for replacement.
* In those cases, what we want is to use the incoming value, if it exists.
*
* These are the cases that have array values at the leaf levels.
*/
$properties = array();
$properties[] = array( 'color', 'palette' );
$properties[] = array( 'color', 'gradients' );
$properties[] = array( 'custom' );
$properties[] = array( 'spacing', 'units' );
$properties[] = array( 'typography', 'fontSizes' );
$properties[] = array( 'typography', 'fontFamilies' );
// There are a few cases in which we want to merge things differently
// from what array_replace_recursive does.
// Some incoming properties should replace the existing.
$to_replace = array();
$to_replace[] = array( 'custom' );
$to_replace[] = array( 'spacing', 'units' );
$to_replace[] = array( 'typography', 'fontSizes' );
$to_replace[] = array( 'typography', 'fontFamilies' );
// Some others should be appended to the existing.
// If the slug is the same than an existing element,
// the $update_or_remove param is used to decide
// what to do with the existing element:
// either remove it and append the incoming,
// or update it with the incoming.
$to_append = array();
$to_append[] = array( 'color', 'duotone' );
$to_append[] = array( 'color', 'gradients' );
$to_append[] = array( 'color', 'palette' );
$nodes = self::get_setting_nodes( $this->theme_json );
foreach ( $nodes as $metadata ) {
foreach ( $properties as $property_path ) {
$path = array_merge( $metadata['path'], $property_path );
foreach ( $to_replace as $path_to_replace ) {
$path = array_merge( $metadata['path'], $path_to_replace );
$node = _wp_array_get( $incoming_data, $path, array() );
if ( ! empty( $node ) ) {
_wp_array_set( $this->theme_json, $path, $node );
}
}
foreach ( $to_append as $path_to_append ) {
$path = array_merge( $metadata['path'], $path_to_append );
$incoming_node = _wp_array_get( $incoming_data, $path, array() );
$existing_node = _wp_array_get( $existing_data, $path, array() );
if ( empty( $incoming_node ) && empty( $existing_node ) ) {
continue;
}
$index_table = array();
$existing_slugs = array();
$merged = array();
foreach ( $existing_node as $key => $value ) {
$index_table[ $value['slug'] ] = $key;
$existing_slugs[] = $value['slug'];
$merged[ $key ] = $value;
}
$to_remove = array();
foreach ( $incoming_node as $value ) {
if ( ! in_array( $value['slug'], $existing_slugs, true ) ) {
$merged[] = $value;
} elseif ( 'update' === $update_or_remove ) {
$merged[ $index_table[ $value['slug'] ] ] = $value;
} else {
$merged[] = $value;
$to_remove[] = $index_table[ $value['slug'] ];
}
}
// Remove the duplicated values and pack the sparsed array.
foreach ( $to_remove as $index ) {
unset( $merged[ $index ] );
}
$merged = array_values( $merged );
_wp_array_set( $this->theme_json, $path, $merged );
}
}
}