Make WordPress Core

Changeset 58328


Ignore:
Timestamp:
06/04/2024 11:53:37 AM (4 months 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.