Skip to content

Commit

Permalink
Background images: add support for theme.json ref value resolution (#…
Browse files Browse the repository at this point in the history
…64128)

Resolves refs before passing styles to style engine in the WP_Theme_JSON class. Consolidates all resolutions in the background panel (image and ref). Removes useGlobalStyleLinks completely. Delete theme URI utils.
Ensures that backgroundImage style objects are not merged, but replaced when merged theme.json configs. For example, an incoming config such as a saved user config should overwrite the background styles of the base theme.json, where it exists.

---------

Co-authored-by: ramonjd <ramonopoly@git.wordpress.org>
Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org>
Co-authored-by: andrewserong <andrewserong@git.wordpress.org>
Co-authored-by: kevin940726 <kevin940726@git.wordpress.org>
  • Loading branch information
5 people committed Aug 15, 2024
1 parent e6057ce commit d669eb6
Show file tree
Hide file tree
Showing 15 changed files with 313 additions and 136 deletions.
1 change: 1 addition & 0 deletions backport-changelog/6.7/7137.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
https://github.com/WordPress/wordpress-develop/pull/7137

* https://github.com/WordPress/gutenberg/pull/64128
* https://github.com/WordPress/gutenberg/pull/64192
* https://github.com/WordPress/gutenberg/pull/64328
68 changes: 49 additions & 19 deletions lib/class-wp-theme-json-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -2329,7 +2329,7 @@ protected static function flatten_tree( $tree, $prefix = '', $token = '--' ) {
* ```php
* array(
* 'name' => 'property_name',
* 'value' => 'property_value,
* 'value' => 'property_value',
* )
* ```
*
Expand All @@ -2338,6 +2338,7 @@ protected static function flatten_tree( $tree, $prefix = '', $token = '--' ) {
* @since 6.1.0 Added `$theme_json`, `$selector`, and `$use_root_padding` parameters.
* @since 6.5.0 Output a `min-height: unset` rule when `aspect-ratio` is set.
* @since 6.6.0 Passing current theme JSON settings to wp_get_typography_font_size_value(). Using style engine to correctly fetch background CSS values.
* @since 6.7.0 Allow ref resolution of background properties.
*
* @param array $styles Styles to process.
* @param array $settings Theme settings.
Expand Down Expand Up @@ -2381,21 +2382,28 @@ protected static function compute_style_properties( $styles, $settings = array()
$root_variable_duplicates[] = substr( $css_property, $root_style_length );
}

// Processes background styles.
if ( 'background' === $value_path[0] && isset( $styles['background'] ) ) {
/*
* For user-uploaded images at the block level, assign defaults.
* Matches defaults applied in the editor and in block supports: background.php.
*/
if ( static::ROOT_BLOCK_SELECTOR !== $selector && ! empty( $styles['background']['backgroundImage']['id'] ) ) {
$styles['background']['backgroundSize'] = $styles['background']['backgroundSize'] ?? 'cover';
// If the background size is set to `contain` and no position is set, set the position to `center`.
if ( 'contain' === $styles['background']['backgroundSize'] && empty( $styles['background']['backgroundPosition'] ) ) {
$styles['background']['backgroundPosition'] = '50% 50%';
}
/*
* Processes background image styles.
* If the value is a URL, it will be converted to a CSS `url()` value.
* For an uploaded image (images with a database ID), apply size and position
* defaults equal to those applied in block supports in lib/background.php.
*/
if ( 'background-image' === $css_property && ! empty( $value ) ) {
$background_styles = gutenberg_style_engine_get_styles(
array( 'background' => array( 'backgroundImage' => $value ) )
);

$value = $background_styles['declarations'][ $css_property ];
}
if ( empty( $value ) && static::ROOT_BLOCK_SELECTOR !== $selector && ! empty( $styles['background']['backgroundImage']['id'] ) ) {
if ( 'background-size' === $css_property ) {
$value = 'cover';
}
// If the background size is set to `contain` and no position is set, set the position to `center`.
if ( 'background-position' === $css_property ) {
$background_size = $styles['background']['backgroundSize'] ?? null;
$value = 'contain' === $background_size ? '50% 50%' : null;
}
$background_styles = gutenberg_style_engine_get_styles( array( 'background' => $styles['background'] ) );
$value = $background_styles['declarations'][ $css_property ] ?? $value;
}

// Skip if empty and not "0" or value represents array of longhand values.
Expand Down Expand Up @@ -2463,6 +2471,7 @@ protected static function compute_style_properties( $styles, $settings = array()
* @since 5.8.0
* @since 5.9.0 Added support for values of array type, which are returned as is.
* @since 6.1.0 Added the `$theme_json` parameter.
* @since 6.7.0 Added support for background image refs
*
* @param array $styles Styles subtree.
* @param array $path Which property to process.
Expand All @@ -2479,15 +2488,17 @@ 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 values is an array with a "ref" key, pointing to a path.
* Where the current value is an array with a 'ref' key pointing
* to a path, this converts that path into the value at that path.
* For example: { "ref": "style.color.background" } => "#fff".
*/
if ( is_array( $value ) && isset( $value['ref'] ) ) {
$value_path = explode( '.', $value['ref'] );
$ref_value = _wp_array_get( $theme_json, $value_path );
$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.
$ref_value_url = $ref_value['url'] ?? null;
// Only use the ref value if we find anything.
if ( ! empty( $ref_value ) && is_string( $ref_value ) ) {
if ( ! empty( $ref_value ) && ( is_string( $ref_value ) || is_string( $ref_value_url ) ) ) {
$value = $ref_value;
}

Expand Down Expand Up @@ -3247,6 +3258,25 @@ public function merge( $incoming ) {
}
}
}

/*
* Style values are merged at the leaf level, however
* some values provide exceptions, namely style values that are
* objects and represent unique definitions for the style.
*/
$style_nodes = static::get_styles_block_nodes();
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
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
useRef,
useState,
useEffect,
useMemo,
} from '@wordpress/element';
import { useDispatch, useSelect } from '@wordpress/data';
import { focus } from '@wordpress/dom';
Expand All @@ -42,11 +43,15 @@ import { isBlobURL } from '@wordpress/blob';
/**
* Internal dependencies
*/
import { useToolsPanelDropdownMenuProps } from './utils';
import { useToolsPanelDropdownMenuProps, getResolvedValue } from './utils';
import { setImmutably } from '../../utils/object';
import MediaReplaceFlow from '../media-replace-flow';
import { store as blockEditorStore } from '../../store';
import { getResolvedThemeFilePath } from './theme-file-uri-utils';

import {
globalStylesDataKey,
globalStylesLinksDataKey,
} from '../../store/private-keys';

const IMAGE_BACKGROUND_TYPE = 'image';
const DEFAULT_CONTROLS = {
Expand Down Expand Up @@ -270,7 +275,6 @@ function BackgroundImageControls( {
onRemoveImage = noop,
onResetImage = noop,
displayInPanel,
themeFileURIs,
defaultValues,
} ) {
const mediaUpload = useSelect(
Expand Down Expand Up @@ -404,10 +408,7 @@ function BackgroundImageControls( {
name={
<InspectorImagePreviewItem
className="block-editor-global-styles-background-panel__image-preview"
imgUrl={ getResolvedThemeFilePath(
url,
themeFileURIs
) }
imgUrl={ url }
filename={ title }
label={ imgLabel }
/>
Expand Down Expand Up @@ -449,7 +450,6 @@ function BackgroundSizeControls( {
style,
inheritedValue,
defaultValues,
themeFileURIs,
} ) {
const sizeValue =
style?.background?.backgroundSize ||
Expand Down Expand Up @@ -587,7 +587,7 @@ function BackgroundSizeControls( {
<FocalPointPicker
__nextHasNoMarginBottom
label={ __( 'Focal point' ) }
url={ getResolvedThemeFilePath( imageValue, themeFileURIs ) }
url={ imageValue }
value={ backgroundPositionToCoords( backgroundPositionValue ) }
onChange={ updateBackgroundPosition }
/>
Expand Down Expand Up @@ -697,8 +697,44 @@ export default function BackgroundPanel( {
defaultControls = DEFAULT_CONTROLS,
defaultValues = {},
headerLabel = __( 'Background image' ),
themeFileURIs,
} ) {
/*
* Resolve any inherited "ref" pointers.
* Should the block editor need resolved, inherited values
* across all controls, this could be abstracted into a hook,
* e.g., useResolveGlobalStyle
*/
const { globalStyles, _links } = useSelect( ( select ) => {
const { getSettings } = select( blockEditorStore );
const _settings = getSettings();
return {
globalStyles: _settings[ globalStylesDataKey ],
_links: _settings[ globalStylesLinksDataKey ],
};
}, [] );
const resolvedInheritedValue = useMemo( () => {
const resolvedValues = {
background: {},
};

if ( ! inheritedValue?.background ) {
return inheritedValue;
}

Object.entries( inheritedValue?.background ).forEach(
( [ key, backgroundValue ] ) => {
resolvedValues.background[ key ] = getResolvedValue(
backgroundValue,
{
styles: globalStyles,
_links,
}
);
}
);
return resolvedValues;
}, [ globalStyles, _links, inheritedValue ] );

const resetAllFilter = useCallback( ( previousValue ) => {
return {
...previousValue,
Expand All @@ -710,11 +746,11 @@ export default function BackgroundPanel( {
onChange( setImmutably( value, [ 'background' ], {} ) );

const { title, url } = value?.background?.backgroundImage || {
...inheritedValue?.background?.backgroundImage,
...resolvedInheritedValue?.background?.backgroundImage,
};
const hasImageValue =
hasBackgroundImageValue( value ) ||
hasBackgroundImageValue( inheritedValue );
hasBackgroundImageValue( resolvedInheritedValue );

const imageValue =
value?.background?.backgroundImage ||
Expand Down Expand Up @@ -756,19 +792,15 @@ export default function BackgroundPanel( {
<BackgroundControlsPanel
label={ title }
filename={ title }
url={ getResolvedThemeFilePath(
url,
themeFileURIs
) }
url={ url }
onToggle={ setIsDropDownOpen }
hasImageValue={ hasImageValue }
>
<VStack spacing={ 3 } className="single-column">
<BackgroundImageControls
onChange={ onChange }
style={ value }
inheritedValue={ inheritedValue }
themeFileURIs={ themeFileURIs }
inheritedValue={ resolvedInheritedValue }
displayInPanel
onResetImage={ () => {
setIsDropDownOpen( false );
Expand All @@ -784,17 +816,15 @@ export default function BackgroundPanel( {
panelId={ panelId }
style={ value }
defaultValues={ defaultValues }
inheritedValue={ inheritedValue }
themeFileURIs={ themeFileURIs }
inheritedValue={ resolvedInheritedValue }
/>
</VStack>
</BackgroundControlsPanel>
) : (
<BackgroundImageControls
onChange={ onChange }
style={ value }
inheritedValue={ inheritedValue }
themeFileURIs={ themeFileURIs }
inheritedValue={ resolvedInheritedValue }
defaultValues={ defaultValues }
onResetImage={ () => {
setIsDropDownOpen( false );
Expand Down
5 changes: 0 additions & 5 deletions packages/block-editor/src/components/global-styles/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,11 +209,6 @@ export function useGlobalStyle(
return [ result, setStyle ];
}

export function useGlobalStyleLinks() {
const { merged: mergedConfig } = useContext( GlobalStylesContext );
return mergedConfig?._links;
}

/**
* React hook that overrides a global settings object with block and element specific settings.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ export {
useGlobalSetting,
useGlobalStyle,
useSettingsForBlockElement,
useGlobalStyleLinks,
} from './hooks';
export { getBlockCSSSelector } from './get-block-css-selector';
export {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -1008,9 +1008,23 @@ describe( 'global styles renderer', () => {
ref: 'styles.elements.h1.typography.letterSpacing',
},
},
background: {
backgroundImage: {
ref: 'styles.background.backgroundImage',
},
backgroundSize: {
ref: 'styles.background.backgroundSize',
},
},
};
const tree = {
styles: {
background: {
backgroundImage: {
url: 'http://my-image.org/image.gif',
},
backgroundSize: 'cover',
},
elements: {
h1: {
typography: {
Expand All @@ -1026,6 +1040,8 @@ describe( 'global styles renderer', () => {
).toEqual( [
'font-size: var(--wp--preset--font-size--xx-large)',
'letter-spacing: 2px',
"background-image: url( 'http://my-image.org/image.gif' )",
'background-size: cover',
] );
} );
it( 'should set default values for block background styles', () => {
Expand Down
Loading

0 comments on commit d669eb6

Please sign in to comment.