--- 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 ];