15 * use get_global_settings, get_global_styles, and get_global_stylesheet instead. |
15 * use get_global_settings, get_global_styles, and get_global_stylesheet instead. |
16 * |
16 * |
17 * @since 5.9.0 |
17 * @since 5.9.0 |
18 * @access private |
18 * @access private |
19 */ |
19 */ |
|
20 #[AllowDynamicProperties] |
20 class WP_Theme_JSON_Schema { |
21 class WP_Theme_JSON_Schema { |
21 |
22 |
22 /** |
23 /** |
23 * Maps old properties to their new location within the schema's settings. |
24 * Maps old properties to their new location within the schema's settings. |
24 * This will be applied at both the defaults and individual block levels. |
25 * This will be applied at both the defaults and individual block levels. |
32 |
33 |
33 /** |
34 /** |
34 * Function that migrates a given theme.json structure to the last version. |
35 * Function that migrates a given theme.json structure to the last version. |
35 * |
36 * |
36 * @since 5.9.0 |
37 * @since 5.9.0 |
|
38 * @since 6.6.0 Migrate up to v3 and add $origin parameter. |
37 * |
39 * |
38 * @param array $theme_json The structure to migrate. |
40 * @param array $theme_json The structure to migrate. |
39 * |
41 * @param string $origin Optional. What source of data this object represents. |
|
42 * One of 'blocks', 'default', 'theme', or 'custom'. Default 'theme'. |
40 * @return array The structure in the last version. |
43 * @return array The structure in the last version. |
41 */ |
44 */ |
42 public static function migrate( $theme_json ) { |
45 public static function migrate( $theme_json, $origin = 'theme' ) { |
43 if ( ! isset( $theme_json['version'] ) ) { |
46 if ( ! isset( $theme_json['version'] ) ) { |
44 $theme_json = array( |
47 $theme_json = array( |
45 'version' => WP_Theme_JSON::LATEST_SCHEMA, |
48 'version' => WP_Theme_JSON::LATEST_SCHEMA, |
46 ); |
49 ); |
47 } |
50 } |
48 |
51 |
49 if ( 1 === $theme_json['version'] ) { |
52 // Migrate each version in order starting with the current version. |
50 $theme_json = self::migrate_v1_to_v2( $theme_json ); |
53 switch ( $theme_json['version'] ) { |
|
54 case 1: |
|
55 $theme_json = self::migrate_v1_to_v2( $theme_json ); |
|
56 // Deliberate fall through. Once migrated to v2, also migrate to v3. |
|
57 case 2: |
|
58 $theme_json = self::migrate_v2_to_v3( $theme_json, $origin ); |
51 } |
59 } |
52 |
60 |
53 return $theme_json; |
61 return $theme_json; |
54 } |
62 } |
55 |
63 |
77 $new['settings'] = self::rename_paths( $old['settings'], self::V1_TO_V2_RENAMED_PATHS ); |
85 $new['settings'] = self::rename_paths( $old['settings'], self::V1_TO_V2_RENAMED_PATHS ); |
78 } |
86 } |
79 |
87 |
80 // Set the new version. |
88 // Set the new version. |
81 $new['version'] = 2; |
89 $new['version'] = 2; |
|
90 |
|
91 return $new; |
|
92 } |
|
93 |
|
94 /** |
|
95 * Migrates from v2 to v3. |
|
96 * |
|
97 * - Sets settings.typography.defaultFontSizes to false if settings.typography.fontSizes are defined. |
|
98 * - Sets settings.spacing.defaultSpacingSizes to false if settings.spacing.spacingSizes are defined. |
|
99 * - Prevents settings.spacing.spacingSizes from merging with settings.spacing.spacingScale by |
|
100 * unsetting spacingScale when spacingSizes are defined. |
|
101 * |
|
102 * @since 6.6.0 |
|
103 * |
|
104 * @param array $old Data to migrate. |
|
105 * @param string $origin What source of data this object represents. |
|
106 * One of 'blocks', 'default', 'theme', or 'custom'. |
|
107 * @return array Data with defaultFontSizes set to false. |
|
108 */ |
|
109 private static function migrate_v2_to_v3( $old, $origin ) { |
|
110 // Copy everything. |
|
111 $new = $old; |
|
112 |
|
113 // Set the new version. |
|
114 $new['version'] = 3; |
|
115 |
|
116 /* |
|
117 * Remaining changes do not need to be applied to the custom origin, |
|
118 * as they should take on the value of the theme origin. |
|
119 */ |
|
120 if ( 'custom' === $origin ) { |
|
121 return $new; |
|
122 } |
|
123 |
|
124 /* |
|
125 * Even though defaultFontSizes and defaultSpacingSizes are new |
|
126 * settings, we need to migrate them as they each control |
|
127 * PRESETS_METADATA prevent_override values which were previously |
|
128 * hardcoded to false. This only needs to happen when the theme provides |
|
129 * fontSizes or spacingSizes as they could match the default ones and |
|
130 * affect the generated CSS. |
|
131 */ |
|
132 if ( isset( $old['settings']['typography']['fontSizes'] ) ) { |
|
133 $new['settings']['typography']['defaultFontSizes'] = false; |
|
134 } |
|
135 |
|
136 /* |
|
137 * Similarly to defaultFontSizes, we need to migrate defaultSpacingSizes |
|
138 * as it controls the PRESETS_METADATA prevent_override which was |
|
139 * previously hardcoded to false. This only needs to happen when the |
|
140 * theme provided spacing sizes via spacingSizes or spacingScale. |
|
141 */ |
|
142 if ( |
|
143 isset( $old['settings']['spacing']['spacingSizes'] ) || |
|
144 isset( $old['settings']['spacing']['spacingScale'] ) |
|
145 ) { |
|
146 $new['settings']['spacing']['defaultSpacingSizes'] = false; |
|
147 } |
|
148 |
|
149 /* |
|
150 * In v3 spacingSizes is merged with the generated spacingScale sizes |
|
151 * instead of completely replacing them. The v3 behavior is what was |
|
152 * documented for the v2 schema, but the code never actually did work |
|
153 * that way. Instead of surprising users with a behavior change two |
|
154 * years after the fact at the same time as a v3 update is introduced, |
|
155 * we'll continue using the "bugged" behavior for v2 themes. And treat |
|
156 * the "bug fix" as a breaking change for v3. |
|
157 */ |
|
158 if ( isset( $old['settings']['spacing']['spacingSizes'] ) ) { |
|
159 unset( $new['settings']['spacing']['spacingScale'] ); |
|
160 } |
82 |
161 |
83 return $new; |
162 return $new; |
84 } |
163 } |
85 |
164 |
86 /** |
165 /** |
135 * |
214 * |
136 * @since 5.9.0 |
215 * @since 5.9.0 |
137 * |
216 * |
138 * @param array $settings Reference to the current settings array. |
217 * @param array $settings Reference to the current settings array. |
139 * @param array $path Path to the property to be removed. |
218 * @param array $path Path to the property to be removed. |
140 * |
|
141 * @return void |
|
142 */ |
219 */ |
143 private static function unset_setting_by_path( &$settings, $path ) { |
220 private static function unset_setting_by_path( &$settings, $path ) { |
144 $tmp_settings = &$settings; // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable |
221 $tmp_settings = &$settings; |
145 $last_key = array_pop( $path ); |
222 $last_key = array_pop( $path ); |
146 foreach ( $path as $key ) { |
223 foreach ( $path as $key ) { |
147 $tmp_settings = &$tmp_settings[ $key ]; |
224 $tmp_settings = &$tmp_settings[ $key ]; |
148 } |
225 } |
149 |
226 |