diff -r 7b1b88e27a20 -r 48c4eec2b7e6 wp/wp-includes/class-wp-theme-json-schema.php --- a/wp/wp-includes/class-wp-theme-json-schema.php Thu Sep 29 08:06:27 2022 +0200 +++ b/wp/wp-includes/class-wp-theme-json-schema.php Fri Sep 05 18:40:08 2025 +0200 @@ -17,6 +17,7 @@ * @since 5.9.0 * @access private */ +#[AllowDynamicProperties] class WP_Theme_JSON_Schema { /** @@ -34,20 +35,27 @@ * Function that migrates a given theme.json structure to the last version. * * @since 5.9.0 + * @since 6.6.0 Migrate up to v3 and add $origin parameter. * * @param array $theme_json The structure to migrate. - * + * @param string $origin Optional. What source of data this object represents. + * One of 'blocks', 'default', 'theme', or 'custom'. Default 'theme'. * @return array The structure in the last version. */ - public static function migrate( $theme_json ) { + public static function migrate( $theme_json, $origin = 'theme' ) { if ( ! isset( $theme_json['version'] ) ) { $theme_json = array( 'version' => WP_Theme_JSON::LATEST_SCHEMA, ); } - if ( 1 === $theme_json['version'] ) { - $theme_json = self::migrate_v1_to_v2( $theme_json ); + // Migrate each version in order starting with the current version. + switch ( $theme_json['version'] ) { + case 1: + $theme_json = self::migrate_v1_to_v2( $theme_json ); + // Deliberate fall through. Once migrated to v2, also migrate to v3. + case 2: + $theme_json = self::migrate_v2_to_v3( $theme_json, $origin ); } return $theme_json; @@ -84,6 +92,77 @@ } /** + * Migrates from v2 to v3. + * + * - Sets settings.typography.defaultFontSizes to false if settings.typography.fontSizes are defined. + * - Sets settings.spacing.defaultSpacingSizes to false if settings.spacing.spacingSizes are defined. + * - Prevents settings.spacing.spacingSizes from merging with settings.spacing.spacingScale by + * unsetting spacingScale when spacingSizes are defined. + * + * @since 6.6.0 + * + * @param array $old Data to migrate. + * @param string $origin What source of data this object represents. + * One of 'blocks', 'default', 'theme', or 'custom'. + * @return array Data with defaultFontSizes set to false. + */ + private static function migrate_v2_to_v3( $old, $origin ) { + // Copy everything. + $new = $old; + + // Set the new version. + $new['version'] = 3; + + /* + * Remaining changes do not need to be applied to the custom origin, + * as they should take on the value of the theme origin. + */ + if ( 'custom' === $origin ) { + return $new; + } + + /* + * Even though defaultFontSizes and defaultSpacingSizes are new + * settings, we need to migrate them as they each control + * PRESETS_METADATA prevent_override values which were previously + * hardcoded to false. This only needs to happen when the theme provides + * fontSizes or spacingSizes as they could match the default ones and + * affect the generated CSS. + */ + if ( isset( $old['settings']['typography']['fontSizes'] ) ) { + $new['settings']['typography']['defaultFontSizes'] = false; + } + + /* + * Similarly to defaultFontSizes, we need to migrate defaultSpacingSizes + * as it controls the PRESETS_METADATA prevent_override which was + * previously hardcoded to false. This only needs to happen when the + * theme provided spacing sizes via spacingSizes or spacingScale. + */ + if ( + isset( $old['settings']['spacing']['spacingSizes'] ) || + isset( $old['settings']['spacing']['spacingScale'] ) + ) { + $new['settings']['spacing']['defaultSpacingSizes'] = false; + } + + /* + * In v3 spacingSizes is merged with the generated spacingScale sizes + * instead of completely replacing them. The v3 behavior is what was + * documented for the v2 schema, but the code never actually did work + * that way. Instead of surprising users with a behavior change two + * years after the fact at the same time as a v3 update is introduced, + * we'll continue using the "bugged" behavior for v2 themes. And treat + * the "bug fix" as a breaking change for v3. + */ + if ( isset( $old['settings']['spacing']['spacingSizes'] ) ) { + unset( $new['settings']['spacing']['spacingScale'] ); + } + + return $new; + } + + /** * Processes the settings subtree. * * @since 5.9.0 @@ -137,11 +216,9 @@ * * @param array $settings Reference to the current settings array. * @param array $path Path to the property to be removed. - * - * @return void */ private static function unset_setting_by_path( &$settings, $path ) { - $tmp_settings = &$settings; // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable + $tmp_settings = &$settings; $last_key = array_pop( $path ); foreach ( $path as $key ) { $tmp_settings = &$tmp_settings[ $key ];