Make WordPress Core

Changeset 58328


Ignore:
Timestamp:
06/04/2024 11:53:37 AM (2 years ago)
Author:
ellatrix
Message:

Editor: Add theme.json v3 migrations.

See ​https://github.com/WordPress/wordpress-develop/pull/6616.
See also the original Gutenberg PRs:

Fixes #61282.

Props ajlende, talldanwp, ramonopoly, ellatrix.

Location:
trunk
Files:
34 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/block-editor.php

    r56736 r58328  
    815815 *
    816816 * @since 6.2.0
     817 * @since 6.6.0 Add support for 'editor-spacing-sizes' theme support.
    817818 *
    818819 * @return array The classic theme supports settings.
    … …  
    845846        }
    846847
     848        $spacing_sizes = current( (array) get_theme_support( 'editor-spacing-sizes' ) );
     849        if ( false !== $spacing_sizes ) {
     850                $theme_settings['spacingSizes'] = $spacing_sizes;
     851        }
     852
    847853        return $theme_settings;
    848854}
  • trunk/src/wp-includes/class-wp-theme-json-data.php

    r58185 r58328  
    4040         * @param string $origin The origin of the data: default, theme, user.
    4141         */
    42         public function __construct( $data = array(), $origin = 'theme' ) {
     42        public function __construct( $data = array( 'version' => WP_Theme_JSON::LATEST_SCHEMA ), $origin = 'theme' ) {
    4343                $this->origin     = $origin;
    4444                $this->theme_json = new WP_Theme_JSON( $data, $this->origin );
  • trunk/src/wp-includes/class-wp-theme-json-resolver.php

    r58265 r58328  
    221221         * @since 5.9.0 Theme supports have been inlined and the `$theme_support_data` argument removed.
    222222         * @since 6.0.0 Added an `$options` parameter to allow the theme data to be returned without theme supports.
     223         * @since 6.6.0 Add support for 'default-font-sizes' and 'default-spacing-sizes' theme supports.
    223224         *
    224225         * @param array $deprecated Deprecated. Not used.
    … …  
    244245                                $theme_json_data = static::translate( $theme_json_data, $wp_theme->get( 'TextDomain' ) );
    245246                        } else {
    246                                 $theme_json_data = array();
     247                                $theme_json_data = array( 'version' => WP_Theme_JSON::LATEST_SCHEMA );
    247248                        }
    248249
    … …  
    311312                        $theme_support_data['settings']['color']['defaultGradients'] = $default_gradients;
    312313
     314                        if ( ! isset( $theme_support_data['settings']['typography'] ) ) {
     315                                $theme_support_data['settings']['typography'] = array();
     316                        }
     317                        $default_font_sizes = false;
     318                        if ( current_theme_supports( 'default-font-sizes' ) ) {
     319                                $default_font_sizes = true;
     320                        }
     321                        if ( ! isset( $theme_support_data['settings']['typography']['fontSizes'] ) ) {
     322                                // If the theme does not have any font sizes, we still want to show the core one.
     323                                $default_font_sizes = true;
     324                        }
     325                        $theme_support_data['settings']['typography']['defaultFontSizes'] = $default_font_sizes;
     326
     327                        if ( ! isset( $theme_support_data['settings']['spacing'] ) ) {
     328                                $theme_support_data['settings']['spacing'] = array();
     329                        }
     330                        $default_spacing_sizes = false;
     331                        if ( current_theme_supports( 'default-spacing-sizes' ) ) {
     332                                $default_spacing_sizes = true;
     333                        }
     334                        if ( ! isset( $theme_support_data['settings']['spacing']['spacingSizes'] ) ) {
     335                                // If the theme does not have any spacing sizes, we still want to show the core one.
     336                                $default_spacing_sizes = true;
     337                        }
     338                        $theme_support_data['settings']['spacing']['defaultSpacingSizes'] = $default_spacing_sizes;
     339
    313340                        if ( ! isset( $theme_support_data['settings']['shadow'] ) ) {
    314341                                $theme_support_data['settings']['shadow'] = array();
    … …  
    360387                }
    361388
    362                 $config = array( 'version' => 2 );
     389                $config = array( 'version' => WP_Theme_JSON::LATEST_SCHEMA );
    363390                foreach ( $blocks as $block_name => $block_type ) {
    364391                        if ( isset( $block_type->supports['__experimentalStyle'] ) ) {
    … …  
    495522         *
    496523         * @since 5.9.0
     524         * @since 6.6.0 The 'isGlobalStylesUserThemeJSON' flag is left on the user data.
    497525         *
    498526         * @return WP_Theme_JSON Entity that holds styles for user data.
    … …  
    532560                                $decoded_data['isGlobalStylesUserThemeJSON']
    533561                        ) {
    534                                 unset( $decoded_data['isGlobalStylesUserThemeJSON'] );
    535562                                $config = $decoded_data;
    536563                        }
    … …  
    538565
    539566                /** This filter is documented in wp-includes/class-wp-theme-json-resolver.php */
    540                 $theme_json   = apply_filters( 'wp_theme_json_data_user', new WP_Theme_JSON_Data( $config, 'custom' ) );
    541                 static::$user = $theme_json->get_theme_json();
     567                $theme_json = apply_filters( 'wp_theme_json_data_user', new WP_Theme_JSON_Data( $config, 'custom' ) );
     568                $config     = $theme_json->get_data();
     569
     570                // Needs to be set for schema migrations of user data.
     571                $config['isGlobalStylesUserThemeJSON'] = true;
     572
     573                static::$user = new WP_Theme_JSON( $config, 'custom' );
    542574
    543575                return static::$user;
    … …  
    587619                $result->merge( static::get_core_data() );
    588620                if ( 'default' === $origin ) {
    589                         $result->set_spacing_sizes();
    590621                        return $result;
    591622                }
    … …  
    598629                $result->merge( static::get_theme_data() );
    599630                if ( 'theme' === $origin ) {
    600                         $result->set_spacing_sizes();
    601631                        return $result;
    602632                }
    603633
    604634                $result->merge( static::get_user_data() );
    605                 $result->set_spacing_sizes();
    606635
    607636                return $result;
  • trunk/src/wp-includes/class-wp-theme-json-schema.php

    r56753 r58328  
    3636         *
    3737         * @since 5.9.0
     38         * @since 6.6.0 Migrate up to v3.
    3839         *
    3940         * @param array $theme_json The structure to migrate.
    … …  
    4849                }
    4950
    50                 if ( 1 === $theme_json['version'] ) {
    51                         $theme_json = self::migrate_v1_to_v2( $theme_json );
     51                // Migrate each version in order starting with the current version.
     52                switch ( $theme_json['version'] ) {
     53                        case 1:
     54                                $theme_json = self::migrate_v1_to_v2( $theme_json );
     55                                // no break
     56                        case 2:
     57                                $theme_json = self::migrate_v2_to_v3( $theme_json );
     58                                // no break
    5259                }
    5360
    … …  
    8188                // Set the new version.
    8289                $new['version'] = 2;
     90
     91                return $new;
     92        }
     93
     94        /**
     95         * Migrates from v2 to v3.
     96         *
     97         * - Sets settings.typography.defaultFontSizes to false.
     98         *
     99         * @since 6.6.0
     100         *
     101         * @param array $old Data to migrate.
     102         *
     103         * @return array Data with defaultFontSizes set to false.
     104         */
     105        private static function migrate_v2_to_v3( $old ) {
     106                // Copy everything.
     107                $new = $old;
     108
     109                // Set the new version.
     110                $new['version'] = 3;
     111
     112                /*
     113                 * Remaining changes do not need to be applied to the custom origin,
     114                 * as they should take on the value of the theme origin.
     115                 */
     116                if (
     117                        isset( $new['isGlobalStylesUserThemeJSON'] ) &&
     118                        true === $new['isGlobalStylesUserThemeJSON']
     119                ) {
     120                        return $new;
     121                }
     122
     123                /*
     124                 * Even though defaultFontSizes and defaultSpacingSizes are new
     125                 * settings, we need to migrate them as they each control
     126                 * PRESETS_METADATA prevent_override values which were previously
     127                 * hardcoded to false. This only needs to happen when the theme provides
     128                 * fontSizes or spacingSizes as they could match the default ones and
     129                 * affect the generated CSS.
     130                 */
     131                if ( isset( $old['settings']['typography']['fontSizes'] ) ) {
     132                        if ( ! isset( $new['settings'] ) ) {
     133                                $new['settings'] = array();
     134                        }
     135                        if ( ! isset( $new['settings']['typography'] ) ) {
     136                                $new['settings']['typography'] = array();
     137                        }
     138                        $new['settings']['typography']['defaultFontSizes'] = false;
     139                }
     140
     141                /*
     142                 * Similarly to defaultFontSizes, we need to migrate defaultSpacingSizes
     143                 * as it controls the PRESETS_METADATA prevent_override which was
     144                 * previously hardcoded to false. This only needs to happen when the
     145                 * theme provided spacing sizes via spacingSizes or spacingScale.
     146                 */
     147                if (
     148                        isset( $old['settings']['spacing']['spacingSizes'] ) ||
     149                        isset( $old['settings']['spacing']['spacingScale'] )
     150                ) {
     151                        if ( ! isset( $new['settings'] ) ) {
     152                                $new['settings'] = array();
     153                        }
     154                        if ( ! isset( $new['settings']['spacing'] ) ) {
     155                                $new['settings']['spacing'] = array();
     156                        }
     157                        $new['settings']['spacing']['defaultSpacingSizes'] = false;
     158                }
     159
     160                /*
     161                 * In v3 spacingSizes is merged with the generated spacingScale sizes
     162                 * instead of completely replacing them. The v3 behavior is what was
     163                 * documented for the v2 schema, but the code never actually did work
     164                 * that way. Instead of surprising users with a behavior change two
     165                 * years after the fact at the same time as a v3 update is introduced,
     166                 * we'll continue using the "bugged" behavior for v2 themes. And treat
     167                 * the "bug fix" as a breaking change for v3.
     168                 */
     169                if ( isset( $old['settings']['spacing']['spacingSizes'] ) ) {
     170                        unset( $new['settings']['spacing']['spacingScale'] );
     171                }
    83172
    84173                return $new;
  • trunk/src/wp-includes/class-wp-theme-json.php

    r58314 r58328  
    124124         * @since 6.2.0 Added 'shadow' presets.
    125125         * @since 6.3.0 Replaced value_func for duotone with `null`. Custom properties are handled by class-wp-duotone.php.
    126          * @since 6.6.0 Added the `dimensions.aspectRatios` & `dimensions.defaultAspectRatios` preset.
     126         * @since 6.6.0 Added the `dimensions.aspectRatios` and `dimensions.defaultAspectRatios` presets.
     127         *              Updated the 'prevent_override' value for font size presets to use 'typography.defaultFontSizes'
     128         *              and spacing size presets to use `spacing.defaultSpacingSizes`.
    127129         * @var array
    128130         */
    … …  
    170172                array(
    171173                        'path'              => array( 'typography', 'fontSizes' ),
    172                         'prevent_override'  => false,
     174                        'prevent_override'  => array( 'typography', 'defaultFontSizes' ),
    173175                        'use_default_names' => true,
    174176                        'value_func'        => 'wp_get_typography_font_size_value',
    … …  
    188190                array(
    189191                        'path'              => array( 'spacing', 'spacingSizes' ),
    190                         'prevent_override'  => false,
     192                        'prevent_override'  => array( 'spacing', 'defaultSpacingSizes' ),
    191193                        'use_default_names' => true,
    192194                        'value_key'         => 'size',
    … …  
    379381         * @since 6.5.0 Added support for `layout.allowCustomContentAndWideSize`,
    380382         *              `background.backgroundSize` and `dimensions.aspectRatio`.
    381          * @since 6.6.0 Added support for `dimensions.aspectRatios` and `dimensions.defaultAspectRatios`.
     383         * @since 6.6.0 Added support for 'dimensions.aspectRatios', 'dimensions.defaultAspectRatios',
     384         *              'typography.defaultFontSizes', and 'spacing.defaultSpacingSizes'.
    382385         * @var array
    383386         */
    … …  
    434437                ),
    435438                'spacing'                       => array(
    436                         'customSpacingSize' => null,
    437                         'spacingSizes'      => null,
    438                         'spacingScale'      => null,
    439                         'blockGap'          => null,
    440                         'margin'            => null,
    441                         'padding'           => null,
    442                         'units'             => null,
     439                        'customSpacingSize'   => null,
     440                        'defaultSpacingSizes' => null,
     441                        'spacingSizes'        => null,
     442                        'spacingScale'        => null,
     443                        'blockGap'            => null,
     444                        'margin'              => null,
     445                        'padding'             => null,
     446                        'units'               => null,
    443447                ),
    444448                'shadow'                        => array(
    … …  
    447451                ),
    448452                'typography'                    => array(
    449                         'fluid'          => null,
    450                         'customFontSize' => null,
    451                         'dropCap'        => null,
    452                         'fontFamilies'   => null,
    453                         'fontSizes'      => null,
    454                         'fontStyle'      => null,
    455                         'fontWeight'     => null,
    456                         'letterSpacing'  => null,
    457                         'lineHeight'     => null,
    458                         'textAlign'      => null,
    459                         'textColumns'    => null,
    460                         'textDecoration' => null,
    461                         'textTransform'  => null,
    462                         'writingMode'    => null,
     453                        'fluid'            => null,
     454                        'customFontSize'   => null,
     455                        'defaultFontSizes' => null,
     456                        'dropCap'          => null,
     457                        'fontFamilies'     => null,
     458                        'fontSizes'        => null,
     459                        'fontStyle'        => null,
     460                        'fontWeight'       => null,
     461                        'letterSpacing'    => null,
     462                        'lineHeight'       => null,
     463                        'textAlign'        => null,
     464                        'textColumns'      => null,
     465                        'textDecoration'   => null,
     466                        'textTransform'    => null,
     467                        'writingMode'      => null,
    463468                ),
    464469        );
    … …  
    729734         * @since 5.8.0
    730735         * @since 5.9.0 Changed value from 1 to 2.
     736         * @since 6.6.0 Changed value from 2 to 3.
    731737         * @var int
    732738         */
    733         const LATEST_SCHEMA = 2;
     739        const LATEST_SCHEMA = 3;
    734740
    735741        /**
    … …  
    737743         *
    738744         * @since 5.8.0
     745         * @since 6.6.0 Key spacingScale by origin, and Pre-generate the
     746         *              spacingSizes from spacingScale.
    739747         *
    740748         * @param array  $theme_json A structure that follows the theme.json schema.
    … …  
    742750         *                           One of 'default', 'theme', or 'custom'. Default 'theme'.
    743751         */
    744         public function __construct( $theme_json = array(), $origin = 'theme' ) {
     752        public function __construct( $theme_json = array( 'version' => WP_Theme_JSON::LATEST_SCHEMA ), $origin = 'theme' ) {
    745753                if ( ! in_array( $origin, static::VALID_ORIGINS, true ) ) {
    746754                        $origin = 'theme';
    … …  
    751759                $valid_element_names = array_keys( static::ELEMENTS );
    752760                $valid_variations    = static::get_valid_block_style_variations();
    753                 $theme_json          = static::sanitize( $this->theme_json, $valid_block_names, $valid_element_names, $valid_variations );
    754                 $this->theme_json    = static::maybe_opt_in_into_settings( $theme_json );
     761                $this->theme_json    = static::sanitize( $this->theme_json, $valid_block_names, $valid_element_names, $valid_variations );
     762                $this->theme_json    = static::maybe_opt_in_into_settings( $this->theme_json );
    755763
    756764                // Internally, presets are keyed by origin.
    … …  
    770778                                }
    771779                        }
     780                }
     781
     782                // In addition to presets, spacingScale (which generates presets) is also keyed by origin.
     783                $scale_path    = array( 'settings', 'spacing', 'spacingScale' );
     784                $spacing_scale = _wp_array_get( $this->theme_json, $scale_path, null );
     785                if ( null !== $spacing_scale ) {
     786                        // If the spacingScale is not already keyed by origin.
     787                        if ( empty( array_intersect( array_keys( $spacing_scale ), static::VALID_ORIGINS ) ) ) {
     788                                _wp_array_set( $this->theme_json, $scale_path, array( $origin => $spacing_scale ) );
     789                        }
     790                }
     791
     792                // Pre-generate the spacingSizes from spacingScale.
     793                $scale_path    = array( 'settings', 'spacing', 'spacingScale', $origin );
     794                $spacing_scale = _wp_array_get( $this->theme_json, $scale_path, null );
     795                if ( isset( $spacing_scale ) ) {
     796                        $sizes_path           = array( 'settings', 'spacing', 'spacingSizes', $origin );
     797                        $spacing_sizes        = _wp_array_get( $this->theme_json, $sizes_path, array() );
     798                        $spacing_scale_sizes  = static::compute_spacing_sizes( $spacing_scale );
     799                        $merged_spacing_sizes = static::merge_spacing_sizes( $spacing_scale_sizes, $spacing_sizes );
     800                        _wp_array_set( $this->theme_json, $sizes_path, $merged_spacing_sizes );
    772801                }
    773802        }
    … …  
    29152944                $incoming_data    = $incoming->get_raw_data();
    29162945                $this->theme_json = array_replace_recursive( $this->theme_json, $incoming_data );
     2946
     2947                /*
     2948                 * Recompute all the spacing sizes based on the new hierarchy of data. In the constructor
     2949                 * spacingScale and spacingSizes are both keyed by origin and VALID_ORIGINS is ordered, so
     2950                 * we can allow partial spacingScale data to inherit missing data from earlier layers when
     2951                 * computing the spacing sizes.
     2952                 *
     2953                 * This happens before the presets are merged to ensure that default spacing sizes can be
     2954                 * removed from the theme origin if $prevent_override is true.
     2955                 */
     2956                $flattened_spacing_scale = array();
     2957                foreach ( static::VALID_ORIGINS as $origin ) {
     2958                        $scale_path = array( 'settings', 'spacing', 'spacingScale', $origin );
     2959
     2960                        // Apply the base spacing scale to the current layer.
     2961                        $base_spacing_scale      = _wp_array_get( $this->theme_json, $scale_path, array() );
     2962                        $flattened_spacing_scale = array_replace( $flattened_spacing_scale, $base_spacing_scale );
     2963
     2964                        $spacing_scale = _wp_array_get( $incoming_data, $scale_path, null );
     2965                        if ( ! isset( $spacing_scale ) ) {
     2966                                continue;
     2967                        }
     2968
     2969                        // Allow partial scale settings by merging with lower layers.
     2970                        $flattened_spacing_scale = array_replace( $flattened_spacing_scale, $spacing_scale );
     2971
     2972                        // Generate and merge the scales for this layer.
     2973                        $sizes_path           = array( 'settings', 'spacing', 'spacingSizes', $origin );
     2974                        $spacing_sizes        = _wp_array_get( $incoming_data, $sizes_path, array() );
     2975                        $spacing_scale_sizes  = static::compute_spacing_sizes( $flattened_spacing_scale );
     2976                        $merged_spacing_sizes = static::merge_spacing_sizes( $spacing_scale_sizes, $spacing_sizes );
     2977
     2978                        _wp_array_set( $incoming_data, $sizes_path, $merged_spacing_sizes );
     2979                }
    29172980
    29182981                /*
    … …  
    29523015
    29533016                        // Replace the presets.
    2954                         foreach ( static::PRESETS_METADATA as $preset ) {
    2955                                 $override_preset = ! static::get_metadata_boolean( $this->theme_json['settings'], $preset['prevent_override'], true );
     3017                        foreach ( static::PRESETS_METADATA as $preset_metadata ) {
     3018                                $prevent_override = $preset_metadata['prevent_override'];
     3019                                if ( is_array( $prevent_override ) ) {
     3020                                        $prevent_override = _wp_array_get( $this->theme_json['settings'], $preset_metadata['prevent_override'] );
     3021                                }
    29563022
    29573023                                foreach ( static::VALID_ORIGINS as $origin ) {
    29583024                                        $base_path = $node['path'];
    2959                                         foreach ( $preset['path'] as $leaf ) {
     3025                                        foreach ( $preset_metadata['path'] as $leaf ) {
    29603026                                                $base_path[] = $leaf;
    29613027                                        }
    … …  
    29693035                                        }
    29703036
    2971                                         if ( 'theme' === $origin && $preset['use_default_names'] ) {
     3037                                        // Set names for theme presets based on the slug if they are not set and can use default names.
     3038                                        if ( 'theme' === $origin && $preset_metadata['use_default_names'] ) {
    29723039                                                foreach ( $content as $key => $item ) {
    29733040                                                        if ( ! isset( $item['name'] ) ) {
    … …  
    29803047                                        }
    29813048
    2982                                         if (
    2983                                                 ( 'theme' !== $origin ) ||
    2984                                                 ( 'theme' === $origin && $override_preset )
    2985                                         ) {
    2986                                                 _wp_array_set( $this->theme_json, $path, $content );
    2987                                         } else {
    2988                                                 $slugs_node = static::get_default_slugs( $this->theme_json, $node['path'] );
    2989                                                 $slugs      = array_merge_recursive( $slugs_global, $slugs_node );
    2990 
    2991                                                 $slugs_for_preset = _wp_array_get( $slugs, $preset['path'], array() );
    2992                                                 $content          = static::filter_slugs( $content, $slugs_for_preset );
    2993                                                 _wp_array_set( $this->theme_json, $path, $content );
     3049                                        // Filter out default slugs from theme presets when defaults should not be overridden.
     3050                                        if ( 'theme' === $origin && $prevent_override ) {
     3051                                                $slugs_node    = static::get_default_slugs( $this->theme_json, $node['path'] );
     3052                                                $preset_global = _wp_array_get( $slugs_global, $preset_metadata['path'], array() );
     3053                                                $preset_node   = _wp_array_get( $slugs_node, $preset_metadata['path'], array() );
     3054                                                $preset_slugs  = array_merge_recursive( $preset_global, $preset_node );
     3055
     3056                                                $content = static::filter_slugs( $content, $preset_slugs );
    29943057                                        }
     3058
     3059                                        _wp_array_set( $this->theme_json, $path, $content );
    29953060                                }
    29963061                        }
    … …  
    35293594                        }
    35303595                        $theme_settings['settings']['spacing']['padding'] = $settings['enableCustomSpacing'];
     3596                }
     3597
     3598                if ( isset( $settings['spacingSizes'] ) ) {
     3599                        if ( ! isset( $theme_settings['settings']['spacing'] ) ) {
     3600                                $theme_settings['settings']['spacing'] = array();
     3601                        }
     3602                        $theme_settings['settings']['spacing']['spacingSizes'] = $settings['spacingSizes'];
    35313603                }
    35323604
    … …  
    37043776         *
    37053777         * @since 6.1.0
     3778         * @deprecated 6.6.0
     3779         *
     3780         * @param string $origin Optional. What source of data to set the spacing sizes for.
     3781         *                       One of 'default', 'theme', or 'custom'. Default 'default'.
    37063782         *
    37073783         * @return null|void
    37083784         */
    37093785        public function set_spacing_sizes() {
     3786                _deprecated_function( __METHOD__, '6.6.0' );
     3787
    37103788                $spacing_scale = isset( $this->theme_json['settings']['spacing']['spacingScale'] )
    37113789                        ? $this->theme_json['settings']['spacing']['spacingScale']
    … …  
    37413819                }
    37423820
     3821                $spacing_sizes = static::compute_spacing_sizes( $spacing_scale );
     3822
     3823                // If there are 7 or fewer steps in the scale revert to numbers for labels instead of t-shirt sizes.
     3824                if ( $spacing_scale['steps'] <= 7 ) {
     3825                        for ( $spacing_sizes_count = 0; $spacing_sizes_count < count( $spacing_sizes ); $spacing_sizes_count++ ) {
     3826                                $spacing_sizes[ $spacing_sizes_count ]['name'] = (string) ( $spacing_sizes_count + 1 );
     3827                        }
     3828                }
     3829
     3830                _wp_array_set( $this->theme_json, array( 'settings', 'spacing', 'spacingSizes', 'default' ), $spacing_sizes );
     3831        }
     3832
     3833        /**
     3834         * Merges two sets of spacing size presets.
     3835         *
     3836         * @since 6.6.0
     3837         *
     3838         * @param array $base     The base set of spacing sizes.
     3839         * @param array $incoming The set of spacing sizes to merge with the base. Duplicate slugs will override the base values.
     3840         * @return array The merged set of spacing sizes.
     3841         */
     3842        private static function merge_spacing_sizes( $base, $incoming ) {
     3843                // Preserve the order if there are no base (spacingScale) values.
     3844                if ( empty( $base ) ) {
     3845                        return $incoming;
     3846                }
     3847                $merged = array();
     3848                foreach ( $base as $item ) {
     3849                        $merged[ $item['slug'] ] = $item;
     3850                }
     3851                foreach ( $incoming as $item ) {
     3852                        $merged[ $item['slug'] ] = $item;
     3853                }
     3854                ksort( $merged, SORT_NUMERIC );
     3855                return array_values( $merged );
     3856        }
     3857
     3858        /**
     3859         * Generates a set of spacing sizes by starting with a medium size and
     3860         * applying an operator with an increment value to generate the rest of the
     3861         * sizes outward from the medium size. The medium slug is '50' with the rest
     3862         * of the slugs being 10 apart. The generated names use t-shirt sizing.
     3863         *
     3864         * Example:
     3865         *
     3866         *     $spacing_scale = array(
     3867         *         'steps'      => 4,
     3868         *         'mediumStep' => 16,
     3869         *         'unit'       => 'px',
     3870         *         'operator'   => '+',
     3871         *         'increment'  => 2,
     3872         *     );
     3873         *     $spacing_sizes = static::compute_spacing_sizes( $spacing_scale );
     3874         *     // -> array(
     3875         *     //        array( 'name' => 'Small',   'slug' => '40', 'size' => '14px' ),
     3876         *     //        array( 'name' => 'Medium',  'slug' => '50', 'size' => '16px' ),
     3877         *     //        array( 'name' => 'Large',   'slug' => '60', 'size' => '18px' ),
     3878         *     //        array( 'name' => 'X-Large', 'slug' => '70', 'size' => '20px' ),
     3879         *     //    )
     3880         *
     3881         * @since 6.6.0
     3882         *
     3883         * @param array $spacing_scale {
     3884         *      The spacing scale values. All are required.
     3885         *
     3886         *      @type int    $steps      The number of steps in the scale. (up to 10 steps are supported.)
     3887         *      @type float  $mediumStep The middle value that gets the slug '50'. (For even number of steps, this becomes the first middle value.)
     3888         *      @type string $unit       The CSS unit to use for the sizes.
     3889         *      @type string $operator   The mathematical operator to apply to generate the other sizes. Either '+' or '*'.
     3890         *      @type float  $increment  The value used with the operator to generate the other sizes.
     3891         * }
     3892         * @return array The spacing sizes presets or an empty array if some spacing scale values are missing or invalid.
     3893         */
     3894        private static function compute_spacing_sizes( $spacing_scale ) {
     3895                /*
     3896                 * This condition is intentionally missing some checks on ranges for the values in order to
     3897                 * keep backwards compatibility with the previous implementation.
     3898                 */
     3899                if (
     3900                        ! isset( $spacing_scale['steps'] ) ||
     3901                        ! is_numeric( $spacing_scale['steps'] ) ||
     3902                        0 === $spacing_scale['steps'] ||
     3903                        ! isset( $spacing_scale['mediumStep'] ) ||
     3904                        ! is_numeric( $spacing_scale['mediumStep'] ) ||
     3905                        ! isset( $spacing_scale['unit'] ) ||
     3906                        ! isset( $spacing_scale['operator'] ) ||
     3907                        ( '+' !== $spacing_scale['operator'] && '*' !== $spacing_scale['operator'] ) ||
     3908                        ! isset( $spacing_scale['increment'] ) ||
     3909                        ! is_numeric( $spacing_scale['increment'] )
     3910                ) {
     3911                        return array();
     3912                }
     3913
    37433914                $unit            = '%' === $spacing_scale['unit'] ? '%' : sanitize_title( $spacing_scale['unit'] );
    37443915                $current_step    = $spacing_scale['mediumStep'];
    … …  
    38233994                }
    38243995
    3825                 // If there are 7 or fewer steps in the scale revert to numbers for labels instead of t-shirt sizes.
    3826                 if ( $spacing_scale['steps'] <= 7 ) {
    3827                         for ( $spacing_sizes_count = 0; $spacing_sizes_count < count( $spacing_sizes ); $spacing_sizes_count++ ) {
    3828                                 $spacing_sizes[ $spacing_sizes_count ]['name'] = (string) ( $spacing_sizes_count + 1 );
    3829                         }
    3830                 }
    3831 
    3832                 _wp_array_set( $this->theme_json, array( 'settings', 'spacing', 'spacingSizes', 'default' ), $spacing_sizes );
     3996                return $spacing_sizes;
    38333997        }
    38343998
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-font-faces-controller.php

    r57868 r58328  
    1919         * @var int
    2020         */
    21         const LATEST_THEME_JSON_VERSION_SUPPORTED = 2;
     21        const LATEST_THEME_JSON_VERSION_SUPPORTED = 3;
    2222
    2323        /**
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-font-families-controller.php

    r57548 r58328  
    2121         * @var int
    2222         */
    23         const LATEST_THEME_JSON_VERSION_SUPPORTED = 2;
     23        const LATEST_THEME_JSON_VERSION_SUPPORTED = 3;
    2424
    2525        /**
  • trunk/src/wp-includes/theme.json

    r58314 r58328  
    11{
    22        "$schema": "https://schemas.wp.org/trunk/theme.json",
    3         "version": 2,
     3        "version": 3,
    44        "settings": {
    55                "appearanceTools": false,
    … …  
    266266                        "padding": false,
    267267                        "customSpacingSize": true,
     268                        "defaultSpacingSizes": true,
    268269                        "units": [ "px", "em", "rem", "vh", "vw", "%" ],
    269270                        "spacingScale": {
    … …  
    277278                "typography": {
    278279                        "customFontSize": true,
     280                        "defaultFontSizes": true,
    279281                        "dropCap": true,
    280282                        "fontSizes": [
  • trunk/src/wp-includes/theme.php

    r58213 r58328  
    26432643 * @since 6.5.0 The `appearance-tools` feature enables a few design tools for blocks,
    26442644 *              see `WP_Theme_JSON::APPEARANCE_TOOLS_OPT_INS` for a complete list.
     2645 * @since 6.6.0 The `editor-spacing-sizes` feature was added.
    26452646 *
    26462647 * @global array $_wp_theme_features
    … …  
    26702671 *                          - 'editor-gradient-presets'
    26712672 *                          - 'editor-font-sizes'
     2673 *                          - 'editor-spacing-sizes'
    26722674 *                          - 'editor-styles'
    26732675 *                          - 'featured-content'
    … …  
    42284230        );
    42294231        register_theme_feature(
     4232                'editor-spacing-sizes',
     4233                array(
     4234                        'type'         => 'array',
     4235                        'description'  => __( 'Custom spacing sizes if defined by the theme.' ),
     4236                        'show_in_rest' => array(
     4237                                'schema' => array(
     4238                                        'items' => array(
     4239                                                'type'       => 'object',
     4240                                                'properties' => array(
     4241                                                        'name' => array(
     4242                                                                'type' => 'string',
     4243                                                        ),
     4244                                                        'size' => array(
     4245                                                                'type' => 'string',
     4246                                                        ),
     4247                                                        'slug' => array(
     4248                                                                'type' => 'string',
     4249                                                        ),
     4250                                                ),
     4251                                        ),
     4252                                ),
     4253                        ),
     4254                )
     4255        );
     4256        register_theme_feature(
    42304257                'editor-styles',
    42314258                array(
  • trunk/tests/phpunit/data/themedir1/block-theme-child-with-fluid-layout/theme.json

    r57336 r58328  
    11{
    22        "$schema": "https://schemas.wp.org/trunk/theme.json",
    3         "version": 2,
     3        "version": 3,
    44        "settings": {
    55                "appearanceTools": true,
  • trunk/tests/phpunit/data/themedir1/block-theme-child-with-fluid-typography-config/theme.json

    r57336 r58328  
    11{
    22        "$schema": "https://schemas.wp.org/trunk/theme.json",
    3         "version": 2,
     3        "version": 3,
    44        "settings": {
    55                "appearanceTools": true,
  • trunk/tests/phpunit/data/themedir1/block-theme-child-with-fluid-typography/theme.json

    r57336 r58328  
    11{
    22        "$schema": "https://schemas.wp.org/trunk/theme.json",
    3         "version": 2,
     3        "version": 3,
    44        "settings": {
    55                "appearanceTools": true,
  • trunk/tests/phpunit/data/themedir1/block-theme-child/styles/variation-a.json

    r57662 r58328  
    11{
    2         "version": 2,
     2        "version": 3,
    33        "settings": {
    44                "blocks": {
  • trunk/tests/phpunit/data/themedir1/block-theme-child/styles/variation-b.json

    r55231 r58328  
    11{
    2         "version": 2,
     2        "version": 3,
    33        "settings": {
    44                "blocks": {
  • trunk/tests/phpunit/data/themedir1/block-theme-child/theme.json

    r57662 r58328  
    11{
    22        "$schema": "https://schemas.wp.org/trunk/theme.json",
    3         "version": 2,
     3        "version": 3,
    44        "settings": {
    55                "color": {
  • trunk/tests/phpunit/data/themedir1/block-theme-deprecated-path/styles/variation.json

    r53416 r58328  
    11{
    2     "version": 2,
    3     "settings": {
    4         "color": {
    5             "palette": [
    6                 {
    7                     "slug": "foreground",
    8                     "color": "#3F67C6",
    9                     "name": "Foreground"
    10                 }
    11             ]
    12         }
    13     },
    14     "styles": {
    15         "blocks": {
    16             "core/post-title": {
    17                 "typography": {
    18                     "fontWeight": "700"
    19                 }
    20             }
    21         }
    22     }
     2        "version": 3,
     3        "settings": {
     4                "color": {
     5                        "palette": [
     6                                {
     7                                        "slug": "foreground",
     8                                        "color": "#3F67C6",
     9                                        "name": "Foreground"
     10                                }
     11                        ]
     12                }
     13        },
     14        "styles": {
     15                "blocks": {
     16                        "core/post-title": {
     17                                "typography": {
     18                                        "fontWeight": "700"
     19                                }
     20                        }
     21                }
     22        }
    2323}
  • trunk/tests/phpunit/data/themedir1/block-theme-with-hooked-blocks/theme.json

    r56759 r58328  
    11{
    22        "$schema": "https://schemas.wp.org/trunk/theme.json",
    3         "version": 2,
     3        "version": 3,
    44        "templateParts": [
    55                {
  • trunk/tests/phpunit/data/themedir1/block-theme/styles/variation-a.json

    r57662 r58328  
    11{
    2         "version": 2,
     2        "version": 3,
    33        "settings": {
    44                "blocks": {
  • trunk/tests/phpunit/data/themedir1/block-theme/styles/variation-b.json

    r58262 r58328  
    11{
    2         "version": 2,
     2        "version": 3,
    33        "settings": {
    44                "blocks": {
  • trunk/tests/phpunit/data/themedir1/block-theme/styles/variation.json

    r54036 r58328  
    11{
    2         "version": 2,
     2        "version": 3,
    33        "title": "Block theme variation",
    44        "settings": {
  • trunk/tests/phpunit/data/themedir1/block-theme/theme.json

    r57885 r58328  
    11{
    22        "$schema": "https://schemas.wp.org/trunk/theme.json",
    3         "version": 2,
     3        "version": 3,
    44        "title": "Block theme",
    55        "settings": {
  • trunk/tests/phpunit/data/themedir1/empty-fontface-theme/theme.json

    r57336 r58328  
    11{
    22        "$schema": "https://schemas.wp.org/trunk/theme.json",
    3   "version": 2,
    4   "customTemplates": [
    5         {
    6           "name": "blank",
    7           "title": "Blank",
    8           "postTypes": [
    9                 "page",
    10                 "post"
    11           ]
    12         }
    13   ],
    14   "settings": {
    15         "appearanceTools": true,
    16         "color": {
    17           "duotone": [],
    18           "gradients": [],
    19           "palette": []
     3        "version": 3,
     4        "customTemplates": [
     5                {
     6                        "name": "blank",
     7                        "title": "Blank",
     8                        "postTypes": [ "page", "post" ]
     9                }
     10        ],
     11        "settings": {
     12                "appearanceTools": true,
     13                "color": {
     14                        "duotone": [],
     15                        "gradients": [],
     16                        "palette": []
     17                },
     18                "custom": {},
     19                "spacing": {
     20                        "units": [ "%", "px", "em", "rem", "vh", "vw" ]
     21                },
     22                "typography": {
     23                        "dropCap": false,
     24                        "fontFamilies": [
     25                                {
     26                                        "fontFamily": "Roboto",
     27                                        "name": "Roboto",
     28                                        "slug": "roboto",
     29                                        "fontFace": []
     30                                }
     31                        ],
     32                        "fontSizes": [
     33                                {
     34                                        "size": "1rem",
     35                                        "slug": "small"
     36                                },
     37                                {
     38                                        "size": "1.125rem",
     39                                        "slug": "medium"
     40                                },
     41                                {
     42                                        "size": "1.75rem",
     43                                        "slug": "large"
     44                                },
     45                                {
     46                                        "size": "clamp(1.75rem, 3vw, 2.25rem)",
     47                                        "slug": "x-large"
     48                                }
     49                        ]
     50                },
     51                "layout": {
     52                        "contentSize": "650px",
     53                        "wideSize": "1000px"
     54                }
    2055        },
    21         "custom": {},
    22         "spacing": {
    23           "units": [
    24                 "%",
    25                 "px",
    26                 "em",
    27                 "rem",
    28                 "vh",
    29                 "vw"
    30           ]
     56        "styles": {
     57                "blocks": {},
     58                "color": {
     59                        "background": "var(--wp--preset--color--background)",
     60                        "text": "var(--wp--preset--color--foreground)"
     61                },
     62                "elements": {},
     63                "spacing": {
     64                        "blockGap": "1.5rem"
     65                },
     66                "typography": {
     67                        "fontFamily": "var(--wp--preset--font-family--system-font)",
     68                        "lineHeight": "var(--wp--custom--typography--line-height--normal)",
     69                        "fontSize": "var(--wp--preset--font-size--medium)"
     70                }
    3171        },
    32         "typography": {
    33           "dropCap": false,
    34           "fontFamilies": [
     72        "templateParts": [
    3573                {
    36                   "fontFamily": "Roboto",
    37                   "name": "Roboto",
    38                   "slug": "roboto",
    39                   "fontFace": []
     74                        "name": "header",
     75                        "title": "Header",
     76                        "area": "header"
    4077                }
    41           ],
    42           "fontSizes": [
    43                 {
    44                   "size": "1rem",
    45                   "slug": "small"
    46                 },
    47                 {
    48                   "size": "1.125rem",
    49                   "slug": "medium"
    50                 },
    51                 {
    52                   "size": "1.75rem",
    53                   "slug": "large"
    54                 },
    55                 {
    56                   "size": "clamp(1.75rem, 3vw, 2.25rem)",
    57                   "slug": "x-large"
    58                 }
    59           ]
    60         },
    61         "layout": {
    62           "contentSize": "650px",
    63           "wideSize": "1000px"
    64         }
    65   },
    66   "styles": {
    67         "blocks": {},
    68         "color": {
    69           "background": "var(--wp--preset--color--background)",
    70           "text": "var(--wp--preset--color--foreground)"
    71         },
    72         "elements": {},
    73         "spacing": {
    74           "blockGap": "1.5rem"
    75         },
    76         "typography": {
    77           "fontFamily": "var(--wp--preset--font-family--system-font)",
    78           "lineHeight": "var(--wp--custom--typography--line-height--normal)",
    79           "fontSize": "var(--wp--preset--font-size--medium)"
    80         }
    81   },
    82   "templateParts": [
    83         {
    84           "name": "header",
    85           "title": "Header",
    86           "area": "header"
    87         }
    88   ]
     78        ]
    8979}
  • trunk/tests/phpunit/data/themedir1/fonts-block-theme/styles/variation-duplicate-fonts.json

    r56500 r58328  
    11{
    2         "version": 2,
     2        "version": 3,
    33        "title": "Variation: duplicate fonts",
    44        "settings": {
  • trunk/tests/phpunit/data/themedir1/fonts-block-theme/styles/variation-new-font-family.json

    r57788 r58328  
    11{
    2         "version": 2,
     2        "version": 3,
    33        "title": "Variation: new font family",
    44        "settings": {
  • trunk/tests/phpunit/data/themedir1/fonts-block-theme/styles/variation-new-font-variations.json

    r56500 r58328  
    11{
    2         "version": 2,
     2        "version": 3,
    33        "title": "Variation: new font variations",
    44        "settings": {
  • trunk/tests/phpunit/data/themedir1/fonts-block-theme/styles/variation-no-fonts.json

    r56500 r58328  
    11{
    2         "version": 2,
     2        "version": 3,
    33        "title": "Variation - no fonts",
    44        "styles": {
  • trunk/tests/phpunit/data/themedir1/fonts-block-theme/theme.json

    r57336 r58328  
    11{
    22        "$schema": "https://schemas.wp.org/trunk/theme.json",
    3         "version": 2,
     3        "version": 3,
    44        "settings": {
    55                "appearanceTools": true,
  • trunk/tests/phpunit/tests/fonts/font-library/wpRestFontFacesController.php

    r57548 r58328  
    624624                return array(
    625625                        array( 1 ),
    626                         array( 3 ),
     626                        array( 4 ),
    627627                );
    628628        }
  • trunk/tests/phpunit/tests/fonts/font-library/wpRestFontFamiliesController.php

    r57987 r58328  
    432432                return array(
    433433                        array( 1 ),
    434                         array( 3 ),
     434                        array( 4 ),
    435435                );
    436436        }
  • trunk/tests/phpunit/tests/rest-api/rest-global-styles-controller.php

    r58262 r58328  
    151151                $expected = array(
    152152                        array(
    153                                 'version'  => 2,
     153                                'version'  => WP_Theme_JSON::LATEST_SCHEMA,
    154154                                'settings' => array(
    155155                                        'blocks' => array(
    … …  
    172172                        ),
    173173                        array(
    174                                 'version'  => 2,
     174                                'version'  => WP_Theme_JSON::LATEST_SCHEMA,
    175175                                'settings' => array(
    176176                                        'blocks' => array(
    … …  
    217217                        ),
    218218                        array(
    219                                 'version'  => 2,
     219                                'version'  => WP_Theme_JSON::LATEST_SCHEMA,
    220220                                'title'    => 'Block theme variation',
    221221                                'settings' => array(
  • trunk/tests/phpunit/tests/rest-api/rest-themes-controller.php

    r58282 r58328  
    420420                $this->assertArrayHasKey( 'editor-font-sizes', $theme_supports );
    421421                $this->assertArrayHasKey( 'editor-gradient-presets', $theme_supports );
     422                $this->assertArrayHasKey( 'editor-spacing-sizes', $theme_supports );
    422423                $this->assertArrayHasKey( 'editor-styles', $theme_supports );
    423424                $this->assertArrayHasKey( 'formats', $theme_supports );
    … …  
    427428                $this->assertArrayHasKey( 'title-tag', $theme_supports );
    428429                $this->assertArrayHasKey( 'wp-block-styles', $theme_supports );
    429                 $this->assertCount( 23, $theme_supports, 'There should be 23 theme supports' );
     430                $this->assertCount( 24, $theme_supports, 'There should be 23 theme supports' );
    430431        }
    431432
  • trunk/tests/phpunit/tests/theme/wpThemeJson.php

    r58314 r58328  
    33013301                $theme = new WP_Theme_JSON(
    33023302                        array(
    3303                                 'version'  => 2,
     3303                                'version'  => WP_Theme_JSON::LATEST_SCHEMA,
    33043304                                'settings' => array(
    33053305                                        'color' => array(
    … …  
    33223322                $user  = new WP_Theme_JSON(
    33233323                        array(
    3324                                 'version'  => 2,
     3324                                'version'  => WP_Theme_JSON::LATEST_SCHEMA,
    33253325                                'settings' => array(
    33263326                                        'color' => array(
    … …  
    33463346                $actual   = $theme->get_data();
    33473347                $expected = array(
    3348                         'version'  => 2,
     3348                        'version'  => WP_Theme_JSON::LATEST_SCHEMA,
    33493349                        'settings' => array(
    33503350                                'color' => array(
    … …  
    33793379                $theme = new WP_Theme_JSON(
    33803380                        array(
    3381                                 'version'  => 2,
     3381                                'version'  => WP_Theme_JSON::LATEST_SCHEMA,
    33823382                                'settings' => array(
    33833383                                        'color' => array(
    … …  
    34013401                $actual   = $theme->get_data();
    34023402                $expected = array(
    3403                         'version'  => 2,
     3403                        'version'  => WP_Theme_JSON::LATEST_SCHEMA,
    34043404                        'settings' => array(
    34053405                                'color' => array(
    … …  
    34293429                $user = new WP_Theme_JSON(
    34303430                        array(
    3431                                 'version'  => 2,
     3431                                'version'  => WP_Theme_JSON::LATEST_SCHEMA,
    34323432                                'settings' => array(
    34333433                                        'color' => array(
    … …  
    34523452                $actual   = $user->get_data();
    34533453                $expected = array(
    3454                         'version'  => 2,
     3454                        'version'  => WP_Theme_JSON::LATEST_SCHEMA,
    34553455                        'settings' => array(
    34563456                                'color' => array(
    … …  
    34783478         */
    34793479        public function test_export_data_deals_with_empty_data() {
    3480                 $theme_v2    = new WP_Theme_JSON(
    3481                         array(
    3482                                 'version' => 2,
     3480                $theme    = new WP_Theme_JSON(
     3481                        array(
     3482                                'version' => WP_Theme_JSON::LATEST_SCHEMA,
    34833483                        ),
    34843484                        'theme'
    34853485                );
    3486                 $actual_v2   = $theme_v2->get_data();
    3487                 $expected_v2 = array( 'version' => 2 );
    3488                 $this->assertEqualSetsWithIndex( $expected_v2, $actual_v2 );
    3489 
    3490                 $theme_v1    = new WP_Theme_JSON(
    3491                         array(
    3492                                 'version' => 1,
    3493                         ),
    3494                         'theme'
    3495                 );
    3496                 $actual_v1   = $theme_v1->get_data();
    3497                 $expected_v1 = array( 'version' => 2 );
    3498                 $this->assertEqualSetsWithIndex( $expected_v1, $actual_v1 );
     3486                $actual   = $theme->get_data();
     3487                $expected = array( 'version' => WP_Theme_JSON::LATEST_SCHEMA );
     3488                $this->assertEqualSetsWithIndex( $expected, $actual );
    34993489        }
    35003490
    … …  
    35053495                $theme = new WP_Theme_JSON(
    35063496                        array(
    3507                                 'version'  => 2,
     3497                                'version'  => WP_Theme_JSON::LATEST_SCHEMA,
    35083498                                'settings' => array(
    35093499                                        'appearanceTools' => true,
    … …  
    35193509                $actual   = $theme->get_data();
    35203510                $expected = array(
    3521                         'version'  => 2,
     3511                        'version'  => WP_Theme_JSON::LATEST_SCHEMA,
    35223512                        'settings' => array(
    35233513                                'appearanceTools' => true,
    … …  
    35393529                $theme = new WP_Theme_JSON(
    35403530                        array(
    3541                                 'version'  => 2,
     3531                                'version'  => WP_Theme_JSON::LATEST_SCHEMA,
    35423532                                'settings' => array(
    35433533                                        'useRootPaddingAwareAlignments' => true,
    … …  
    35533543                $actual   = $theme->get_data();
    35543544                $expected = array(
    3555                         'version'  => 2,
     3545                        'version'  => WP_Theme_JSON::LATEST_SCHEMA,
    35563546                        'settings' => array(
    35573547                                'useRootPaddingAwareAlignments' => true,
    … …  
    36453635                $theme_json = new WP_Theme_JSON(
    36463636                        array(
    3647                                 'version' => 2,
     3637                                'version' => WP_Theme_JSON::LATEST_SCHEMA,
    36483638                                'styles'  => array(
    36493639                                        'color'    => array(
    … …  
    37303720                $theme_json = new WP_Theme_JSON(
    37313721                        array(
    3732                                 'version' => 2,
     3722                                'version' => WP_Theme_JSON::LATEST_SCHEMA,
    37333723                                'styles'  => array(
    37343724                                        'color'    => array(
    … …  
    37683758                $theme_json = new WP_Theme_JSON(
    37693759                        array(
    3770                                 'version' => 2,
     3760                                'version' => WP_Theme_JSON::LATEST_SCHEMA,
    37713761                                'styles'  => array(
    37723762                                        'color'    => array(
    … …  
    38053795                $theme_json = new WP_Theme_JSON(
    38063796                        array(
    3807                                 'version' => 2,
     3797                                'version' => WP_Theme_JSON::LATEST_SCHEMA,
    38083798                                'styles'  => array(
    38093799                                        'color' => array(
    … …  
    38313821                $theme_json = new WP_Theme_JSON(
    38323822                        array(
    3833                                 'version'  => 2,
     3823                                'version'  => WP_Theme_JSON::LATEST_SCHEMA,
    38343824                                'styles'   => array(
    38353825                                        'spacing' => array(
    … …  
    38683858                $theme_json = new WP_Theme_JSON(
    38693859                        array(
    3870                                 'version' => 2,
     3860                                'version' => WP_Theme_JSON::LATEST_SCHEMA,
    38713861                                'styles'  => array(
    38723862                                        'spacing' => array(
    … …  
    39013891                $theme_json = new WP_Theme_JSON(
    39023892                        array(
    3903                                 'version'  => 2,
     3893                                'version'  => WP_Theme_JSON::LATEST_SCHEMA,
    39043894                                'settings' => array(
    39053895                                        'layout' => array(
    … …  
    39323922                $theme_json = new WP_Theme_JSON(
    39333923                        array(
    3934                                 'version'  => 2,
     3924                                'version'  => WP_Theme_JSON::LATEST_SCHEMA,
    39353925                                'settings' => array(
    39363926                                        'appearanceTools' => true,
    … …  
    39553945                $theme_json = new WP_Theme_JSON(
    39563946                        array(
    3957                                 'version' => 2,
     3947                                'version' => WP_Theme_JSON::LATEST_SCHEMA,
    39583948                                'styles'  => array(
    39593949                                        'spacing' => array(
    … …  
    39743964                $actual   = $theme_json->get_raw_data();
    39753965                $expected = array(
    3976                         'version' => 2,
     3966                        'version' => WP_Theme_JSON::LATEST_SCHEMA,
    39773967                        'styles'  => array(
    39783968                                'spacing' => array(
    … …  
    39983988                $theme_json = new WP_Theme_JSON(
    39993989                        array(
    4000                                 'version' => 2,
     3990                                'version' => WP_Theme_JSON::LATEST_SCHEMA,
    40013991                                'styles'  => array(
    40023992                                        'blocks' => array(
    … …  
    40224012                $sanitized_theme_json = $theme_json->get_raw_data();
    40234013                $expected             = array(
    4024                         'version' => 2,
     4014                        'version' => WP_Theme_JSON::LATEST_SCHEMA,
    40254015                        'styles'  => array(
    40264016                                'blocks' => array(
    … …  
    40514041                $theme_json = new WP_Theme_JSON(
    40524042                        array(
    4053                                 'version' => 2,
     4043                                'version' => WP_Theme_JSON::LATEST_SCHEMA,
    40544044                                'styles'  => array(
    40554045                                        'blocks' => array(
    … …  
    41354125                $theme_json = new WP_Theme_JSON(
    41364126                        array(
    4137                                 'version'  => '2',
     4127                                'version'  => WP_Theme_JSON::LATEST_SCHEMA,
    41384128                                'badKey2'  => 'I am Evil!',
    41394129                                'settings' => array(
    … …  
    42034193
    42044194                $expected_sanitized   = array(
    4205                         'version'  => '2',
     4195                        'version'  => WP_Theme_JSON::LATEST_SCHEMA,
    42064196                        'settings' => array(
    42074197                                'typography' => array(
    … …  
    42724262                $theme_json = new WP_Theme_JSON(
    42734263                        array(
    4274                                 'version' => 2,
     4264                                'version' => WP_Theme_JSON::LATEST_SCHEMA,
    42754265                                'styles'  => array(
    42764266                                        'blocks' => array(
    … …  
    43204310                $theme_json = new WP_Theme_JSON(
    43214311                        array(
    4322                                 'version' => 2,
     4312                                'version' => WP_Theme_JSON::LATEST_SCHEMA,
    43234313                                'styles'  => array(
    43244314                                        'blocks' => array(
    … …  
    44744464                $theme_json = new WP_Theme_JSON(
    44754465                        array(
    4476                                 'version'  => 2,
     4466                                'version'  => WP_Theme_JSON::LATEST_SCHEMA,
    44774467                                'settings' => array(
    44784468                                        'spacing' => array(
    … …  
    44804470                                        ),
    44814471                                ),
    4482                         )
    4483                 );
    4484 
    4485                 $theme_json->set_spacing_sizes();
     4472                        ),
     4473                        'default'
     4474                );
     4475
    44864476                $this->assertSame( $expected_output, _wp_array_get( $theme_json->get_raw_data(), array( 'settings', 'spacing', 'spacingSizes', 'default' ) ) );
    44874477        }
    … …  
    45064496                                'expected_output' => array(
    45074497                                        array(
    4508                                                 'name' => '1',
     4498                                                'name' => 'Medium',
    45094499                                                'slug' => '50',
    45104500                                                'size' => '4rem',
    … …  
    45224512                                'expected_output' => array(
    45234513                                        array(
    4524                                                 'name' => '1',
     4514                                                'name' => 'Medium',
    45254515                                                'slug' => '50',
    45264516                                                'size' => '4rem',
    45274517                                        ),
    45284518                                        array(
    4529                                                 'name' => '2',
     4519                                                'name' => 'Large',
    45304520                                                'slug' => '60',
    45314521                                                'size' => '5.5rem',
    … …  
    45434533                                'expected_output' => array(
    45444534                                        array(
    4545                                                 'name' => '1',
     4535                                                'name' => 'Small',
    45464536                                                'slug' => '40',
    45474537                                                'size' => '2.5rem',
    45484538                                        ),
    45494539                                        array(
    4550                                                 'name' => '2',
     4540                                                'name' => 'Medium',
    45514541                                                'slug' => '50',
    45524542                                                'size' => '4rem',
    45534543                                        ),
    45544544                                        array(
    4555                                                 'name' => '3',
     4545                                                'name' => 'Large',
    45564546                                                'slug' => '60',
    45574547                                                'size' => '5.5rem',
    … …  
    45694559                                'expected_output' => array(
    45704560                                        array(
    4571                                                 'name' => '1',
     4561                                                'name' => 'Small',
    45724562                                                'slug' => '40',
    45734563                                                'size' => '2.5rem',
    45744564                                        ),
    45754565                                        array(
    4576                                                 'name' => '2',
     4566                                                'name' => 'Medium',
    45774567                                                'slug' => '50',
    45784568                                                'size' => '4rem',
    45794569                                        ),
    45804570                                        array(
    4581                                                 'name' => '3',
     4571                                                'name' => 'Large',
    45824572                                                'slug' => '60',
    45834573                                                'size' => '5.5rem',
    45844574                                        ),
    45854575                                        array(
    4586                                                 'name' => '4',
     4576                                                'name' => 'X-Large',
    45874577                                                'slug' => '70',
    45884578                                                'size' => '7rem',
    … …  
    46004590                                'expected_output' => array(
    46014591                                        array(
    4602                                                 'name' => '1',
     4592                                                'name' => 'Small',
    46034593                                                'slug' => '40',
    46044594                                                'size' => '2.5rem',
    46054595                                        ),
    46064596                                        array(
    4607                                                 'name' => '2',
     4597                                                'name' => 'Medium',
    46084598                                                'slug' => '50',
    46094599                                                'size' => '5rem',
    46104600                                        ),
    46114601                                        array(
    4612                                                 'name' => '3',
     4602                                                'name' => 'Large',
    46134603                                                'slug' => '60',
    46144604                                                'size' => '7.5rem',
    46154605                                        ),
    46164606                                        array(
    4617                                                 'name' => '4',
     4607                                                'name' => 'X-Large',
    46184608                                                'slug' => '70',
    46194609                                                'size' => '10rem',
    46204610                                        ),
    46214611                                        array(
    4622                                                 'name' => '5',
     4612                                                'name' => '2X-Large',
    46234613                                                'slug' => '80',
    46244614                                                'size' => '12.5rem',
    … …  
    46364626                                'expected_output' => array(
    46374627                                        array(
    4638                                                 'name' => '1',
     4628                                                'name' => 'X-Small',
    46394629                                                'slug' => '30',
    46404630                                                'size' => '0.67rem',
    46414631                                        ),
    46424632                                        array(
    4643                                                 'name' => '2',
     4633                                                'name' => 'Small',
    46444634                                                'slug' => '40',
    46454635                                                'size' => '1rem',
    46464636                                        ),
    46474637                                        array(
    4648                                                 'name' => '3',
     4638                                                'name' => 'Medium',
    46494639                                                'slug' => '50',
    46504640                                                'size' => '1.5rem',
    46514641                                        ),
    46524642                                        array(
    4653                                                 'name' => '4',
     4643                                                'name' => 'Large',
    46544644                                                'slug' => '60',
    46554645                                                'size' => '2.25rem',
    46564646                                        ),
    46574647                                        array(
    4658                                                 'name' => '5',
     4648                                                'name' => 'X-Large',
    46594649                                                'slug' => '70',
    46604650                                                'size' => '3.38rem',
    … …  
    46724662                                'expected_output' => array(
    46734663                                        array(
    4674                                                 'name' => '1',
     4664                                                'name' => 'X-Small',
    46754665                                                'slug' => '30',
    46764666                                                'size' => '0.09rem',
    46774667                                        ),
    46784668                                        array(
    4679                                                 'name' => '2',
     4669                                                'name' => 'Small',
    46804670                                                'slug' => '40',
    46814671                                                'size' => '0.38rem',
    46824672                                        ),
    46834673                                        array(
    4684                                                 'name' => '3',
     4674                                                'name' => 'Medium',
    46854675                                                'slug' => '50',
    46864676                                                'size' => '1.5rem',
    46874677                                        ),
    46884678                                        array(
    4689                                                 'name' => '4',
     4679                                                'name' => 'Large',
    46904680                                                'slug' => '60',
    46914681                                                'size' => '6rem',
    46924682                                        ),
    46934683                                        array(
    4694                                                 'name' => '5',
     4684                                                'name' => 'X-Large',
    46954685                                                'slug' => '70',
    46964686                                                'size' => '24rem',
    … …  
    47634753         */
    47644754        public function test_set_spacing_sizes_when_invalid( $spacing_scale, $expected_output ) {
    4765                 $this->expectException( Exception::class );
    4766                 $this->expectExceptionMessage( 'Some of the theme.json settings.spacing.spacingScale values are invalid' );
    4767 
    47684755                $theme_json = new WP_Theme_JSON(
    47694756                        array(
    4770                                 'version'  => 2,
     4757                                'version'  => WP_Theme_JSON::LATEST_SCHEMA,
    47714758                                'settings' => array(
    47724759                                        'spacing' => array(
    … …  
    47744761                                        ),
    47754762                                ),
    4776                         )
    4777                 );
    4778 
    4779                 // Ensure PHPUnit 10 compatibility.
    4780                 set_error_handler(
    4781                         static function ( $errno, $errstr ) {
    4782                                 restore_error_handler();
    4783                                 throw new Exception( $errstr, $errno );
    4784                         },
    4785                         E_ALL
    4786                 );
    4787 
    4788                 $theme_json->set_spacing_sizes();
    4789 
    4790                 restore_error_handler();
     4763                        ),
     4764                        'default'
     4765                );
    47914766
    47924767                $this->assertSame( $expected_output, _wp_array_get( $theme_json->get_raw_data(), array( 'settings', 'spacing', 'spacingSizes', 'default' ) ) );
    … …  
    48104785                                        'unit'       => 'rem',
    48114786                                ),
    4812                                 'expected_output' => null,
     4787                                'expected_output' => array(),
    48134788                        ),
    48144789                        'non numeric increment'   => array(
    … …  
    48204795                                        'unit'       => 'rem',
    48214796                                ),
    4822                                 'expected_output' => null,
     4797                                'expected_output' => array(),
    48234798                        ),
    48244799                        'non numeric steps'       => array(
    … …  
    48304805                                        'unit'       => 'rem',
    48314806                                ),
    4832                                 'expected_output' => null,
     4807                                'expected_output' => array(),
    48334808                        ),
    48344809                        'non numeric medium step' => array(
    … …  
    48404815                                        'unit'       => 'rem',
    48414816                                ),
    4842                                 'expected_output' => null,
     4817                                'expected_output' => array(),
    48434818                        ),
    48444819                        'missing unit value'      => array(
    … …  
    48494824                                        'mediumStep' => 4,
    48504825                                ),
    4851                                 'expected_output' => null,
     4826                                'expected_output' => array(),
    48524827                        ),
    48534828                );
  • trunk/tests/phpunit/tests/theme/wpThemeJsonSchema.php

    r57662 r58328  
    4242                                ),
    4343                                'typography' => array(
     44                                        'fontSizes'      => array(
     45                                                array(
     46                                                        'name' => 'Small',
     47                                                        'slug' => 'small',
     48                                                        'size' => 12,
     49                                                ),
     50                                                array(
     51                                                        'name' => 'Normal',
     52                                                        'slug' => 'normal',
     53                                                        'size' => 16,
     54                                                ),
     55                                        ),
    4456                                        'fontStyle'      => false,
    4557                                        'fontWeight'     => false,
    … …  
    127139                                ),
    128140                                'typography' => array(
    129                                         'fontStyle'      => false,
    130                                         'fontWeight'     => false,
    131                                         'letterSpacing'  => false,
    132                                         'textDecoration' => false,
    133                                         'textTransform'  => false,
     141                                        'defaultFontSizes' => false,
     142                                        'fontSizes'        => array(
     143                                                array(
     144                                                        'name' => 'Small',
     145                                                        'slug' => 'small',
     146                                                        'size' => 12,
     147                                                ),
     148                                                array(
     149                                                        'name' => 'Normal',
     150                                                        'slug' => 'normal',
     151                                                        'size' => 16,
     152                                                ),
     153                                        ),
     154                                        'fontStyle'        => false,
     155                                        'fontWeight'       => false,
     156                                        'letterSpacing'    => false,
     157                                        'textDecoration'   => false,
     158                                        'textTransform'    => false,
    134159                                ),
    135160                                'blocks'     => array(
    … …  
    186211                $this->assertEqualSetsWithIndex( $expected, $actual );
    187212        }
     213
     214        public function test_migrate_v2_to_latest() {
     215                $theme_json_v2 = array(
     216                        'version'  => 2,
     217                        'settings' => array(
     218                                'typography' => array(
     219                                        'fontSizes' => array(
     220                                                array(
     221                                                        'name' => 'Small',
     222                                                        'slug' => 'small',
     223                                                        'size' => 12,
     224                                                ),
     225                                                array(
     226                                                        'name' => 'Normal',
     227                                                        'slug' => 'normal',
     228                                                        'size' => 16,
     229                                                ),
     230                                        ),
     231                                ),
     232                                'spacing'    => array(
     233                                        'spacingSizes' => array(
     234                                                array(
     235                                                        'name' => 'Small',
     236                                                        'slug' => 20,
     237                                                        'size' => '20px',
     238                                                ),
     239                                                array(
     240                                                        'name' => 'Large',
     241                                                        'slug' => 80,
     242                                                        'size' => '80px',
     243                                                ),
     244                                        ),
     245                                ),
     246                        ),
     247                );
     248
     249                $actual = WP_Theme_JSON_Schema::migrate( $theme_json_v2 );
     250
     251                $expected = array(
     252                        'version'  => WP_Theme_JSON::LATEST_SCHEMA,
     253                        'settings' => array(
     254                                'typography' => array(
     255                                        'defaultFontSizes' => false,
     256                                        'fontSizes'        => array(
     257                                                array(
     258                                                        'name' => 'Small',
     259                                                        'slug' => 'small',
     260                                                        'size' => 12,
     261                                                ),
     262                                                array(
     263                                                        'name' => 'Normal',
     264                                                        'slug' => 'normal',
     265                                                        'size' => 16,
     266                                                ),
     267                                        ),
     268                                ),
     269                                'spacing'    => array(
     270                                        'defaultSpacingSizes' => false,
     271                                        'spacingSizes'        => array(
     272                                                array(
     273                                                        'name' => 'Small',
     274                                                        'slug' => 20,
     275                                                        'size' => '20px',
     276                                                ),
     277                                                array(
     278                                                        'name' => 'Large',
     279                                                        'slug' => 80,
     280                                                        'size' => '80px',
     281                                                ),
     282                                        ),
     283                                ),
     284                        ),
     285                );
     286
     287                $this->assertEqualSetsWithIndex( $expected, $actual );
     288        }
    188289}
  • trunk/tests/qunit/fixtures/wp-api-generated.js

    r58326 r58328  
    78567856                            "description": "Version of the theme.json schema used for the typography settings.",
    78577857                            "type": "integer",
    7858                             "default": 2,
     7858                            "default": 3,
    78597859                            "minimum": 2,
    7860                             "maximum": 2,
     7860                            "maximum": 3,
    78617861                            "required": false
    78627862                        },
    … …  
    79257925                            "description": "Version of the theme.json schema used for the typography settings.",
    79267926                            "type": "integer",
    7927                             "default": 2,
     7927                            "default": 3,
    79287928                            "minimum": 2,
    7929                             "maximum": 2,
     7929                            "maximum": 3,
    79307930                            "required": false
    79317931                        },
    … …  
    80588058                            "description": "Version of the theme.json schema used for the typography settings.",
    80598059                            "type": "integer",
    8060                             "default": 2,
     8060                            "default": 3,
    80618061                            "minimum": 2,
    8062                             "maximum": 2,
     8062                            "maximum": 3,
    80638063                            "required": false
    80648064                        },
Note: See TracChangeset for help on using the changeset viewer.