From 668c31e7d040c3ab25a48adb4166186d21def63d Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Mon, 3 Jun 2024 11:51:13 -0500 Subject: [PATCH 01/27] Backport 58409 class-wp-theme-json.php --- src/wp-includes/class-wp-theme-json.php | 70 ++++++++++++++----------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/src/wp-includes/class-wp-theme-json.php b/src/wp-includes/class-wp-theme-json.php index 9aa2b97b8b274..c23096de50d2e 100644 --- a/src/wp-includes/class-wp-theme-json.php +++ b/src/wp-includes/class-wp-theme-json.php @@ -124,6 +124,7 @@ class WP_Theme_JSON { * @since 6.2.0 Added 'shadow' presets. * @since 6.3.0 Replaced value_func for duotone with `null`. Custom properties are handled by class-wp-duotone.php. * @since 6.6.0 Added the `dimensions.aspectRatios` & `dimensions.defaultAspectRatios` preset. + * @since 6.6.0 Updated the 'prevent_override' value for font size presets to use 'typography.defaultFontSizes'. * @var array */ const PRESETS_METADATA = array( @@ -169,7 +170,7 @@ class WP_Theme_JSON { ), array( 'path' => array( 'typography', 'fontSizes' ), - 'prevent_override' => false, + 'prevent_override' => array( 'typography', 'defaultFontSizes' ), 'use_default_names' => true, 'value_func' => 'wp_get_typography_font_size_value', 'css_vars' => '--wp--preset--font-size--$slug', @@ -379,6 +380,7 @@ class WP_Theme_JSON { * @since 6.5.0 Added support for `layout.allowCustomContentAndWideSize`, * `background.backgroundSize` and `dimensions.aspectRatio`. * @since 6.6.0 Added support for `dimensions.aspectRatios` and `dimensions.defaultAspectRatios`. + * @since 6.6.0 Added support for `typography.defaultFontSizes`. * @var array */ const VALID_SETTINGS = array( @@ -446,20 +448,21 @@ class WP_Theme_JSON { 'defaultPresets' => null, ), 'typography' => array( - 'fluid' => null, - 'customFontSize' => null, - 'dropCap' => null, - 'fontFamilies' => null, - 'fontSizes' => null, - 'fontStyle' => null, - 'fontWeight' => null, - 'letterSpacing' => null, - 'lineHeight' => null, - 'textAlign' => null, - 'textColumns' => null, - 'textDecoration' => null, - 'textTransform' => null, - 'writingMode' => null, + 'fluid' => null, + 'customFontSize' => null, + 'defaultFontSizes' => null, + 'dropCap' => null, + 'fontFamilies' => null, + 'fontSizes' => null, + 'fontStyle' => null, + 'fontWeight' => null, + 'letterSpacing' => null, + 'lineHeight' => null, + 'textAlign' => null, + 'textColumns' => null, + 'textDecoration' => null, + 'textTransform' => null, + 'writingMode' => null, ), ); @@ -728,9 +731,10 @@ public static function get_element_class_name( $element ) { * * @since 5.8.0 * @since 5.9.0 Changed value from 1 to 2. + * @since 6.6.0 Changed value from 2 to 3. * @var int */ - const LATEST_SCHEMA = 2; + const LATEST_SCHEMA = 3; /** * Constructor. @@ -741,7 +745,7 @@ public static function get_element_class_name( $element ) { * @param string $origin Optional. What source of data this object represents. * One of 'default', 'theme', or 'custom'. Default 'theme'. */ - public function __construct( $theme_json = array(), $origin = 'theme' ) { + public function __construct( $theme_json = array( 'version' => WP_Theme_JSON::LATEST_SCHEMA ), $origin = 'theme' ) { if ( ! in_array( $origin, static::VALID_ORIGINS, true ) ) { $origin = 'theme'; } @@ -2951,12 +2955,15 @@ public function merge( $incoming ) { } // Replace the presets. - foreach ( static::PRESETS_METADATA as $preset ) { - $override_preset = ! static::get_metadata_boolean( $this->theme_json['settings'], $preset['prevent_override'], true ); + foreach ( static::PRESETS_METADATA as $preset_metadata ) { + $prevent_override = $preset_metadata['prevent_override']; + if ( is_array( $prevent_override ) ) { + $prevent_override = _wp_array_get( $this->theme_json['settings'], $preset_metadata['prevent_override'] ); + } foreach ( static::VALID_ORIGINS as $origin ) { $base_path = $node['path']; - foreach ( $preset['path'] as $leaf ) { + foreach ( $preset_metadata['path'] as $leaf ) { $base_path[] = $leaf; } @@ -2968,7 +2975,8 @@ public function merge( $incoming ) { continue; } - if ( 'theme' === $origin && $preset['use_default_names'] ) { + // Set names for theme presets based on the slug if they are not set and can use default names. + if ( 'theme' === $origin && $preset_metadata['use_default_names'] ) { foreach ( $content as $key => $item ) { if ( ! isset( $item['name'] ) ) { $name = static::get_name_from_defaults( $item['slug'], $base_path ); @@ -2979,19 +2987,17 @@ public function merge( $incoming ) { } } - if ( - ( 'theme' !== $origin ) || - ( 'theme' === $origin && $override_preset ) - ) { - _wp_array_set( $this->theme_json, $path, $content ); - } else { - $slugs_node = static::get_default_slugs( $this->theme_json, $node['path'] ); - $slugs = array_merge_recursive( $slugs_global, $slugs_node ); + // Filter out default slugs from theme presets when defaults should not be overridden. + if ( 'theme' === $origin && $prevent_override ) { + $slugs_node = static::get_default_slugs( $this->theme_json, $node['path'] ); + $preset_global = _wp_array_get( $slugs_global, $preset_metadata['path'], array() ); + $preset_node = _wp_array_get( $slugs_node, $preset_metadata['path'], array() ); + $preset_slugs = array_merge_recursive( $preset_global, $preset_node ); - $slugs_for_preset = _wp_array_get( $slugs, $preset['path'], array() ); - $content = static::filter_slugs( $content, $slugs_for_preset ); - _wp_array_set( $this->theme_json, $path, $content ); + $content = static::filter_slugs( $content, $preset_slugs ); } + + _wp_array_set( $this->theme_json, $path, $content ); } } } From 4c0218453b6a92437954ea6cf531bccc723eba9f Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Thu, 23 May 2024 11:28:15 -0500 Subject: [PATCH 02/27] Backport 58409 class-wp-theme-json-schema.php --- .../class-wp-theme-json-schema.php | 61 ++++++++++++++++++- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/class-wp-theme-json-schema.php b/src/wp-includes/class-wp-theme-json-schema.php index 46712a032bc2b..91a4494522910 100644 --- a/src/wp-includes/class-wp-theme-json-schema.php +++ b/src/wp-includes/class-wp-theme-json-schema.php @@ -35,6 +35,7 @@ class WP_Theme_JSON_Schema { * Function that migrates a given theme.json structure to the last version. * * @since 5.9.0 + * @since 6.6.0 Migrate up to v3. * * @param array $theme_json The structure to migrate. * @@ -47,8 +48,14 @@ public static function migrate( $theme_json ) { ); } - if ( 1 === $theme_json['version'] ) { - $theme_json = self::migrate_v1_to_v2( $theme_json ); + // Migrate each version in order starting with the current version. + switch ( $theme_json['version'] ) { + case 1: + $theme_json = self::migrate_v1_to_v2( $theme_json ); + // no break + case 2: + $theme_json = self::migrate_v2_to_v3( $theme_json ); + // no break } return $theme_json; @@ -84,6 +91,56 @@ private static function migrate_v1_to_v2( $old ) { return $new; } + /** + * Migrates from v2 to v3. + * + * - Sets settings.typography.defaultFontSizes to false. + * + * @since 6.6.0 + * + * @param array $old Data to migrate. + * + * @return array Data with defaultFontSizes set to false. + */ + private static function migrate_v2_to_v3( $old ) { + // Copy everything. + $new = $old; + + // Set the new version. + $new['version'] = 3; + + /* + * Remaining changes do not need to be applied to the custom origin, + * as they should take on the value of the theme origin. + */ + if ( + isset( $new['isGlobalStylesUserThemeJSON'] ) && + true === $new['isGlobalStylesUserThemeJSON'] + ) { + return $new; + } + + /* + * Even though defaultFontSizes is a new setting, we need to migrate + * it as it controls the PRESETS_METADATA prevent_override which was + * previously hardcoded to false. This only needs to happen when the + * theme provided font sizes as they could match the default ones and + * affect the generated CSS. And in v2 we provided default font sizes + * when the theme did not provide any. + */ + if ( isset( $old['settings']['typography']['fontSizes'] ) ) { + if ( ! isset( $new['settings'] ) ) { + $new['settings'] = array(); + } + if ( ! isset( $new['settings']['typography'] ) ) { + $new['settings']['typography'] = array(); + } + $new['settings']['typography']['defaultFontSizes'] = false; + } + + return $new; + } + /** * Processes the settings subtree. * From a4e24a06e01f525a446a58178c554e44ffb988b5 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Thu, 23 May 2024 11:32:05 -0500 Subject: [PATCH 03/27] Backport 58409 class-wp-theme-json-data.php --- src/wp-includes/class-wp-theme-json-data.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wp-includes/class-wp-theme-json-data.php b/src/wp-includes/class-wp-theme-json-data.php index 30dab47185ca9..ca72ae81b5ab5 100644 --- a/src/wp-includes/class-wp-theme-json-data.php +++ b/src/wp-includes/class-wp-theme-json-data.php @@ -39,7 +39,7 @@ class WP_Theme_JSON_Data { * @param array $data Array following the theme.json specification. * @param string $origin The origin of the data: default, theme, user. */ - public function __construct( $data = array(), $origin = 'theme' ) { + public function __construct( $data = array( 'version' => WP_Theme_JSON::LATEST_SCHEMA ), $origin = 'theme' ) { $this->origin = $origin; $this->theme_json = new WP_Theme_JSON( $data, $this->origin ); } From 4696b352f3bb15fc70de1d95636f030dfc256949 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Thu, 23 May 2024 11:42:27 -0500 Subject: [PATCH 04/27] Backport 58409 class-wp-theme-json-resolver.php --- src/wp-includes/class-wp-theme-json-resolver.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/wp-includes/class-wp-theme-json-resolver.php b/src/wp-includes/class-wp-theme-json-resolver.php index 0bdf4a23db119..464a6cc4bf739 100644 --- a/src/wp-includes/class-wp-theme-json-resolver.php +++ b/src/wp-includes/class-wp-theme-json-resolver.php @@ -243,7 +243,7 @@ public static function get_theme_data( $deprecated = array(), $options = array() $theme_json_data = static::read_json_file( $theme_json_file ); $theme_json_data = static::translate( $theme_json_data, $wp_theme->get( 'TextDomain' ) ); } else { - $theme_json_data = array(); + $theme_json_data = array( 'version' => WP_Theme_JSON::LATEST_SCHEMA ); } /** @@ -359,7 +359,7 @@ public static function get_block_data() { return static::$blocks; } - $config = array( 'version' => 2 ); + $config = array( 'version' => WP_Theme_JSON::LATEST_SCHEMA ); foreach ( $blocks as $block_name => $block_type ) { if ( isset( $block_type->supports['__experimentalStyle'] ) ) { $config['styles']['blocks'][ $block_name ] = static::remove_json_comments( $block_type->supports['__experimentalStyle'] ); @@ -494,6 +494,7 @@ public static function get_user_data_from_wp_global_styles( $theme, $create_post * Returns the user's origin config. * * @since 5.9.0 + * @since 6.6.0 The 'isGlobalStylesUserThemeJSON' flag is left on the user data. * * @return WP_Theme_JSON Entity that holds styles for user data. */ @@ -531,14 +532,18 @@ public static function get_user_data() { isset( $decoded_data['isGlobalStylesUserThemeJSON'] ) && $decoded_data['isGlobalStylesUserThemeJSON'] ) { - unset( $decoded_data['isGlobalStylesUserThemeJSON'] ); $config = $decoded_data; } } /** This filter is documented in wp-includes/class-wp-theme-json-resolver.php */ - $theme_json = apply_filters( 'wp_theme_json_data_user', new WP_Theme_JSON_Data( $config, 'custom' ) ); - static::$user = $theme_json->get_theme_json(); + $theme_json = apply_filters( 'wp_theme_json_data_user', new WP_Theme_JSON_Data( $config, 'custom' ) ); + $config = $theme_json->get_data(); + + // Needs to be set for schema migrations of user data. + $config['isGlobalStylesUserThemeJSON'] = true; + + static::$user = new WP_Theme_JSON( $config, 'custom' ); return static::$user; } From 97a24e0985c4a5d7746acc9d9b59acd9a019615c Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Thu, 23 May 2024 11:45:05 -0500 Subject: [PATCH 05/27] Backport 58409 theme.json --- src/wp-includes/theme.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wp-includes/theme.json b/src/wp-includes/theme.json index 485d01247d636..0dbb0c5ba561f 100644 --- a/src/wp-includes/theme.json +++ b/src/wp-includes/theme.json @@ -1,6 +1,6 @@ { "$schema": "https://schemas.wp.org/trunk/theme.json", - "version": 2, + "version": 3, "settings": { "appearanceTools": false, "useRootPaddingAwareAlignments": false, @@ -276,6 +276,7 @@ }, "typography": { "customFontSize": true, + "defaultFontSizes": true, "dropCap": true, "fontSizes": [ { From 719a4bde14d2a09cf8fc6520dbbc57f9fe2f6cbe Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Thu, 23 May 2024 11:48:17 -0500 Subject: [PATCH 06/27] Backport 58409 PHPUnit wpThemeJsonSchema.php --- .../phpunit/tests/theme/wpThemeJsonSchema.php | 82 +++++++++++++++++-- 1 file changed, 77 insertions(+), 5 deletions(-) diff --git a/tests/phpunit/tests/theme/wpThemeJsonSchema.php b/tests/phpunit/tests/theme/wpThemeJsonSchema.php index cb5bb41780c68..dcd876908cb29 100644 --- a/tests/phpunit/tests/theme/wpThemeJsonSchema.php +++ b/tests/phpunit/tests/theme/wpThemeJsonSchema.php @@ -41,6 +41,18 @@ public function test_migrate_v1_to_latest() { 'width' => false, ), 'typography' => array( + 'fontSizes' => array( + array( + 'name' => 'Small', + 'slug' => 'small', + 'size' => 12, + ), + array( + 'name' => 'Normal', + 'slug' => 'normal', + 'size' => 16, + ), + ), 'fontStyle' => false, 'fontWeight' => false, 'letterSpacing' => false, @@ -126,11 +138,24 @@ public function test_migrate_v1_to_latest() { 'width' => false, ), 'typography' => array( - 'fontStyle' => false, - 'fontWeight' => false, - 'letterSpacing' => false, - 'textDecoration' => false, - 'textTransform' => false, + 'defaultFontSizes' => false, + 'fontSizes' => array( + array( + 'name' => 'Small', + 'slug' => 'small', + 'size' => 12, + ), + array( + 'name' => 'Normal', + 'slug' => 'normal', + 'size' => 16, + ), + ), + 'fontStyle' => false, + 'fontWeight' => false, + 'letterSpacing' => false, + 'textDecoration' => false, + 'textTransform' => false, ), 'blocks' => array( 'core/group' => array( @@ -185,4 +210,51 @@ public function test_migrate_v1_to_latest() { $this->assertEqualSetsWithIndex( $expected, $actual ); } + + public function test_migrate_v2_to_latest() { + $theme_json_v2 = array( + 'version' => 2, + 'settings' => array( + 'typography' => array( + 'fontSizes' => array( + array( + 'name' => 'Small', + 'slug' => 'small', + 'size' => 12, + ), + array( + 'name' => 'Normal', + 'slug' => 'normal', + 'size' => 16, + ), + ), + ), + ), + ); + + $actual = WP_Theme_JSON_Schema::migrate( $theme_json_v2 ); + + $expected = array( + 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'settings' => array( + 'typography' => array( + 'defaultFontSizes' => false, + 'fontSizes' => array( + array( + 'name' => 'Small', + 'slug' => 'small', + 'size' => 12, + ), + array( + 'name' => 'Normal', + 'slug' => 'normal', + 'size' => 16, + ), + ), + ), + ), + ); + + $this->assertEqualSetsWithIndex( $expected, $actual ); + } } From 9a0e4b4cc08a2992c40711f8c49c017ce0125984 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Thu, 23 May 2024 11:57:36 -0500 Subject: [PATCH 07/27] Backport 58409 PHPUnit wpThemeJson.php --- tests/phpunit/tests/theme/wpThemeJson.php | 80 ++++++++++------------- 1 file changed, 35 insertions(+), 45 deletions(-) diff --git a/tests/phpunit/tests/theme/wpThemeJson.php b/tests/phpunit/tests/theme/wpThemeJson.php index 5707e6a804a00..8bd99dde0a4d2 100644 --- a/tests/phpunit/tests/theme/wpThemeJson.php +++ b/tests/phpunit/tests/theme/wpThemeJson.php @@ -3300,7 +3300,7 @@ public function test_get_editor_settings_custom_units_can_be_filtered() { public function test_export_data() { $theme = new WP_Theme_JSON( array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'settings' => array( 'color' => array( 'palette' => array( @@ -3321,7 +3321,7 @@ public function test_export_data() { ); $user = new WP_Theme_JSON( array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'settings' => array( 'color' => array( 'palette' => array( @@ -3345,7 +3345,7 @@ public function test_export_data() { $theme->merge( $user ); $actual = $theme->get_data(); $expected = array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'settings' => array( 'color' => array( 'palette' => array( @@ -3378,7 +3378,7 @@ public function test_export_data() { public function test_export_data_deals_with_empty_user_data() { $theme = new WP_Theme_JSON( array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'settings' => array( 'color' => array( 'palette' => array( @@ -3400,7 +3400,7 @@ public function test_export_data_deals_with_empty_user_data() { $actual = $theme->get_data(); $expected = array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'settings' => array( 'color' => array( 'palette' => array( @@ -3428,7 +3428,7 @@ public function test_export_data_deals_with_empty_user_data() { public function test_export_data_deals_with_empty_theme_data() { $user = new WP_Theme_JSON( array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'settings' => array( 'color' => array( 'palette' => array( @@ -3451,7 +3451,7 @@ public function test_export_data_deals_with_empty_theme_data() { $actual = $user->get_data(); $expected = array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'settings' => array( 'color' => array( 'palette' => array( @@ -3477,25 +3477,15 @@ public function test_export_data_deals_with_empty_theme_data() { * @ticket 55505 */ public function test_export_data_deals_with_empty_data() { - $theme_v2 = new WP_Theme_JSON( - array( - 'version' => 2, - ), - 'theme' - ); - $actual_v2 = $theme_v2->get_data(); - $expected_v2 = array( 'version' => 2 ); - $this->assertEqualSetsWithIndex( $expected_v2, $actual_v2 ); - - $theme_v1 = new WP_Theme_JSON( + $theme = new WP_Theme_JSON( array( - 'version' => 1, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, ), 'theme' ); - $actual_v1 = $theme_v1->get_data(); - $expected_v1 = array( 'version' => 2 ); - $this->assertEqualSetsWithIndex( $expected_v1, $actual_v1 ); + $actual = $theme->get_data(); + $expected = array( 'version' => WP_Theme_JSON::LATEST_SCHEMA ); + $this->assertEqualSetsWithIndex( $expected, $actual ); } /** @@ -3504,7 +3494,7 @@ public function test_export_data_deals_with_empty_data() { public function test_export_data_sets_appearance_tools() { $theme = new WP_Theme_JSON( array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'settings' => array( 'appearanceTools' => true, 'blocks' => array( @@ -3518,7 +3508,7 @@ public function test_export_data_sets_appearance_tools() { $actual = $theme->get_data(); $expected = array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'settings' => array( 'appearanceTools' => true, 'blocks' => array( @@ -3538,7 +3528,7 @@ public function test_export_data_sets_appearance_tools() { public function test_export_data_sets_use_root_padding_aware_alignments() { $theme = new WP_Theme_JSON( array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'settings' => array( 'useRootPaddingAwareAlignments' => true, 'blocks' => array( @@ -3552,7 +3542,7 @@ public function test_export_data_sets_use_root_padding_aware_alignments() { $actual = $theme->get_data(); $expected = array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'settings' => array( 'useRootPaddingAwareAlignments' => true, 'blocks' => array( @@ -3644,7 +3634,7 @@ public function test_get_element_class_name_invalid() { public function test_get_property_value_valid() { $theme_json = new WP_Theme_JSON( array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'styles' => array( 'color' => array( 'background' => '#ffffff', @@ -3729,7 +3719,7 @@ public function data_get_property_value_should_return_string_for_invalid_paths_o public function test_get_property_value_loop() { $theme_json = new WP_Theme_JSON( array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'styles' => array( 'color' => array( 'background' => '#ffffff', @@ -3767,7 +3757,7 @@ public function test_get_property_value_loop() { public function test_get_property_value_recursion() { $theme_json = new WP_Theme_JSON( array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'styles' => array( 'color' => array( 'background' => '#ffffff', @@ -3804,7 +3794,7 @@ public function test_get_property_value_recursion() { public function test_get_property_value_self() { $theme_json = new WP_Theme_JSON( array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'styles' => array( 'color' => array( 'background' => '#ffffff', @@ -3830,7 +3820,7 @@ public function test_get_property_value_self() { public function test_get_styles_for_block_with_padding_aware_alignments() { $theme_json = new WP_Theme_JSON( array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'styles' => array( 'spacing' => array( 'padding' => array( @@ -3867,7 +3857,7 @@ public function test_get_styles_for_block_with_padding_aware_alignments() { public function test_get_styles_for_block_without_padding_aware_alignments() { $theme_json = new WP_Theme_JSON( array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'styles' => array( 'spacing' => array( 'padding' => array( @@ -3900,7 +3890,7 @@ public function test_get_styles_for_block_without_padding_aware_alignments() { public function test_get_styles_for_block_with_content_width() { $theme_json = new WP_Theme_JSON( array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'settings' => array( 'layout' => array( 'contentSize' => '800px', @@ -3931,7 +3921,7 @@ public function test_get_styles_for_block_with_content_width() { public function test_get_styles_with_appearance_tools() { $theme_json = new WP_Theme_JSON( array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'settings' => array( 'appearanceTools' => true, ), @@ -3954,7 +3944,7 @@ public function test_get_styles_with_appearance_tools() { public function test_sanitization() { $theme_json = new WP_Theme_JSON( array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'styles' => array( 'spacing' => array( 'blockGap' => 'valid value', @@ -3973,7 +3963,7 @@ public function test_sanitization() { $actual = $theme_json->get_raw_data(); $expected = array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'styles' => array( 'spacing' => array( 'blockGap' => 'valid value', @@ -3997,7 +3987,7 @@ public function test_sanitization() { public function test_sanitize_for_unregistered_style_variations() { $theme_json = new WP_Theme_JSON( array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'styles' => array( 'blocks' => array( 'core/quote' => array( @@ -4021,7 +4011,7 @@ public function test_sanitize_for_unregistered_style_variations() { $sanitized_theme_json = $theme_json->get_raw_data(); $expected = array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'styles' => array( 'blocks' => array( 'core/quote' => array( @@ -4050,7 +4040,7 @@ public function test_sanitize_for_unregistered_style_variations() { public function test_sanitize_for_block_with_style_variations( $theme_json_variations, $expected_sanitized ) { $theme_json = new WP_Theme_JSON( array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'styles' => array( 'blocks' => array( 'core/quote' => $theme_json_variations, @@ -4134,7 +4124,7 @@ public function data_sanitize_for_block_with_style_variations() { public function test_sanitize_indexed_arrays() { $theme_json = new WP_Theme_JSON( array( - 'version' => '2', + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'badKey2' => 'I am Evil!', 'settings' => array( 'badKey3' => 'I am Evil!', @@ -4202,7 +4192,7 @@ public function test_sanitize_indexed_arrays() { ); $expected_sanitized = array( - 'version' => '2', + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'settings' => array( 'typography' => array( 'fontFamilies' => array( @@ -4271,7 +4261,7 @@ public function test_sanitize_indexed_arrays() { public function test_sanitize_with_invalid_style_variation( $theme_json_variations ) { $theme_json = new WP_Theme_JSON( array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'styles' => array( 'blocks' => array( 'core/quote' => $theme_json_variations, @@ -4319,7 +4309,7 @@ public function data_sanitize_with_invalid_style_variation() { public function test_get_styles_for_block_with_style_variations( $theme_json_variations, $metadata_variations, $expected ) { $theme_json = new WP_Theme_JSON( array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'styles' => array( 'blocks' => array( 'core/quote' => $theme_json_variations, @@ -4473,7 +4463,7 @@ public function test_block_style_variations_with_invalid_properties() { public function test_set_spacing_sizes( $spacing_scale, $expected_output ) { $theme_json = new WP_Theme_JSON( array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'settings' => array( 'spacing' => array( 'spacingScale' => $spacing_scale, @@ -4767,7 +4757,7 @@ public function test_set_spacing_sizes_when_invalid( $spacing_scale, $expected_o $theme_json = new WP_Theme_JSON( array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'settings' => array( 'spacing' => array( 'spacingScale' => $spacing_scale, From 915f25452e69876e375169952895a6bc7365454e Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Thu, 23 May 2024 12:06:06 -0500 Subject: [PATCH 08/27] Backport 58409 PHPUnit rest-global-styles-controller.php --- .../tests/rest-api/rest-global-styles-controller.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/phpunit/tests/rest-api/rest-global-styles-controller.php b/tests/phpunit/tests/rest-api/rest-global-styles-controller.php index 6f920c9152bb4..02d3ec8d5a72c 100644 --- a/tests/phpunit/tests/rest-api/rest-global-styles-controller.php +++ b/tests/phpunit/tests/rest-api/rest-global-styles-controller.php @@ -150,7 +150,7 @@ public function test_get_theme_items() { $data = $response->get_data(); $expected = array( array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'settings' => array( 'blocks' => array( 'core/paragraph' => array( @@ -171,7 +171,7 @@ public function test_get_theme_items() { 'title' => 'variation-a', ), array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'settings' => array( 'blocks' => array( 'core/post-title' => array( @@ -216,7 +216,7 @@ public function test_get_theme_items() { ), ), array( - 'version' => 2, + 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'title' => 'Block theme variation', 'settings' => array( 'color' => array( From 2f9b431fa88db2e4786ce9b6ef91e062a57af3e3 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Thu, 23 May 2024 12:07:04 -0500 Subject: [PATCH 09/27] Backport 58409 PHPUnit data --- .../theme.json | 2 +- .../theme.json | 2 +- .../theme.json | 2 +- .../block-theme-child/styles/variation-a.json | 2 +- .../block-theme-child/styles/variation-b.json | 2 +- .../themedir1/block-theme-child/theme.json | 2 +- .../styles/variation.json | 44 +++--- .../block-theme-with-hooked-blocks/theme.json | 2 +- .../block-theme/styles/variation-a.json | 2 +- .../block-theme/styles/variation-b.json | 2 +- .../block-theme/styles/variation.json | 2 +- .../data/themedir1/block-theme/theme.json | 2 +- .../themedir1/empty-fontface-theme/theme.json | 146 ++++++++---------- .../styles/variation-duplicate-fonts.json | 2 +- .../styles/variation-new-font-family.json | 2 +- .../styles/variation-new-font-variations.json | 2 +- .../styles/variation-no-fonts.json | 2 +- .../themedir1/fonts-block-theme/theme.json | 2 +- 18 files changed, 106 insertions(+), 116 deletions(-) diff --git a/tests/phpunit/data/themedir1/block-theme-child-with-fluid-layout/theme.json b/tests/phpunit/data/themedir1/block-theme-child-with-fluid-layout/theme.json index 710ec336df70b..813024ba8abeb 100644 --- a/tests/phpunit/data/themedir1/block-theme-child-with-fluid-layout/theme.json +++ b/tests/phpunit/data/themedir1/block-theme-child-with-fluid-layout/theme.json @@ -1,6 +1,6 @@ { "$schema": "https://schemas.wp.org/trunk/theme.json", - "version": 2, + "version": 3, "settings": { "appearanceTools": true, "layout": { diff --git a/tests/phpunit/data/themedir1/block-theme-child-with-fluid-typography-config/theme.json b/tests/phpunit/data/themedir1/block-theme-child-with-fluid-typography-config/theme.json index dcd3745f1630c..3aa0560aaf062 100644 --- a/tests/phpunit/data/themedir1/block-theme-child-with-fluid-typography-config/theme.json +++ b/tests/phpunit/data/themedir1/block-theme-child-with-fluid-typography-config/theme.json @@ -1,6 +1,6 @@ { "$schema": "https://schemas.wp.org/trunk/theme.json", - "version": 2, + "version": 3, "settings": { "appearanceTools": true, "layout": { diff --git a/tests/phpunit/data/themedir1/block-theme-child-with-fluid-typography/theme.json b/tests/phpunit/data/themedir1/block-theme-child-with-fluid-typography/theme.json index 7b34524270295..b2624775a5003 100644 --- a/tests/phpunit/data/themedir1/block-theme-child-with-fluid-typography/theme.json +++ b/tests/phpunit/data/themedir1/block-theme-child-with-fluid-typography/theme.json @@ -1,6 +1,6 @@ { "$schema": "https://schemas.wp.org/trunk/theme.json", - "version": 2, + "version": 3, "settings": { "appearanceTools": true, "typography": { diff --git a/tests/phpunit/data/themedir1/block-theme-child/styles/variation-a.json b/tests/phpunit/data/themedir1/block-theme-child/styles/variation-a.json index a9d5ade894692..53c3ef60619b5 100644 --- a/tests/phpunit/data/themedir1/block-theme-child/styles/variation-a.json +++ b/tests/phpunit/data/themedir1/block-theme-child/styles/variation-a.json @@ -1,5 +1,5 @@ { - "version": 2, + "version": 3, "settings": { "blocks": { "core/paragraph": { diff --git a/tests/phpunit/data/themedir1/block-theme-child/styles/variation-b.json b/tests/phpunit/data/themedir1/block-theme-child/styles/variation-b.json index 0a8a4fcab99f6..4e949f24c7f40 100644 --- a/tests/phpunit/data/themedir1/block-theme-child/styles/variation-b.json +++ b/tests/phpunit/data/themedir1/block-theme-child/styles/variation-b.json @@ -1,5 +1,5 @@ { - "version": 2, + "version": 3, "settings": { "blocks": { "core/post-title": { diff --git a/tests/phpunit/data/themedir1/block-theme-child/theme.json b/tests/phpunit/data/themedir1/block-theme-child/theme.json index 1157fa9128030..185437e9b81c4 100644 --- a/tests/phpunit/data/themedir1/block-theme-child/theme.json +++ b/tests/phpunit/data/themedir1/block-theme-child/theme.json @@ -1,6 +1,6 @@ { "$schema": "https://schemas.wp.org/trunk/theme.json", - "version": 2, + "version": 3, "settings": { "color": { "palette": [ diff --git a/tests/phpunit/data/themedir1/block-theme-deprecated-path/styles/variation.json b/tests/phpunit/data/themedir1/block-theme-deprecated-path/styles/variation.json index ad3affb1152d6..06f672f6fd25d 100644 --- a/tests/phpunit/data/themedir1/block-theme-deprecated-path/styles/variation.json +++ b/tests/phpunit/data/themedir1/block-theme-deprecated-path/styles/variation.json @@ -1,23 +1,23 @@ { - "version": 2, - "settings": { - "color": { - "palette": [ - { - "slug": "foreground", - "color": "#3F67C6", - "name": "Foreground" - } - ] - } - }, - "styles": { - "blocks": { - "core/post-title": { - "typography": { - "fontWeight": "700" - } - } - } - } -} \ No newline at end of file + "version": 3, + "settings": { + "color": { + "palette": [ + { + "slug": "foreground", + "color": "#3F67C6", + "name": "Foreground" + } + ] + } + }, + "styles": { + "blocks": { + "core/post-title": { + "typography": { + "fontWeight": "700" + } + } + } + } +} diff --git a/tests/phpunit/data/themedir1/block-theme-with-hooked-blocks/theme.json b/tests/phpunit/data/themedir1/block-theme-with-hooked-blocks/theme.json index 28f3d7aa8443d..b4cfc5e80223a 100644 --- a/tests/phpunit/data/themedir1/block-theme-with-hooked-blocks/theme.json +++ b/tests/phpunit/data/themedir1/block-theme-with-hooked-blocks/theme.json @@ -1,6 +1,6 @@ { "$schema": "https://schemas.wp.org/trunk/theme.json", - "version": 2, + "version": 3, "templateParts": [ { "area": "header", diff --git a/tests/phpunit/data/themedir1/block-theme/styles/variation-a.json b/tests/phpunit/data/themedir1/block-theme/styles/variation-a.json index 42c20fc63b592..eb08d0090c177 100644 --- a/tests/phpunit/data/themedir1/block-theme/styles/variation-a.json +++ b/tests/phpunit/data/themedir1/block-theme/styles/variation-a.json @@ -1,5 +1,5 @@ { - "version": 2, + "version": 3, "settings": { "blocks": { "core/paragraph": { diff --git a/tests/phpunit/data/themedir1/block-theme/styles/variation-b.json b/tests/phpunit/data/themedir1/block-theme/styles/variation-b.json index 23e9cb2d63391..a670b9dcb2fa1 100644 --- a/tests/phpunit/data/themedir1/block-theme/styles/variation-b.json +++ b/tests/phpunit/data/themedir1/block-theme/styles/variation-b.json @@ -1,5 +1,5 @@ { - "version": 2, + "version": 3, "settings": { "blocks": { "core/post-title": { diff --git a/tests/phpunit/data/themedir1/block-theme/styles/variation.json b/tests/phpunit/data/themedir1/block-theme/styles/variation.json index d0f316cb454dd..debb3666a767b 100644 --- a/tests/phpunit/data/themedir1/block-theme/styles/variation.json +++ b/tests/phpunit/data/themedir1/block-theme/styles/variation.json @@ -1,5 +1,5 @@ { - "version": 2, + "version": 3, "title": "Block theme variation", "settings": { "color": { diff --git a/tests/phpunit/data/themedir1/block-theme/theme.json b/tests/phpunit/data/themedir1/block-theme/theme.json index fb24069fb6429..2c29884bf4dcb 100644 --- a/tests/phpunit/data/themedir1/block-theme/theme.json +++ b/tests/phpunit/data/themedir1/block-theme/theme.json @@ -1,6 +1,6 @@ { "$schema": "https://schemas.wp.org/trunk/theme.json", - "version": 2, + "version": 3, "title": "Block theme", "settings": { "color": { diff --git a/tests/phpunit/data/themedir1/empty-fontface-theme/theme.json b/tests/phpunit/data/themedir1/empty-fontface-theme/theme.json index 92b16631120f8..2b39f38dd66e4 100644 --- a/tests/phpunit/data/themedir1/empty-fontface-theme/theme.json +++ b/tests/phpunit/data/themedir1/empty-fontface-theme/theme.json @@ -1,89 +1,79 @@ { "$schema": "https://schemas.wp.org/trunk/theme.json", - "version": 2, - "customTemplates": [ - { - "name": "blank", - "title": "Blank", - "postTypes": [ - "page", - "post" - ] - } - ], - "settings": { - "appearanceTools": true, - "color": { - "duotone": [], - "gradients": [], - "palette": [] - }, - "custom": {}, - "spacing": { - "units": [ - "%", - "px", - "em", - "rem", - "vh", - "vw" - ] - }, - "typography": { - "dropCap": false, - "fontFamilies": [ + "version": 3, + "customTemplates": [ { - "fontFamily": "Roboto", - "name": "Roboto", - "slug": "roboto", - "fontFace": [] + "name": "blank", + "title": "Blank", + "postTypes": [ "page", "post" ] } - ], - "fontSizes": [ - { - "size": "1rem", - "slug": "small" + ], + "settings": { + "appearanceTools": true, + "color": { + "duotone": [], + "gradients": [], + "palette": [] }, - { - "size": "1.125rem", - "slug": "medium" + "custom": {}, + "spacing": { + "units": [ "%", "px", "em", "rem", "vh", "vw" ] }, - { - "size": "1.75rem", - "slug": "large" + "typography": { + "dropCap": false, + "fontFamilies": [ + { + "fontFamily": "Roboto", + "name": "Roboto", + "slug": "roboto", + "fontFace": [] + } + ], + "fontSizes": [ + { + "size": "1rem", + "slug": "small" + }, + { + "size": "1.125rem", + "slug": "medium" + }, + { + "size": "1.75rem", + "slug": "large" + }, + { + "size": "clamp(1.75rem, 3vw, 2.25rem)", + "slug": "x-large" + } + ] }, - { - "size": "clamp(1.75rem, 3vw, 2.25rem)", - "slug": "x-large" + "layout": { + "contentSize": "650px", + "wideSize": "1000px" } - ] }, - "layout": { - "contentSize": "650px", - "wideSize": "1000px" - } - }, - "styles": { - "blocks": {}, - "color": { - "background": "var(--wp--preset--color--background)", - "text": "var(--wp--preset--color--foreground)" - }, - "elements": {}, - "spacing": { - "blockGap": "1.5rem" + "styles": { + "blocks": {}, + "color": { + "background": "var(--wp--preset--color--background)", + "text": "var(--wp--preset--color--foreground)" + }, + "elements": {}, + "spacing": { + "blockGap": "1.5rem" + }, + "typography": { + "fontFamily": "var(--wp--preset--font-family--system-font)", + "lineHeight": "var(--wp--custom--typography--line-height--normal)", + "fontSize": "var(--wp--preset--font-size--medium)" + } }, - "typography": { - "fontFamily": "var(--wp--preset--font-family--system-font)", - "lineHeight": "var(--wp--custom--typography--line-height--normal)", - "fontSize": "var(--wp--preset--font-size--medium)" - } - }, - "templateParts": [ - { - "name": "header", - "title": "Header", - "area": "header" - } - ] + "templateParts": [ + { + "name": "header", + "title": "Header", + "area": "header" + } + ] } diff --git a/tests/phpunit/data/themedir1/fonts-block-theme/styles/variation-duplicate-fonts.json b/tests/phpunit/data/themedir1/fonts-block-theme/styles/variation-duplicate-fonts.json index 040689043379d..c24a4a85a4f67 100644 --- a/tests/phpunit/data/themedir1/fonts-block-theme/styles/variation-duplicate-fonts.json +++ b/tests/phpunit/data/themedir1/fonts-block-theme/styles/variation-duplicate-fonts.json @@ -1,5 +1,5 @@ { - "version": 2, + "version": 3, "title": "Variation: duplicate fonts", "settings": { "typography": { diff --git a/tests/phpunit/data/themedir1/fonts-block-theme/styles/variation-new-font-family.json b/tests/phpunit/data/themedir1/fonts-block-theme/styles/variation-new-font-family.json index 0af954cbecaa8..dfc83f3726d79 100644 --- a/tests/phpunit/data/themedir1/fonts-block-theme/styles/variation-new-font-family.json +++ b/tests/phpunit/data/themedir1/fonts-block-theme/styles/variation-new-font-family.json @@ -1,5 +1,5 @@ { - "version": 2, + "version": 3, "title": "Variation: new font family", "settings": { "typography": { diff --git a/tests/phpunit/data/themedir1/fonts-block-theme/styles/variation-new-font-variations.json b/tests/phpunit/data/themedir1/fonts-block-theme/styles/variation-new-font-variations.json index 81268817ade70..95cb7b88d0fb7 100644 --- a/tests/phpunit/data/themedir1/fonts-block-theme/styles/variation-new-font-variations.json +++ b/tests/phpunit/data/themedir1/fonts-block-theme/styles/variation-new-font-variations.json @@ -1,5 +1,5 @@ { - "version": 2, + "version": 3, "title": "Variation: new font variations", "settings": { "typography": { diff --git a/tests/phpunit/data/themedir1/fonts-block-theme/styles/variation-no-fonts.json b/tests/phpunit/data/themedir1/fonts-block-theme/styles/variation-no-fonts.json index 9c98c6893fa06..fcdd368ec691b 100644 --- a/tests/phpunit/data/themedir1/fonts-block-theme/styles/variation-no-fonts.json +++ b/tests/phpunit/data/themedir1/fonts-block-theme/styles/variation-no-fonts.json @@ -1,5 +1,5 @@ { - "version": 2, + "version": 3, "title": "Variation - no fonts", "styles": { "typography": { diff --git a/tests/phpunit/data/themedir1/fonts-block-theme/theme.json b/tests/phpunit/data/themedir1/fonts-block-theme/theme.json index a5d40da2b5bb2..a7946a3f11023 100644 --- a/tests/phpunit/data/themedir1/fonts-block-theme/theme.json +++ b/tests/phpunit/data/themedir1/fonts-block-theme/theme.json @@ -1,6 +1,6 @@ { "$schema": "https://schemas.wp.org/trunk/theme.json", - "version": 2, + "version": 3, "settings": { "appearanceTools": true, "color": { From 3769e79c6415462cacf894b738ffbedd5c260451 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Thu, 23 May 2024 12:29:53 -0500 Subject: [PATCH 10/27] Backport 61842 class-wp-theme-json.php --- src/wp-includes/class-wp-theme-json.php | 187 +++++++++++++++++++++--- 1 file changed, 169 insertions(+), 18 deletions(-) diff --git a/src/wp-includes/class-wp-theme-json.php b/src/wp-includes/class-wp-theme-json.php index c23096de50d2e..b318cb1ab2a57 100644 --- a/src/wp-includes/class-wp-theme-json.php +++ b/src/wp-includes/class-wp-theme-json.php @@ -125,6 +125,7 @@ class WP_Theme_JSON { * @since 6.3.0 Replaced value_func for duotone with `null`. Custom properties are handled by class-wp-duotone.php. * @since 6.6.0 Added the `dimensions.aspectRatios` & `dimensions.defaultAspectRatios` preset. * @since 6.6.0 Updated the 'prevent_override' value for font size presets to use 'typography.defaultFontSizes'. + * @since 6.6.0 Updated the 'prevent_override' value for spacing size presets to use `spacing.defaultSpacingSizes`. * @var array */ const PRESETS_METADATA = array( @@ -188,7 +189,7 @@ class WP_Theme_JSON { ), array( 'path' => array( 'spacing', 'spacingSizes' ), - 'prevent_override' => false, + 'prevent_override' => array( 'spacing', 'defaultSpacingSizes' ), 'use_default_names' => true, 'value_key' => 'size', 'css_vars' => '--wp--preset--spacing--$slug', @@ -381,6 +382,7 @@ class WP_Theme_JSON { * `background.backgroundSize` and `dimensions.aspectRatio`. * @since 6.6.0 Added support for `dimensions.aspectRatios` and `dimensions.defaultAspectRatios`. * @since 6.6.0 Added support for `typography.defaultFontSizes`. + * @since 6.6.0 Added support for `spacing.defaultSpacingSizes`. * @var array */ const VALID_SETTINGS = array( @@ -435,13 +437,14 @@ class WP_Theme_JSON { 'sticky' => null, ), 'spacing' => array( - 'customSpacingSize' => null, - 'spacingSizes' => null, - 'spacingScale' => null, - 'blockGap' => null, - 'margin' => null, - 'padding' => null, - 'units' => null, + 'customSpacingSize' => null, + 'defaultSpacingSizes' => null, + 'spacingSizes' => null, + 'spacingScale' => null, + 'blockGap' => null, + 'margin' => null, + 'padding' => null, + 'units' => null, ), 'shadow' => array( 'presets' => null, @@ -740,6 +743,7 @@ public static function get_element_class_name( $element ) { * Constructor. * * @since 5.8.0 + * @since 6.6.0 Pre-generate the spacingSizes from spacingScale. * * @param array $theme_json A structure that follows the theme.json schema. * @param string $origin Optional. What source of data this object represents. @@ -754,8 +758,8 @@ public function __construct( $theme_json = array( 'version' => WP_Theme_JSON::LA $valid_block_names = array_keys( static::get_blocks_metadata() ); $valid_element_names = array_keys( static::ELEMENTS ); $valid_variations = static::get_valid_block_style_variations(); - $theme_json = static::sanitize( $this->theme_json, $valid_block_names, $valid_element_names, $valid_variations ); - $this->theme_json = static::maybe_opt_in_into_settings( $theme_json ); + $this->theme_json = static::sanitize( $this->theme_json, $valid_block_names, $valid_element_names, $valid_variations ); + $this->theme_json = static::maybe_opt_in_into_settings( $this->theme_json ); // Internally, presets are keyed by origin. $nodes = static::get_setting_nodes( $this->theme_json ); @@ -774,6 +778,27 @@ public function __construct( $theme_json = array( 'version' => WP_Theme_JSON::LA } } } + + // In addition to presets, spacingScale (which generates presets) is also keyed by origin. + $scale_path = array( 'settings', 'spacing', 'spacingScale' ); + $spacing_scale = _wp_array_get( $this->theme_json, $scale_path, null ); + if ( null !== $spacing_scale ) { + // If the spacingScale is not already keyed by origin. + if ( empty( array_intersect( array_keys( $spacing_scale ), static::VALID_ORIGINS ) ) ) { + _wp_array_set( $this->theme_json, $scale_path, array( $origin => $spacing_scale ) ); + } + } + + // Pre-generate the spacingSizes from spacingScale. + $scale_path = array( 'settings', 'spacing', 'spacingScale', $origin ); + $spacing_scale = _wp_array_get( $this->theme_json, $scale_path, null ); + if ( isset( $spacing_scale ) ) { + $sizes_path = array( 'settings', 'spacing', 'spacingSizes', $origin ); + $spacing_sizes = _wp_array_get( $this->theme_json, $sizes_path, array() ); + $spacing_scale_sizes = static::compute_spacing_sizes( $spacing_scale ); + $merged_spacing_sizes = static::merge_spacing_sizes( $spacing_scale_sizes, $spacing_sizes ); + _wp_array_set( $this->theme_json, $sizes_path, $merged_spacing_sizes ); + } } /** @@ -2919,6 +2944,40 @@ public function merge( $incoming ) { $incoming_data = $incoming->get_raw_data(); $this->theme_json = array_replace_recursive( $this->theme_json, $incoming_data ); + /* + * Recompute all the spacing sizes based on the new hierarchy of data. In the constructor + * spacingScale and spacingSizes are both keyed by origin and VALID_ORIGINS is ordered, so + * we can allow partial spacingScale data to inherit missing data from earlier layers when + * computing the spacing sizes. + * + * This happens before the presets are merged to ensure that default spacing sizes can be + * removed from the theme origin if $prevent_override is true. + */ + $flattened_spacing_scale = array(); + foreach ( static::VALID_ORIGINS as $origin ) { + $scale_path = array( 'settings', 'spacing', 'spacingScale', $origin ); + + // Apply the base spacing scale to the current layer. + $base_spacing_scale = _wp_array_get( $this->theme_json, $scale_path, array() ); + $flattened_spacing_scale = array_replace( $flattened_spacing_scale, $base_spacing_scale ); + + $spacing_scale = _wp_array_get( $incoming_data, $scale_path, null ); + if ( ! isset( $spacing_scale ) ) { + continue; + } + + // Allow partial scale settings by merging with lower layers. + $flattened_spacing_scale = array_replace( $flattened_spacing_scale, $spacing_scale ); + + // Generate and merge the scales for this layer. + $sizes_path = array( 'settings', 'spacing', 'spacingSizes', $origin ); + $spacing_sizes = _wp_array_get( $incoming_data, $sizes_path, array() ); + $spacing_scale_sizes = static::compute_spacing_sizes( $flattened_spacing_scale ); + $merged_spacing_sizes = static::merge_spacing_sizes( $spacing_scale_sizes, $spacing_sizes ); + + _wp_array_set( $incoming_data, $sizes_path, $merged_spacing_sizes ); + } + /* * The array_replace_recursive algorithm merges at the leaf level, * but we don't want leaf arrays to be merged, so we overwrite it. @@ -3709,10 +3768,16 @@ public function get_data() { * Sets the spacingSizes array based on the spacingScale values from theme.json. * * @since 6.1.0 + * @deprecated 6.6.0 + * + * @param string $origin Optional. What source of data to set the spacing sizes for. + * One of 'default', 'theme', or 'custom'. Default 'default'. * * @return null|void */ public function set_spacing_sizes() { + _deprecated_function( __METHOD__, '6.6.0' ); + $spacing_scale = isset( $this->theme_json['settings']['spacing']['spacingScale'] ) ? $this->theme_json['settings']['spacing']['spacingScale'] : array(); @@ -3746,6 +3811,99 @@ public function set_spacing_sizes() { return null; } + $spacing_sizes = static::compute_spacing_sizes( $spacing_scale ); + + // If there are 7 or fewer steps in the scale revert to numbers for labels instead of t-shirt sizes. + if ( $spacing_scale['steps'] <= 7 ) { + for ( $spacing_sizes_count = 0; $spacing_sizes_count < count( $spacing_sizes ); $spacing_sizes_count++ ) { + $spacing_sizes[ $spacing_sizes_count ]['name'] = (string) ( $spacing_sizes_count + 1 ); + } + } + + _wp_array_set( $this->theme_json, array( 'settings', 'spacing', 'spacingSizes', 'default' ), $spacing_sizes ); + } + + /** + * Merges two sets of spacing size presets. + * + * @since 6.6.0 + * + * @param array $base The base set of spacing sizes. + * @param array $incoming The set of spacing sizes to merge with the base. Duplicate slugs will override the base values. + * @return array The merged set of spacing sizes. + */ + private static function merge_spacing_sizes( $base, $incoming ) { + // Preserve the order if there are no base (spacingScale) values. + if ( empty( $base ) ) { + return $incoming; + } + $merged = array(); + foreach ( $base as $item ) { + $merged[ $item['slug'] ] = $item; + } + foreach ( $incoming as $item ) { + $merged[ $item['slug'] ] = $item; + } + ksort( $merged, SORT_NUMERIC ); + return array_values( $merged ); + } + + /** + * Generates a set of spacing sizes by starting with a medium size and + * applying an operator with an increment value to generate the rest of the + * sizes outward from the medium size. The medium slug is '50' with the rest + * of the slugs being 10 apart. The generated names use t-shirt sizing. + * + * Example: + * + * $spacing_scale = array( + * 'steps' => 4, + * 'mediumStep' => 16, + * 'unit' => 'px', + * 'operator' => '+', + * 'increment' => 2, + * ); + * $spacing_sizes = static::compute_spacing_sizes( $spacing_scale ); + * // -> array( + * // array( 'name' => 'Small', 'slug' => '40', 'size' => '14px' ), + * // array( 'name' => 'Medium', 'slug' => '50', 'size' => '16px' ), + * // array( 'name' => 'Large', 'slug' => '60', 'size' => '18px' ), + * // array( 'name' => 'X-Large', 'slug' => '70', 'size' => '20px' ), + * // ) + * + * @since 6.6.0 + * + * @param array $spacing_scale { + * The spacing scale values. All are required. + * + * @type int $steps The number of steps in the scale. (up to 10 steps are supported.) + * @type float $mediumStep The middle value that gets the slug '50'. (For even number of steps, this becomes the first middle value.) + * @type string $unit The CSS unit to use for the sizes. + * @type string $operator The mathematical operator to apply to generate the other sizes. Either '+' or '*'. + * @type float $increment The value used with the operator to generate the other sizes. + * } + * @return array The spacing sizes presets or an empty array if some spacing scale values are missing or invalid. + */ + private static function compute_spacing_sizes( $spacing_scale ) { + /* + * This condition is intentionally missing some checks on ranges for the values in order to + * keep backwards compatibility with the previous implementation. + */ + if ( + ! isset( $spacing_scale['steps'] ) || + ! is_numeric( $spacing_scale['steps'] ) || + 0 === $spacing_scale['steps'] || + ! isset( $spacing_scale['mediumStep'] ) || + ! is_numeric( $spacing_scale['mediumStep'] ) || + ! isset( $spacing_scale['unit'] ) || + ! isset( $spacing_scale['operator'] ) || + ( '+' !== $spacing_scale['operator'] && '*' !== $spacing_scale['operator'] ) || + ! isset( $spacing_scale['increment'] ) || + ! is_numeric( $spacing_scale['increment'] ) + ) { + return array(); + } + $unit = '%' === $spacing_scale['unit'] ? '%' : sanitize_title( $spacing_scale['unit'] ); $current_step = $spacing_scale['mediumStep']; $steps_mid_point = round( $spacing_scale['steps'] / 2, 0 ); @@ -3828,14 +3986,7 @@ public function set_spacing_sizes() { $spacing_sizes[] = $above_sizes_item; } - // If there are 7 or fewer steps in the scale revert to numbers for labels instead of t-shirt sizes. - if ( $spacing_scale['steps'] <= 7 ) { - for ( $spacing_sizes_count = 0; $spacing_sizes_count < count( $spacing_sizes ); $spacing_sizes_count++ ) { - $spacing_sizes[ $spacing_sizes_count ]['name'] = (string) ( $spacing_sizes_count + 1 ); - } - } - - _wp_array_set( $this->theme_json, array( 'settings', 'spacing', 'spacingSizes', 'default' ), $spacing_sizes ); + return $spacing_sizes; } /** From dc57d3840e4796ebd4efc88159a54b5d26d1cfb7 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Thu, 23 May 2024 12:31:01 -0500 Subject: [PATCH 11/27] Backport 61842 class-wp-theme-json-resolver.php --- src/wp-includes/class-wp-theme-json-resolver.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/wp-includes/class-wp-theme-json-resolver.php b/src/wp-includes/class-wp-theme-json-resolver.php index 464a6cc4bf739..6c63444a8bf74 100644 --- a/src/wp-includes/class-wp-theme-json-resolver.php +++ b/src/wp-includes/class-wp-theme-json-resolver.php @@ -591,7 +591,6 @@ public static function get_merged_data( $origin = 'custom' ) { $result = new WP_Theme_JSON(); $result->merge( static::get_core_data() ); if ( 'default' === $origin ) { - $result->set_spacing_sizes(); return $result; } @@ -602,12 +601,10 @@ public static function get_merged_data( $origin = 'custom' ) { $result->merge( static::get_theme_data() ); if ( 'theme' === $origin ) { - $result->set_spacing_sizes(); return $result; } $result->merge( static::get_user_data() ); - $result->set_spacing_sizes(); return $result; } From 943d9bbe07051bee3c0ba1c3d9f88665bc40ffdd Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Thu, 23 May 2024 12:32:04 -0500 Subject: [PATCH 12/27] Backport 61842 class-wp-theme-json-schema.php --- .../class-wp-theme-json-schema.php | 44 ++++++++++++++++--- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/src/wp-includes/class-wp-theme-json-schema.php b/src/wp-includes/class-wp-theme-json-schema.php index 91a4494522910..aa654f25979eb 100644 --- a/src/wp-includes/class-wp-theme-json-schema.php +++ b/src/wp-includes/class-wp-theme-json-schema.php @@ -121,12 +121,12 @@ private static function migrate_v2_to_v3( $old ) { } /* - * Even though defaultFontSizes is a new setting, we need to migrate - * it as it controls the PRESETS_METADATA prevent_override which was - * previously hardcoded to false. This only needs to happen when the - * theme provided font sizes as they could match the default ones and - * affect the generated CSS. And in v2 we provided default font sizes - * when the theme did not provide any. + * Even though defaultFontSizes and defaultSpacingSizes are new + * settings, we need to migrate them as they each control + * PRESETS_METADATA prevent_override values which were previously + * hardcoded to false. This only needs to happen when the theme provides + * fontSizes or spacingSizes as they could match the default ones and + * affect the generated CSS. */ if ( isset( $old['settings']['typography']['fontSizes'] ) ) { if ( ! isset( $new['settings'] ) ) { @@ -138,6 +138,38 @@ private static function migrate_v2_to_v3( $old ) { $new['settings']['typography']['defaultFontSizes'] = false; } + /* + * Similarly to defaultFontSizes, we need to migrate defaultSpacingSizes + * as it controls the PRESETS_METADATA prevent_override which was + * previously hardcoded to false. This only needs to happen when the + * theme provided spacing sizes via spacingSizes or spacingScale. + */ + if ( + isset( $old['settings']['spacing']['spacingSizes'] ) || + isset( $old['settings']['spacing']['spacingScale'] ) + ) { + if ( ! isset( $new['settings'] ) ) { + $new['settings'] = array(); + } + if ( ! isset( $new['settings']['spacing'] ) ) { + $new['settings']['spacing'] = array(); + } + $new['settings']['spacing']['defaultSpacingSizes'] = false; + } + + /* + * In v3 spacingSizes is merged with the generated spacingScale sizes + * instead of completely replacing them. The v3 behavior is what was + * documented for the v2 schema, but the code never actually did work + * that way. Instead of surprising users with a behavior change two + * years after the fact at the same time as a v3 update is introduced, + * we'll continue using the "bugged" behavior for v2 themes. And treat + * the "bug fix" as a breaking change for v3. + */ + if ( isset( $old['settings']['spacing']['spacingSizes'] ) ) { + unset( $new['settings']['spacing']['spacingScale'] ); + } + return $new; } From 0a33eb149ac71f38116eb001875fd5d8f0b23216 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Thu, 23 May 2024 12:33:24 -0500 Subject: [PATCH 13/27] Backport 61842 theme.json --- src/wp-includes/theme.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/wp-includes/theme.json b/src/wp-includes/theme.json index 0dbb0c5ba561f..c2ea0e71938bb 100644 --- a/src/wp-includes/theme.json +++ b/src/wp-includes/theme.json @@ -265,6 +265,7 @@ "margin": false, "padding": false, "customSpacingSize": true, + "defaultSpacingSizes": true, "units": [ "px", "em", "rem", "vh", "vw", "%" ], "spacingScale": { "operator": "*", From 35695f2ad18746a650379388f697553be572d937 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Thu, 23 May 2024 12:35:00 -0500 Subject: [PATCH 14/27] Backport 61842 PHPUnit wpThemeJsonSchema.php --- .../phpunit/tests/theme/wpThemeJsonSchema.php | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/phpunit/tests/theme/wpThemeJsonSchema.php b/tests/phpunit/tests/theme/wpThemeJsonSchema.php index dcd876908cb29..aa6f78eb03439 100644 --- a/tests/phpunit/tests/theme/wpThemeJsonSchema.php +++ b/tests/phpunit/tests/theme/wpThemeJsonSchema.php @@ -229,6 +229,20 @@ public function test_migrate_v2_to_latest() { ), ), ), + 'spacing' => array( + 'spacingSizes' => array( + array( + 'name' => 'Small', + 'slug' => 20, + 'size' => '20px', + ), + array( + 'name' => 'Large', + 'slug' => 80, + 'size' => '80px', + ), + ), + ), ), ); @@ -252,6 +266,21 @@ public function test_migrate_v2_to_latest() { ), ), ), + 'spacing' => array( + 'defaultSpacingSizes' => false, + 'spacingSizes' => array( + array( + 'name' => 'Small', + 'slug' => 20, + 'size' => '20px', + ), + array( + 'name' => 'Large', + 'slug' => 80, + 'size' => '80px', + ), + ), + ), ), ); From 7599a7ff97efb8a5a5b8894098a2e185f326e6cb Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Thu, 23 May 2024 12:36:41 -0500 Subject: [PATCH 15/27] Backport 61842 PHPUnit wpThemeJson.php --- tests/phpunit/tests/theme/wpThemeJson.php | 83 ++++++++++------------- 1 file changed, 34 insertions(+), 49 deletions(-) diff --git a/tests/phpunit/tests/theme/wpThemeJson.php b/tests/phpunit/tests/theme/wpThemeJson.php index 8bd99dde0a4d2..8c6d6d1524a75 100644 --- a/tests/phpunit/tests/theme/wpThemeJson.php +++ b/tests/phpunit/tests/theme/wpThemeJson.php @@ -4469,10 +4469,10 @@ public function test_set_spacing_sizes( $spacing_scale, $expected_output ) { 'spacingScale' => $spacing_scale, ), ), - ) + ), + 'default' ); - $theme_json->set_spacing_sizes(); $this->assertSame( $expected_output, _wp_array_get( $theme_json->get_raw_data(), array( 'settings', 'spacing', 'spacingSizes', 'default' ) ) ); } @@ -4495,7 +4495,7 @@ public function data_set_spacing_sizes() { ), 'expected_output' => array( array( - 'name' => '1', + 'name' => 'Medium', 'slug' => '50', 'size' => '4rem', ), @@ -4511,12 +4511,12 @@ public function data_set_spacing_sizes() { ), 'expected_output' => array( array( - 'name' => '1', + 'name' => 'Medium', 'slug' => '50', 'size' => '4rem', ), array( - 'name' => '2', + 'name' => 'Large', 'slug' => '60', 'size' => '5.5rem', ), @@ -4532,17 +4532,17 @@ public function data_set_spacing_sizes() { ), 'expected_output' => array( array( - 'name' => '1', + 'name' => 'Small', 'slug' => '40', 'size' => '2.5rem', ), array( - 'name' => '2', + 'name' => 'Medium', 'slug' => '50', 'size' => '4rem', ), array( - 'name' => '3', + 'name' => 'Large', 'slug' => '60', 'size' => '5.5rem', ), @@ -4558,22 +4558,22 @@ public function data_set_spacing_sizes() { ), 'expected_output' => array( array( - 'name' => '1', + 'name' => 'Small', 'slug' => '40', 'size' => '2.5rem', ), array( - 'name' => '2', + 'name' => 'Medium', 'slug' => '50', 'size' => '4rem', ), array( - 'name' => '3', + 'name' => 'Large', 'slug' => '60', 'size' => '5.5rem', ), array( - 'name' => '4', + 'name' => 'X-Large', 'slug' => '70', 'size' => '7rem', ), @@ -4589,27 +4589,27 @@ public function data_set_spacing_sizes() { ), 'expected_output' => array( array( - 'name' => '1', + 'name' => 'Small', 'slug' => '40', 'size' => '2.5rem', ), array( - 'name' => '2', + 'name' => 'Medium', 'slug' => '50', 'size' => '5rem', ), array( - 'name' => '3', + 'name' => 'Large', 'slug' => '60', 'size' => '7.5rem', ), array( - 'name' => '4', + 'name' => 'X-Large', 'slug' => '70', 'size' => '10rem', ), array( - 'name' => '5', + 'name' => '2X-Large', 'slug' => '80', 'size' => '12.5rem', ), @@ -4625,27 +4625,27 @@ public function data_set_spacing_sizes() { ), 'expected_output' => array( array( - 'name' => '1', + 'name' => 'X-Small', 'slug' => '30', 'size' => '0.67rem', ), array( - 'name' => '2', + 'name' => 'Small', 'slug' => '40', 'size' => '1rem', ), array( - 'name' => '3', + 'name' => 'Medium', 'slug' => '50', 'size' => '1.5rem', ), array( - 'name' => '4', + 'name' => 'Large', 'slug' => '60', 'size' => '2.25rem', ), array( - 'name' => '5', + 'name' => 'X-Large', 'slug' => '70', 'size' => '3.38rem', ), @@ -4661,27 +4661,27 @@ public function data_set_spacing_sizes() { ), 'expected_output' => array( array( - 'name' => '1', + 'name' => 'X-Small', 'slug' => '30', 'size' => '0.09rem', ), array( - 'name' => '2', + 'name' => 'Small', 'slug' => '40', 'size' => '0.38rem', ), array( - 'name' => '3', + 'name' => 'Medium', 'slug' => '50', 'size' => '1.5rem', ), array( - 'name' => '4', + 'name' => 'Large', 'slug' => '60', 'size' => '6rem', ), array( - 'name' => '5', + 'name' => 'X-Large', 'slug' => '70', 'size' => '24rem', ), @@ -4752,9 +4752,6 @@ public function data_set_spacing_sizes() { * @param array $expected_output Expected output from data provider. */ public function test_set_spacing_sizes_when_invalid( $spacing_scale, $expected_output ) { - $this->expectException( Exception::class ); - $this->expectExceptionMessage( 'Some of the theme.json settings.spacing.spacingScale values are invalid' ); - $theme_json = new WP_Theme_JSON( array( 'version' => WP_Theme_JSON::LATEST_SCHEMA, @@ -4763,22 +4760,10 @@ public function test_set_spacing_sizes_when_invalid( $spacing_scale, $expected_o 'spacingScale' => $spacing_scale, ), ), - ) - ); - - // Ensure PHPUnit 10 compatibility. - set_error_handler( - static function ( $errno, $errstr ) { - restore_error_handler(); - throw new Exception( $errstr, $errno ); - }, - E_ALL + ), + 'default' ); - $theme_json->set_spacing_sizes(); - - restore_error_handler(); - $this->assertSame( $expected_output, _wp_array_get( $theme_json->get_raw_data(), array( 'settings', 'spacing', 'spacingSizes', 'default' ) ) ); } @@ -4799,7 +4784,7 @@ public function data_set_spacing_sizes_when_invalid() { 'mediumStep' => 4, 'unit' => 'rem', ), - 'expected_output' => null, + 'expected_output' => array(), ), 'non numeric increment' => array( 'spacing_scale' => array( @@ -4809,7 +4794,7 @@ public function data_set_spacing_sizes_when_invalid() { 'mediumStep' => 4, 'unit' => 'rem', ), - 'expected_output' => null, + 'expected_output' => array(), ), 'non numeric steps' => array( 'spacing_scale' => array( @@ -4819,7 +4804,7 @@ public function data_set_spacing_sizes_when_invalid() { 'mediumStep' => 4, 'unit' => 'rem', ), - 'expected_output' => null, + 'expected_output' => array(), ), 'non numeric medium step' => array( 'spacing_scale' => array( @@ -4829,7 +4814,7 @@ public function data_set_spacing_sizes_when_invalid() { 'mediumStep' => 'That which is just right', 'unit' => 'rem', ), - 'expected_output' => null, + 'expected_output' => array(), ), 'missing unit value' => array( 'spacing_scale' => array( @@ -4838,7 +4823,7 @@ public function data_set_spacing_sizes_when_invalid() { 'steps' => 5, 'mediumStep' => 4, ), - 'expected_output' => null, + 'expected_output' => array(), ), ); } From ca161dad0ca22a9df2f1ef9b6588ea64e2c5dcc4 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Mon, 3 Jun 2024 13:35:11 -0500 Subject: [PATCH 16/27] Merge 6.6 `@since` tags --- src/wp-includes/class-wp-theme-json.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/wp-includes/class-wp-theme-json.php b/src/wp-includes/class-wp-theme-json.php index b318cb1ab2a57..ea8c2225863a6 100644 --- a/src/wp-includes/class-wp-theme-json.php +++ b/src/wp-includes/class-wp-theme-json.php @@ -123,9 +123,9 @@ class WP_Theme_JSON { * `prevent_override` value for `color.duotone` to use `color.defaultDuotone`. * @since 6.2.0 Added 'shadow' presets. * @since 6.3.0 Replaced value_func for duotone with `null`. Custom properties are handled by class-wp-duotone.php. - * @since 6.6.0 Added the `dimensions.aspectRatios` & `dimensions.defaultAspectRatios` preset. - * @since 6.6.0 Updated the 'prevent_override' value for font size presets to use 'typography.defaultFontSizes'. - * @since 6.6.0 Updated the 'prevent_override' value for spacing size presets to use `spacing.defaultSpacingSizes`. + * @since 6.6.0 Added the `dimensions.aspectRatios` and `dimensions.defaultAspectRatios` presets. + * Updated the 'prevent_override' value for font size presets to use 'typography.defaultFontSizes' + * and spacing size presets to use `spacing.defaultSpacingSizes`. * @var array */ const PRESETS_METADATA = array( @@ -380,9 +380,8 @@ class WP_Theme_JSON { * `typography.writingMode`, `lightbox.enabled` and `lightbox.allowEditing`. * @since 6.5.0 Added support for `layout.allowCustomContentAndWideSize`, * `background.backgroundSize` and `dimensions.aspectRatio`. - * @since 6.6.0 Added support for `dimensions.aspectRatios` and `dimensions.defaultAspectRatios`. - * @since 6.6.0 Added support for `typography.defaultFontSizes`. - * @since 6.6.0 Added support for `spacing.defaultSpacingSizes`. + * @since 6.6.0 Added support for 'dimensions.aspectRatios', 'dimensions.defaultAspectRatios', + * 'typography.defaultFontSizes', and 'spacing.defaultSpacingSizes'. * @var array */ const VALID_SETTINGS = array( @@ -743,7 +742,8 @@ public static function get_element_class_name( $element ) { * Constructor. * * @since 5.8.0 - * @since 6.6.0 Pre-generate the spacingSizes from spacingScale. + * @since 6.6.0 Key spacingScale by origin, and Pre-generate the + * spacingSizes from spacingScale. * * @param array $theme_json A structure that follows the theme.json schema. * @param string $origin Optional. What source of data this object represents. From caaeb7268f79be9634e1476713c2dfd003f617c5 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Mon, 3 Jun 2024 16:19:04 -0500 Subject: [PATCH 17/27] Update LATEST_THEME_JSON_VERSION_SUPPORTED in font-faces controller --- .../rest-api/endpoints/class-wp-rest-font-faces-controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-font-faces-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-font-faces-controller.php index c7f72d4ec1d9d..91b5f63e964ee 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-font-faces-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-font-faces-controller.php @@ -18,7 +18,7 @@ class WP_REST_Font_Faces_Controller extends WP_REST_Posts_Controller { * @since 6.5.0 * @var int */ - const LATEST_THEME_JSON_VERSION_SUPPORTED = 2; + const LATEST_THEME_JSON_VERSION_SUPPORTED = 3; /** * Whether the controller supports batching. From 6569a11ffd3fe5c4a7c5f9e53eddcf0df20a2dac Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Mon, 3 Jun 2024 16:19:14 -0500 Subject: [PATCH 18/27] Add default-font-sizes options for classic themes --- src/wp-includes/class-wp-theme-json-resolver.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/wp-includes/class-wp-theme-json-resolver.php b/src/wp-includes/class-wp-theme-json-resolver.php index 6c63444a8bf74..585101382de5f 100644 --- a/src/wp-includes/class-wp-theme-json-resolver.php +++ b/src/wp-includes/class-wp-theme-json-resolver.php @@ -310,6 +310,19 @@ public static function get_theme_data( $deprecated = array(), $options = array() } $theme_support_data['settings']['color']['defaultGradients'] = $default_gradients; + if ( ! isset( $theme_support_data['settings']['typography'] ) ) { + $theme_support_data['settings']['typography'] = array(); + } + $default_font_sizes = false; + if ( current_theme_supports( 'default-font-sizes' ) ) { + $default_font_sizes = true; + } + if ( ! isset( $theme_support_data['settings']['typography']['fontSizes'] ) ) { + // If the theme does not have any font sizes, we still want to show the core one. + $default_font_sizes = true; + } + $theme_support_data['settings']['typography']['defaultFontSizes'] = $default_font_sizes; + if ( ! isset( $theme_support_data['settings']['shadow'] ) ) { $theme_support_data['settings']['shadow'] = array(); } From d0732518a0219d03c7b3f4ff02a8694a0d4e518b Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Mon, 3 Jun 2024 16:20:43 -0500 Subject: [PATCH 19/27] Add default-spacing-sizes options for classic themes --- src/wp-includes/class-wp-theme-json-resolver.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/wp-includes/class-wp-theme-json-resolver.php b/src/wp-includes/class-wp-theme-json-resolver.php index 585101382de5f..3ceb9dcde422d 100644 --- a/src/wp-includes/class-wp-theme-json-resolver.php +++ b/src/wp-includes/class-wp-theme-json-resolver.php @@ -323,6 +323,19 @@ public static function get_theme_data( $deprecated = array(), $options = array() } $theme_support_data['settings']['typography']['defaultFontSizes'] = $default_font_sizes; + if ( ! isset( $theme_support_data['settings']['spacing'] ) ) { + $theme_support_data['settings']['spacing'] = array(); + } + $default_spacing_sizes = false; + if ( current_theme_supports( 'default-spacing-sizes' ) ) { + $default_spacing_sizes = true; + } + if ( ! isset( $theme_support_data['settings']['spacing']['spacingSizes'] ) ) { + // If the theme does not have any spacing sizes, we still want to show the core one. + $default_spacing_sizes = true; + } + $theme_support_data['settings']['spacing']['defaultSpacingSizes'] = $default_spacing_sizes; + if ( ! isset( $theme_support_data['settings']['shadow'] ) ) { $theme_support_data['settings']['shadow'] = array(); } From 93e3c82dece82a54a35fd0cb2ce328f05d89c07b Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Mon, 3 Jun 2024 16:34:41 -0500 Subject: [PATCH 20/27] Add editor-spacing-sizes for consistency --- src/wp-includes/block-editor.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/wp-includes/block-editor.php b/src/wp-includes/block-editor.php index e04b012e7dd08..d3b4c6a38035d 100644 --- a/src/wp-includes/block-editor.php +++ b/src/wp-includes/block-editor.php @@ -844,5 +844,10 @@ function get_classic_theme_supports_block_editor_settings() { $theme_settings['gradients'] = $gradient_presets; } + $spacing_sizes = current( (array) get_theme_support( 'editor-spacing-sizes' ) ); + if ( false !== $spacing_sizes ) { + $theme_settings['spacingSizes'] = $spacing_sizes; + } + return $theme_settings; } From ea23bf02f9033f8533c644ae365b46027635e71c Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Mon, 3 Jun 2024 16:44:52 -0500 Subject: [PATCH 21/27] Update LATEST_THEME_JSON_VERSION_SUPPORTED in font-families controller --- .../endpoints/class-wp-rest-font-families-controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-font-families-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-font-families-controller.php index 184b42d141dd3..c2d70d0dd6916 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-font-families-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-font-families-controller.php @@ -20,7 +20,7 @@ class WP_REST_Font_Families_Controller extends WP_REST_Posts_Controller { * @since 6.5.0 * @var int */ - const LATEST_THEME_JSON_VERSION_SUPPORTED = 2; + const LATEST_THEME_JSON_VERSION_SUPPORTED = 3; /** * Whether the controller supports batching. From afe235ed10863a0e1f311bbb8ba23d54ddc4e954 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Mon, 3 Jun 2024 17:01:19 -0500 Subject: [PATCH 22/27] Fix phpunit tests --- .../tests/fonts/font-library/wpRestFontFacesController.php | 2 +- .../tests/fonts/font-library/wpRestFontFamiliesController.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/phpunit/tests/fonts/font-library/wpRestFontFacesController.php b/tests/phpunit/tests/fonts/font-library/wpRestFontFacesController.php index 3e74b23b7cb20..a4f6d8194902f 100644 --- a/tests/phpunit/tests/fonts/font-library/wpRestFontFacesController.php +++ b/tests/phpunit/tests/fonts/font-library/wpRestFontFacesController.php @@ -623,7 +623,7 @@ public function test_create_item_invalid_theme_json_version( $theme_json_version public function data_create_item_invalid_theme_json_version() { return array( array( 1 ), - array( 3 ), + array( 4 ), ); } diff --git a/tests/phpunit/tests/fonts/font-library/wpRestFontFamiliesController.php b/tests/phpunit/tests/fonts/font-library/wpRestFontFamiliesController.php index 78890139f304e..673d03606c490 100644 --- a/tests/phpunit/tests/fonts/font-library/wpRestFontFamiliesController.php +++ b/tests/phpunit/tests/fonts/font-library/wpRestFontFamiliesController.php @@ -431,7 +431,7 @@ public function test_create_item_invalid_theme_json_version( $theme_json_version public function data_create_item_invalid_theme_json_version() { return array( array( 1 ), - array( 3 ), + array( 4 ), ); } From 1b583a103aee384ff325386873c4d0757a78f81c Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Mon, 3 Jun 2024 17:08:58 -0500 Subject: [PATCH 23/27] Update wp-api-generated --- tests/qunit/fixtures/wp-api-generated.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/qunit/fixtures/wp-api-generated.js b/tests/qunit/fixtures/wp-api-generated.js index ed7842acd09c4..4cdf820e2196b 100644 --- a/tests/qunit/fixtures/wp-api-generated.js +++ b/tests/qunit/fixtures/wp-api-generated.js @@ -7855,9 +7855,9 @@ mockedApiResponse.Schema = { "theme_json_version": { "description": "Version of the theme.json schema used for the typography settings.", "type": "integer", - "default": 2, + "default": 3, "minimum": 2, - "maximum": 2, + "maximum": 3, "required": false }, "font_family_settings": { @@ -7924,9 +7924,9 @@ mockedApiResponse.Schema = { "theme_json_version": { "description": "Version of the theme.json schema used for the typography settings.", "type": "integer", - "default": 2, + "default": 3, "minimum": 2, - "maximum": 2, + "maximum": 3, "required": false }, "font_family_settings": { @@ -8057,9 +8057,9 @@ mockedApiResponse.Schema = { "theme_json_version": { "description": "Version of the theme.json schema used for the typography settings.", "type": "integer", - "default": 2, + "default": 3, "minimum": 2, - "maximum": 2, + "maximum": 3, "required": false }, "font_face_settings": { From 1e93db47e2e636ce50f6b907038933a690907452 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Mon, 3 Jun 2024 17:36:57 -0500 Subject: [PATCH 24/27] Added 6.6.0 doc comments --- src/wp-includes/block-editor.php | 1 + src/wp-includes/class-wp-theme-json-resolver.php | 1 + 2 files changed, 2 insertions(+) diff --git a/src/wp-includes/block-editor.php b/src/wp-includes/block-editor.php index d3b4c6a38035d..fdc4846f69f80 100644 --- a/src/wp-includes/block-editor.php +++ b/src/wp-includes/block-editor.php @@ -814,6 +814,7 @@ function get_block_editor_theme_styles() { * Returns the classic theme supports settings for block editor. * * @since 6.2.0 + * @since 6.6.0 Add support for 'editor-spacing-sizes' theme support. * * @return array The classic theme supports settings. */ diff --git a/src/wp-includes/class-wp-theme-json-resolver.php b/src/wp-includes/class-wp-theme-json-resolver.php index 3ceb9dcde422d..c3a5db45ad79a 100644 --- a/src/wp-includes/class-wp-theme-json-resolver.php +++ b/src/wp-includes/class-wp-theme-json-resolver.php @@ -220,6 +220,7 @@ protected static function has_same_registered_blocks( $origin ) { * @since 5.8.0 * @since 5.9.0 Theme supports have been inlined and the `$theme_support_data` argument removed. * @since 6.0.0 Added an `$options` parameter to allow the theme data to be returned without theme supports. + * @since 6.6.0 Add support for 'default-font-sizes' and 'default-spacing-sizes' theme supports. * * @param array $deprecated Deprecated. Not used. * @param array $options { From c8cdcc1784baba5f7162d40776ddb569fbf0d9f1 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Mon, 3 Jun 2024 19:18:02 -0500 Subject: [PATCH 25/27] register_theme_feature( 'editor-spacing-sizes' ) --- src/wp-includes/theme.php | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/wp-includes/theme.php b/src/wp-includes/theme.php index 330c36d3f55ff..fd37543791912 100644 --- a/src/wp-includes/theme.php +++ b/src/wp-includes/theme.php @@ -2642,6 +2642,7 @@ function get_theme_starter_content() { * @since 6.3.0 The `border` feature allows themes without theme.json to add border styles to blocks. * @since 6.5.0 The `appearance-tools` feature enables a few design tools for blocks, * see `WP_Theme_JSON::APPEARANCE_TOOLS_OPT_INS` for a complete list. + * @since 6.6.0 The `editor-spacing-sizes` feature was added. * * @global array $_wp_theme_features * @@ -2669,6 +2670,7 @@ function get_theme_starter_content() { * - 'editor-color-palette' * - 'editor-gradient-presets' * - 'editor-font-sizes' + * - 'editor-spacing-sizes' * - 'editor-styles' * - 'featured-content' * - 'html5' @@ -4226,6 +4228,31 @@ function create_initial_theme_features() { ), ) ); + register_theme_feature( + 'editor-spacing-sizes', + array( + 'type' => 'array', + 'description' => __( 'Custom spacing sizes if defined by the theme.' ), + 'show_in_rest' => array( + 'schema' => array( + 'items' => array( + 'type' => 'object', + 'properties' => array( + 'name' => array( + 'type' => 'string', + ), + 'size' => array( + 'type' => 'string', + ), + 'slug' => array( + 'type' => 'string', + ), + ), + ), + ), + ), + ) + ); register_theme_feature( 'editor-styles', array( From 5214e4f5be933562efae937595752cd2b9ee574a Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Mon, 3 Jun 2024 19:31:28 -0500 Subject: [PATCH 26/27] Copy spacingSizes from editor-spacing-sizes --- src/wp-includes/class-wp-theme-json.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/wp-includes/class-wp-theme-json.php b/src/wp-includes/class-wp-theme-json.php index ea8c2225863a6..18e0872eb4673 100644 --- a/src/wp-includes/class-wp-theme-json.php +++ b/src/wp-includes/class-wp-theme-json.php @@ -3595,6 +3595,13 @@ public static function get_from_editor_settings( $settings ) { $theme_settings['settings']['spacing']['padding'] = $settings['enableCustomSpacing']; } + if ( isset( $settings['spacingSizes'] ) ) { + if ( ! isset( $theme_settings['settings']['spacing'] ) ) { + $theme_settings['settings']['spacing'] = array(); + } + $theme_settings['settings']['spacing']['spacingSizes'] = $settings['spacingSizes']; + } + return $theme_settings; } From 6b6d2b676222039e43f3595afb8ec3dbd58d8e10 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Mon, 3 Jun 2024 21:09:56 -0500 Subject: [PATCH 27/27] Fix tests --- tests/phpunit/tests/rest-api/rest-themes-controller.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/phpunit/tests/rest-api/rest-themes-controller.php b/tests/phpunit/tests/rest-api/rest-themes-controller.php index dfa243d5770c9..2c5660f8e0083 100644 --- a/tests/phpunit/tests/rest-api/rest-themes-controller.php +++ b/tests/phpunit/tests/rest-api/rest-themes-controller.php @@ -419,6 +419,7 @@ public function test_get_item_schema() { $this->assertArrayHasKey( 'editor-color-palette', $theme_supports ); $this->assertArrayHasKey( 'editor-font-sizes', $theme_supports ); $this->assertArrayHasKey( 'editor-gradient-presets', $theme_supports ); + $this->assertArrayHasKey( 'editor-spacing-sizes', $theme_supports ); $this->assertArrayHasKey( 'editor-styles', $theme_supports ); $this->assertArrayHasKey( 'formats', $theme_supports ); $this->assertArrayHasKey( 'html5', $theme_supports ); @@ -426,7 +427,7 @@ public function test_get_item_schema() { $this->assertArrayHasKey( 'responsive-embeds', $theme_supports ); $this->assertArrayHasKey( 'title-tag', $theme_supports ); $this->assertArrayHasKey( 'wp-block-styles', $theme_supports ); - $this->assertCount( 23, $theme_supports, 'There should be 23 theme supports' ); + $this->assertCount( 24, $theme_supports, 'There should be 23 theme supports' ); } /**