Skip to content

Commit

Permalink
The commit tries to ensure that backgroundImage style objects are not…
Browse files Browse the repository at this point in the history
… merged, but replaced when merged theme.json configs. So, for example, an incoming config such as a saved user config should overwrite the background styles of the base theme.json, where it exists.
  • Loading branch information
ramonjd committed Aug 15, 2024
1 parent fb65340 commit cb34d72
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 35 deletions.
27 changes: 21 additions & 6 deletions lib/class-wp-theme-json-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -2491,14 +2491,8 @@ protected static function get_property_value( $styles, $path, $theme_json = null
* This converts references to a path to the value at that path
* where the value is an array with a "ref" key, pointing to a path.
* For example: { "ref": "style.color.background" } => "#fff".
* In the case of backgroundImage, if both a ref and a URL are present in the value,
* the URL takes precedence and the ref is ignored.
*/
if ( is_array( $value ) && isset( $value['ref'] ) ) {
if ( isset( $value['url'] ) ) {
unset( $value['ref'] );
return $value;
}
$value_path = explode( '.', $value['ref'] );
$ref_value = _wp_array_get( $theme_json, $value_path, null );
// Background Image refs can refer to a string or an array containing a URL string.
Expand Down Expand Up @@ -3264,6 +3258,27 @@ public function merge( $incoming ) {
}
}
}

$blocks_metadata = static::get_blocks_metadata();
$style_nodes = static::get_style_nodes(
$incoming_data,
$blocks_metadata,
array(
'include_block_style_variations' => true,
)
);
foreach ( $style_nodes as $style_node ) {
$path = $style_node['path'];
/*
* Background image styles should be replaced, not merged,
* as they themselves are specific object definitions for the style.
*/
$background_image_path = array_merge( $path, static::PROPERTIES_METADATA['background-image'] );
$content = _wp_array_get( $incoming_data, $background_image_path, null );
if ( isset( $content ) ) {
_wp_array_set( $this->theme_json, $background_image_path, $content );
}
}
}

/**
Expand Down
14 changes: 0 additions & 14 deletions packages/block-editor/src/components/global-styles/test/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -444,20 +444,6 @@ describe( 'editor utils', () => {
{ url: 'file:./assets/image.jpg' },
themeJson,
],
/*
* Merged theme.json and global styles retain the "ref" value,
* even though the URL is provided in the global styles.
*/
[
{
ref: 'styles.background.backgroundImage',
url: 'https://wordpress.org/assets/image.jpg',
},
{
url: 'https://wordpress.org/assets/image.jpg',
},
themeJson,
],
[
{
ref: 'styles.blocks.core/group.background.backgroundImage',
Expand Down
7 changes: 0 additions & 7 deletions packages/block-editor/src/components/global-styles/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -566,15 +566,8 @@ export function getResolvedRefValue( ruleValue, tree ) {
* This converts references to a path to the value at that path
* where the value is an array with a "ref" key, pointing to a path.
* For example: { "ref": "style.color.background" } => "#fff".
* In the case of backgroundImage, if both a ref and a URL are present in the value,
* the URL takes precedence and the ref is ignored.
*/
if ( typeof ruleValue !== 'string' && ruleValue?.ref ) {
if ( 'string' === typeof ruleValue?.url ) {
delete ruleValue.ref;
return ruleValue;
}

const refPath = ruleValue.ref.split( '.' );
const resolvedRuleValue = getCSSValueFromRawStyle(
getValueFromObjectPath( tree, refPath )
Expand Down
19 changes: 16 additions & 3 deletions packages/editor/src/components/global-styles-provider/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,23 @@ const { GlobalStylesContext, cleanEmptyObject } = unlock(

export function mergeBaseAndUserConfigs( base, user ) {
return deepmerge( base, user, {
// We only pass as arrays the presets,
// in which case we want the new array of values
// to override the old array (no merging).
/*
* We only pass as arrays the presets,
* in which case we want the new array of values
* to override the old array (no merging).
*/
isMergeableObject: isPlainObject,
/*
* Exceptions to the above rule.
* Background images should be replaced, not merged,
* as they themselves are specific object definitions for the style.
*/
customMerge: ( key ) => {
if ( key === 'backgroundImage' ) {
return ( baseConfig, userConfig ) => userConfig;
}
return undefined;
},
} );
}

Expand Down
109 changes: 104 additions & 5 deletions phpunit/class-wp-theme-json-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -2294,6 +2294,110 @@ public function test_merge_incoming_data_presets_use_default_names() {
$this->assertSameSetsWithIndex( $expected, $actual );
}

public function test_merge_incoming_styles() {
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'styles' => array(
'background' => array(
'backgroundImage' => array(
'url' => 'http://example.org/quote.png',
),
'backgroundSize' => 'cover',
),
'typography' => array(
'fontSize' => '10px',
),
'core/group' => array(
'background' => array(
'backgroundImage' => array(
'ref' => 'styles.blocks.core/verse.background.backgroundImage',
),
'backgroundAttachment' => 'fixed',
),
),
'core/quote' => array(
'background' => array(
'backgroundImage' => array(
'url' => 'http://example.org/quote.png',
),
'backgroundAttachment' => array(
'ref' => 'styles.blocks.core/group.background.backgroundAttachment',
),
),
),
'core/verse' => array(
'background' => array(
'backgroundImage' => "url(''http://example.org/verse.png')",
),
),
),
)
);

$update_background_image_styles = array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'styles' => array(
'background' => array(
'backgroundSize' => 'contain',
),
'typography' => array(
'fontSize' => '12px',
),
'blocks' => array(
'core/group' => array(
'background' => array(
'backgroundImage' => array(
'url' => 'http://example.org/group.png',
),
),
),
'core/verse' => array(
'background' => array(
'backgroundImage' => array(
'ref' => 'styles.blocks.core/group.background.backgroundImage',
),
),
),
),
),
);
$expected = array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'styles' => array(
'background' => array(
'backgroundImage' => array(
'url' => 'http://example.org/quote.png',
),
'backgroundSize' => 'contain',
),
'typography' => array(
'fontSize' => '12px',
),
'blocks' => array(
'core/group' => array(
'background' => array(
'backgroundImage' => array(
'url' => 'http://example.org/group.png',
),
),
),
'core/verse' => array(
'background' => array(
'backgroundImage' => array(
'ref' => 'styles.blocks.core/group.background.backgroundImage',
),
),
),
),
),
);
$theme_json->merge( new WP_Theme_JSON_Gutenberg( $update_background_image_styles ) );
$actual = $theme_json->get_raw_data();

$this->assertEqualSetsWithIndex( $expected, $actual );
}

public function test_remove_insecure_properties_removes_unsafe_styles() {
$actual = WP_Theme_JSON_Gutenberg::remove_insecure_properties(
array(
Expand Down Expand Up @@ -4936,12 +5040,7 @@ public function test_get_resolved_background_image_styles() {
'core/group' => array(
'background' => array(
'backgroundImage' => array(
/*
* Merged theme.json and global styles retain the "ref" value,
* even though the URL is provided in the global styles.
*/
'id' => 123,
'ref' => 'styles.background.backgroundImage',
'url' => 'http://example.org/group.png',
),
),
Expand Down

0 comments on commit cb34d72

Please sign in to comment.