summaryrefslogtreecommitdiffstats
path: root/wp-includes/class-wp-theme-json.php
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--wp-includes/class-wp-theme-json.php215
1 files changed, 190 insertions, 25 deletions
diff --git a/wp-includes/class-wp-theme-json.php b/wp-includes/class-wp-theme-json.php
index e5f1741..d754da9 100644
--- a/wp-includes/class-wp-theme-json.php
+++ b/wp-includes/class-wp-theme-json.php
@@ -204,10 +204,12 @@ class WP_Theme_JSON {
* @since 6.2.0 Added `outline-*`, and `min-height` properties.
* @since 6.3.0 Added `column-count` property.
* @since 6.4.0 Added `writing-mode` property.
+ * @since 6.5.0 Added `aspect-ratio` property.
*
* @var array
*/
const PROPERTIES_METADATA = array(
+ 'aspect-ratio' => array( 'dimensions', 'aspectRatio' ),
'background' => array( 'color', 'gradient' ),
'background-color' => array( 'color', 'background' ),
'border-radius' => array( 'border', 'radius' ),
@@ -344,6 +346,8 @@ class WP_Theme_JSON {
* @since 6.3.0 Added support for `typography.textColumns`, removed `layout.definitions`.
* @since 6.4.0 Added support for `layout.allowEditing`, `background.backgroundImage`,
* `typography.writingMode`, `lightbox.enabled` and `lightbox.allowEditing`.
+ * @since 6.5.0 Added support for `layout.allowCustomContentAndWideSize`,
+ * `background.backgroundSize` and `dimensions.aspectRatio`.
* @var array
*/
const VALID_SETTINGS = array(
@@ -351,6 +355,7 @@ class WP_Theme_JSON {
'useRootPaddingAwareAlignments' => null,
'background' => array(
'backgroundImage' => null,
+ 'backgroundSize' => null,
),
'border' => array(
'color' => null,
@@ -377,12 +382,14 @@ class WP_Theme_JSON {
),
'custom' => null,
'dimensions' => array(
- 'minHeight' => null,
+ 'aspectRatio' => null,
+ 'minHeight' => null,
),
'layout' => array(
- 'contentSize' => null,
- 'wideSize' => null,
- 'allowEditing' => null,
+ 'contentSize' => null,
+ 'wideSize' => null,
+ 'allowEditing' => null,
+ 'allowCustomContentAndWideSize' => null,
),
'lightbox' => array(
'enabled' => null,
@@ -422,6 +429,38 @@ class WP_Theme_JSON {
),
);
+ /*
+ * The valid properties for fontFamilies under settings key.
+ *
+ * @since 6.5.0
+ *
+ * @var array
+ */
+ const FONT_FAMILY_SCHEMA = array(
+ array(
+ 'fontFamily' => null,
+ 'name' => null,
+ 'slug' => null,
+ 'fontFace' => array(
+ array(
+ 'ascentOverride' => null,
+ 'descentOverride' => null,
+ 'fontDisplay' => null,
+ 'fontFamily' => null,
+ 'fontFeatureSettings' => null,
+ 'fontStyle' => null,
+ 'fontStretch' => null,
+ 'fontVariationSettings' => null,
+ 'fontWeight' => null,
+ 'lineGapOverride' => null,
+ 'sizeAdjust' => null,
+ 'src' => null,
+ 'unicodeRange' => null,
+ ),
+ ),
+ ),
+ );
+
/**
* The valid properties under the styles key.
*
@@ -434,6 +473,7 @@ class WP_Theme_JSON {
* updated `blockGap` to be allowed at any level.
* @since 6.2.0 Added `outline`, and `minHeight` properties.
* @since 6.3.0 Added support for `typography.textColumns`.
+ * @since 6.5.0 Added support for `dimensions.aspectRatio`.
*
* @var array
*/
@@ -454,7 +494,8 @@ class WP_Theme_JSON {
'text' => null,
),
'dimensions' => array(
- 'minHeight' => null,
+ 'aspectRatio' => null,
+ 'minHeight' => null,
),
'filter' => array(
'duotone' => null,
@@ -548,6 +589,52 @@ class WP_Theme_JSON {
);
/**
+ * Return the input schema at the root and per origin.
+ *
+ * @since 6.5.0
+ *
+ * @param array $schema The base schema.
+ * @return array The schema at the root and per origin.
+ *
+ * Example:
+ * schema_in_root_and_per_origin(
+ * array(
+ * 'fontFamily' => null,
+ * 'slug' => null,
+ * )
+ * )
+ *
+ * Returns:
+ * array(
+ * 'fontFamily' => null,
+ * 'slug' => null,
+ * 'default' => array(
+ * 'fontFamily' => null,
+ * 'slug' => null,
+ * ),
+ * 'blocks' => array(
+ * 'fontFamily' => null,
+ * 'slug' => null,
+ * ),
+ * 'theme' => array(
+ * 'fontFamily' => null,
+ * 'slug' => null,
+ * ),
+ * 'custom' => array(
+ * 'fontFamily' => null,
+ * 'slug' => null,
+ * ),
+ * )
+ */
+ protected static function schema_in_root_and_per_origin( $schema ) {
+ $schema_in_root_and_per_origin = $schema;
+ foreach ( static::VALID_ORIGINS as $origin ) {
+ $schema_in_root_and_per_origin[ $origin ] = $schema;
+ }
+ return $schema_in_root_and_per_origin;
+ }
+
+ /**
* Returns a class name by an element name.
*
* @since 6.1.0
@@ -571,10 +658,12 @@ class WP_Theme_JSON {
* @since 6.0.0
* @since 6.2.0 Added `dimensions.minHeight` and `position.sticky`.
* @since 6.4.0 Added `background.backgroundImage`.
+ * @since 6.5.0 Added `background.backgroundSize` and `dimensions.aspectRatio`.
* @var array
*/
const APPEARANCE_TOOLS_OPT_INS = array(
array( 'background', 'backgroundImage' ),
+ array( 'background', 'backgroundSize' ),
array( 'border', 'color' ),
array( 'border', 'radius' ),
array( 'border', 'style' ),
@@ -583,6 +672,7 @@ class WP_Theme_JSON {
array( 'color', 'heading' ),
array( 'color', 'button' ),
array( 'color', 'caption' ),
+ array( 'dimensions', 'aspectRatio' ),
array( 'dimensions', 'minHeight' ),
array( 'position', 'sticky' ),
array( 'spacing', 'blockGap' ),
@@ -785,11 +875,12 @@ class WP_Theme_JSON {
$schema_styles_blocks[ $block ]['variations'] = $schema_styles_variations;
}
- $schema['styles'] = static::VALID_STYLES;
- $schema['styles']['blocks'] = $schema_styles_blocks;
- $schema['styles']['elements'] = $schema_styles_elements;
- $schema['settings'] = static::VALID_SETTINGS;
- $schema['settings']['blocks'] = $schema_settings_blocks;
+ $schema['styles'] = static::VALID_STYLES;
+ $schema['styles']['blocks'] = $schema_styles_blocks;
+ $schema['styles']['elements'] = $schema_styles_elements;
+ $schema['settings'] = static::VALID_SETTINGS;
+ $schema['settings']['blocks'] = $schema_settings_blocks;
+ $schema['settings']['typography']['fontFamilies'] = static::schema_in_root_and_per_origin( static::FONT_FAMILY_SCHEMA );
// Remove anything that's not present in the schema.
foreach ( array( 'styles', 'settings' ) as $subtree ) {
@@ -929,7 +1020,7 @@ class WP_Theme_JSON {
if ( $duotone_support ) {
$root_selector = wp_get_block_css_selector( $block_type );
- $duotone_selector = WP_Theme_JSON::scope_selector( $root_selector, $duotone_support );
+ $duotone_selector = static::scope_selector( $root_selector, $duotone_support );
}
}
@@ -941,8 +1032,7 @@ class WP_Theme_JSON {
if ( ! empty( $block_type->styles ) ) {
$style_selectors = array();
foreach ( $block_type->styles as $style ) {
- // The style variation classname is duplicated in the selector to ensure that it overrides core block styles.
- $style_selectors[ $style['name'] ] = static::append_to_selector( '.is-style-' . $style['name'] . '.is-style-' . $style['name'], static::$blocks_metadata[ $block_name ]['selector'] );
+ $style_selectors[ $style['name'] ] = static::get_block_style_variation_selector( $style['name'], static::$blocks_metadata[ $block_name ]['selector'] );
}
static::$blocks_metadata[ $block_name ]['styleVariations'] = $style_selectors;
}
@@ -963,24 +1053,40 @@ class WP_Theme_JSON {
* @return array The modified $tree.
*/
protected static function remove_keys_not_in_schema( $tree, $schema ) {
- $tree = array_intersect_key( $tree, $schema );
+ if ( ! is_array( $tree ) ) {
+ return $tree;
+ }
- foreach ( $schema as $key => $data ) {
- if ( ! isset( $tree[ $key ] ) ) {
+ foreach ( $tree as $key => $value ) {
+ // Remove keys not in the schema or with null/empty values.
+ if ( ! array_key_exists( $key, $schema ) ) {
+ unset( $tree[ $key ] );
continue;
}
- if ( is_array( $schema[ $key ] ) && is_array( $tree[ $key ] ) ) {
- $tree[ $key ] = static::remove_keys_not_in_schema( $tree[ $key ], $schema[ $key ] );
-
- if ( empty( $tree[ $key ] ) ) {
+ if ( is_array( $schema[ $key ] ) ) {
+ if ( ! is_array( $value ) ) {
unset( $tree[ $key ] );
+ } elseif ( wp_is_numeric_array( $value ) ) {
+ // If indexed, process each item in the array.
+ foreach ( $value as $item_key => $item_value ) {
+ if ( isset( $schema[ $key ][0] ) && is_array( $schema[ $key ][0] ) ) {
+ $tree[ $key ][ $item_key ] = self::remove_keys_not_in_schema( $item_value, $schema[ $key ][0] );
+ } else {
+ // If the schema does not define a further structure, keep the value as is.
+ $tree[ $key ][ $item_key ] = $item_value;
+ }
+ }
+ } else {
+ // If associative, process as a single object.
+ $tree[ $key ] = self::remove_keys_not_in_schema( $value, $schema[ $key ] );
+
+ if ( empty( $tree[ $key ] ) ) {
+ unset( $tree[ $key ] );
+ }
}
- } elseif ( is_array( $schema[ $key ] ) && ! is_array( $tree[ $key ] ) ) {
- unset( $tree[ $key ] );
}
}
-
return $tree;
}
@@ -1064,6 +1170,7 @@ class WP_Theme_JSON {
foreach ( $style_nodes as &$node ) {
$node['selector'] = static::scope_selector( $options['scope'], $node['selector'] );
}
+ unset( $node );
}
if ( ! empty( $options['root_selector'] ) ) {
@@ -1071,7 +1178,7 @@ class WP_Theme_JSON {
$setting_nodes[ $root_settings_key ]['selector'] = $options['root_selector'];
}
if ( false !== $root_style_key ) {
- $setting_nodes[ $root_style_key ]['selector'] = $options['root_selector'];
+ $style_nodes[ $root_style_key ]['selector'] = $options['root_selector'];
}
}
@@ -1915,6 +2022,7 @@ class WP_Theme_JSON {
* @since 5.8.0
* @since 5.9.0 Added the `$settings` and `$properties` parameters.
* @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.
*
* @param array $styles Styles to process.
* @param array $settings Theme settings.
@@ -1986,6 +2094,15 @@ class WP_Theme_JSON {
$value = wp_get_typography_font_size_value( array( 'size' => $value ) );
}
+ if ( 'aspect-ratio' === $css_property ) {
+ // For aspect ratio to work, other dimensions rules must be unset.
+ // This ensures that a fixed height does not override the aspect ratio.
+ $declarations[] = array(
+ 'name' => 'min-height',
+ 'value' => 'unset',
+ );
+ }
+
$declarations[] = array(
'name' => $css_property,
'value' => $value,
@@ -3390,7 +3507,15 @@ class WP_Theme_JSON {
|| ! is_numeric( $spacing_scale['mediumStep'] )
|| ( '+' !== $spacing_scale['operator'] && '*' !== $spacing_scale['operator'] ) ) {
if ( ! empty( $spacing_scale ) ) {
- trigger_error( __( 'Some of the theme.json settings.spacing.spacingScale values are invalid' ), E_USER_NOTICE );
+ trigger_error(
+ sprintf(
+ /* translators: 1: theme.json, 2: settings.spacing.spacingScale */
+ __( 'Some of the %1$s %2$s values are invalid' ),
+ 'theme.json',
+ 'settings.spacing.spacingScale'
+ ),
+ E_USER_NOTICE
+ );
}
return null;
}
@@ -3713,12 +3838,18 @@ class WP_Theme_JSON {
* Replaces CSS variables with their values in place.
*
* @since 6.3.0
+ * @since 6.5.0 Check for empty style before processing its value.
+ *
* @param array $styles CSS declarations to convert.
* @param array $values key => value pairs to use for replacement.
* @return array
*/
private static function convert_variables_to_value( $styles, $values ) {
foreach ( $styles as $key => $style ) {
+ if ( empty( $style ) ) {
+ continue;
+ }
+
if ( is_array( $style ) ) {
$styles[ $key ] = self::convert_variables_to_value( $style, $values );
continue;
@@ -3781,4 +3912,38 @@ class WP_Theme_JSON {
$theme_json->theme_json['styles'] = self::convert_variables_to_value( $styles, $vars );
return $theme_json;
}
+
+ /**
+ * Generates a selector for a block style variation.
+ *
+ * @since 6.5.0
+ *
+ * @param string $variation_name Name of the block style variation.
+ * @param string $block_selector CSS selector for the block.
+ * @return string Block selector with block style variation selector added to it.
+ */
+ protected static function get_block_style_variation_selector( $variation_name, $block_selector ) {
+ $variation_class = ".is-style-$variation_name";
+
+ if ( ! $block_selector ) {
+ return $variation_class;
+ }
+
+ $limit = 1;
+ $selector_parts = explode( ',', $block_selector );
+ $result = array();
+
+ foreach ( $selector_parts as $part ) {
+ $result[] = preg_replace_callback(
+ '/((?::\([^)]+\))?\s*)([^\s:]+)/',
+ function ( $matches ) use ( $variation_class ) {
+ return $matches[1] . $matches[2] . $variation_class;
+ },
+ $part,
+ $limit
+ );
+ }
+
+ return implode( ',', $result );
+ }
}