PluginProbe
Gutenberg / 16.2.0
Gutenberg v16.2.0
24.0.0 23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 All 403 releases
← All changes | lib/class-wp-theme-json-resolver-gutenberg.php +92 -344 23.7.0 → 16.2.0 View file →
@@ -1,7 +1,7 @@
1 1 <?php
2 2 /**
3 - * WP_Theme_JSON_Resolver_Gutenberg class
3 + * WP_Theme_JSON_Resolver class
4 4 *
5 5 * @package gutenberg
6 6 * @since 5.8.0
7 7 */
@@ -13,9 +13,8 @@
13 13 * This class is for internal core usage and is not supposed to be used by extenders (plugins and/or themes).
14 14 * This is a low-level API that may need to do breaking changes. Please,
15 15 * use gutenberg_get_global_settings, gutenberg_get_global_styles, and gutenberg_get_global_stylesheet instead.
16 16 *
17 - * @since 5.8.0
18 17 * @access private
19 18 */
20 19 #[AllowDynamicProperties]
21 20 class WP_Theme_JSON_Resolver_Gutenberg {
@@ -36,9 +35,9 @@
36 35 /**
37 36 * Container for data coming from core.
38 37 *
39 38 * @since 5.8.0
40 - * @var WP_Theme_JSON_Gutenberg
39 + * @var WP_Theme_JSON
41 40 */
42 41 protected static $core = null;
43 42
44 43 /**
@@ -44,9 +43,9 @@
44 43 /**
45 44 * Container for data coming from the blocks.
46 45 *
47 46 * @since 6.1.0
48 - * @var WP_Theme_JSON_Gutenberg
47 + * @var WP_Theme_JSON
49 48 */
50 49 protected static $blocks = null;
51 50
52 51 /**
@@ -52,9 +51,9 @@
52 51 /**
53 52 * Container for data coming from the theme.
54 53 *
55 54 * @since 5.8.0
56 - * @var WP_Theme_JSON_Gutenberg
55 + * @var WP_Theme_JSON
57 56 */
58 57 protected static $theme = null;
59 58
60 59 /**
@@ -60,9 +59,9 @@
60 59 /**
61 60 * Container for data coming from the user.
62 61 *
63 62 * @since 5.9.0
64 - * @var WP_Theme_JSON_Gutenberg
63 + * @var WP_Theme_JSON
65 64 */
66 65 protected static $user = null;
67 66
68 67 /**
@@ -143,9 +142,9 @@
143 142 */
144 143 protected static function translate( $theme_json, $domain = 'default' ) {
145 144 if ( null === static::$i18n_schema ) {
146 145 $i18n_schema = wp_json_file_decode( __DIR__ . '/theme-i18n.json' );
147 - static::$i18n_schema = $i18n_schema ?? array();
146 + static::$i18n_schema = null === $i18n_schema ? array() : $i18n_schema;
148 147 }
149 148
150 149 return translate_settings_using_i18n_schema( static::$i18n_schema, $theme_json, $domain );
151 150 }
@@ -154,9 +153,9 @@
154 153 * Returns core's origin config.
155 154 *
156 155 * @since 5.8.0
157 156 *
158 - * @return WP_Theme_JSON_Gutenberg Entity that holds core data.
157 + * @return WP_Theme_JSON Entity that holds core data.
159 158 */
160 159 public static function get_core_data() {
161 160 if ( null !== static::$core && static::has_same_registered_blocks( 'core' ) ) {
162 161 return static::$core;
@@ -169,12 +168,13 @@
169 168 * Filters the default data provided by WordPress for global styles & settings.
170 169 *
171 170 * @since 6.1.0
172 171 *
173 - * @param WP_Theme_JSON_Data_Gutenberg Class to access and update the underlying data.
172 + * @param WP_Theme_JSON_Data Class to access and update the underlying data.
174 173 */
175 174 $theme_json = apply_filters( 'wp_theme_json_data_default', new WP_Theme_JSON_Data_Gutenberg( $config, 'default' ) );
176 - static::$core = $theme_json->get_theme_json();
175 + $config = $theme_json->get_data();
176 + static::$core = new WP_Theme_JSON_Gutenberg( $config, 'default' );
177 177
178 178 return static::$core;
179 179 }
180 180
@@ -219,10 +219,8 @@
219 219 *
220 220 * @since 5.8.0
221 221 * @since 5.9.0 Theme supports have been inlined and the `$theme_support_data` argument removed.
222 222 * @since 6.0.0 Added an `$options` parameter to allow the theme data to be returned without theme supports.
223 - * @since 6.6.0 Added support for 'default-font-sizes' and 'default-spacing-sizes' theme supports.
224 - * Added registration and merging of block style variations from partial theme.json files and the block styles registry.
225 223 *
226 224 * @param array $deprecated Deprecated. Not used.
227 225 * @param array $options {
228 226 * Options arguments.
@@ -228,9 +226,9 @@
228 226 * Options arguments.
229 227 *
230 228 * @type bool $with_supports Whether to include theme supports in the data. Default true.
231 229 * }
232 - * @return WP_Theme_JSON_Gutenberg Entity that holds theme data.
230 + * @return WP_Theme_JSON Entity that holds theme data.
233 231 */
234 232 public static function get_theme_data( $deprecated = array(), $options = array() ) {
235 233 if ( ! empty( $deprecated ) ) {
236 234 _deprecated_argument( __METHOD__, '5.9.0' );
@@ -238,54 +236,32 @@
238 236
239 237 $options = wp_parse_args( $options, array( 'with_supports' => true ) );
240 238
241 239 if ( null === static::$theme || ! static::has_same_registered_blocks( 'theme' ) ) {
240 + $theme_json_file = static::get_file_path_from_theme( 'theme.json' );
242 241 $wp_theme = wp_get_theme();
243 - $theme_json_file = $wp_theme->get_file_path( 'theme.json' );
244 - if ( is_readable( $theme_json_file ) ) {
242 + if ( '' !== $theme_json_file ) {
245 243 $theme_json_data = static::read_json_file( $theme_json_file );
246 244 $theme_json_data = static::translate( $theme_json_data, $wp_theme->get( 'TextDomain' ) );
247 245 } else {
248 - $theme_json_data = array( 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA );
246 + $theme_json_data = array();
249 247 }
250 248
251 - /*
252 - * Register variations defined by theme partials (theme.json files in the styles directory).
253 - * This is required so the variations pass sanitization of theme.json data.
254 - */
255 - $variations = static::get_style_variations( 'block' );
256 - gutenberg_register_block_style_variations_from_theme_json_partials( $variations );
257 -
258 - /*
259 - * Source variations from the block styles registry and block style variation files. Then, merge them into the existing theme.json data.
260 - *
261 - * In case the same style properties are defined in several sources, this is how we should resolve the values,
262 - * from higher to lower priority:
263 - *
264 - * - styles.blocks.blockType.variations from theme.json
265 - * - styles.variations from theme.json
266 - * - variations from block style variation files
267 - * - variations from block styles registry
268 - *
269 - * See test_add_registered_block_styles_to_theme_data and test_unwraps_block_style_variations.
270 - */
271 - $theme_json_data = static::inject_variations_from_block_style_variation_files( $theme_json_data, $variations );
272 - $theme_json_data = static::inject_variations_from_block_styles_registry( $theme_json_data );
273 -
274 249 /**
275 250 * Filters the data provided by the theme for global styles and settings.
276 251 *
277 252 * @since 6.1.0
278 253 *
279 - * @param WP_Theme_JSON_Data_Gutenberg Class to access and update the underlying data.
254 + * @param WP_Theme_JSON_Data Class to access and update the underlying data.
280 255 */
281 - $theme_json = apply_filters( 'wp_theme_json_data_theme', new WP_Theme_JSON_Data_Gutenberg( $theme_json_data, 'theme' ) );
282 - static::$theme = $theme_json->get_theme_json();
256 + $theme_json = apply_filters( 'wp_theme_json_data_theme', new WP_Theme_JSON_Data_Gutenberg( $theme_json_data, 'theme' ) );
257 + $theme_json_data = $theme_json->get_data();
258 + static::$theme = new WP_Theme_JSON_Gutenberg( $theme_json_data );
283 259
284 260 if ( $wp_theme->parent() ) {
285 261 // Get parent theme.json.
286 - $parent_theme_json_file = $wp_theme->parent()->get_file_path( 'theme.json' );
287 - if ( $theme_json_file !== $parent_theme_json_file && is_readable( $parent_theme_json_file ) ) {
262 + $parent_theme_json_file = static::get_file_path_from_theme( 'theme.json', true );
263 + if ( '' !== $parent_theme_json_file ) {
288 264 $parent_theme_json_data = static::read_json_file( $parent_theme_json_file );
289 265 $parent_theme_json_data = static::translate( $parent_theme_json_data, $wp_theme->parent()->get( 'TextDomain' ) );
290 266 $parent_theme = new WP_Theme_JSON_Gutenberg( $parent_theme_json_data );
291 267
@@ -298,11 +274,9 @@
298 274 }
299 275 }
300 276
301 277 // BEGIN OF EXPERIMENTAL CODE. Not to backport to core.
302 - if ( ! class_exists( 'WP_Font_Face' ) && class_exists( 'WP_Fonts_Resolver' ) ) {
303 - static::$theme = WP_Fonts_Resolver::add_missing_fonts_to_theme_json( static::$theme );
304 - }
278 + static::$theme = WP_Fonts_Resolver::add_missing_fonts_to_theme_json( static::$theme );
305 279 // END OF EXPERIMENTAL CODE.
306 280
307 281 }
308 282
@@ -317,35 +291,35 @@
317 291 * and merge the static::$theme upon that.
318 292 */
319 293 $theme_support_data = WP_Theme_JSON_Gutenberg::get_from_editor_settings( get_classic_theme_supports_block_editor_settings() );
320 294 if ( ! wp_theme_has_theme_json() ) {
321 - /*
322 - * Unlike block themes, classic themes without a theme.json disable
323 - * default presets when custom preset theme support is added. This
324 - * behavior can be overridden by using the corresponding default
325 - * preset theme support.
326 - */
327 - $theme_support_data['settings']['color']['defaultPalette'] =
328 - ! isset( $theme_support_data['settings']['color']['palette'] ) ||
329 - current_theme_supports( 'default-color-palette' );
330 - $theme_support_data['settings']['color']['defaultGradients'] =
331 - ! isset( $theme_support_data['settings']['color']['gradients'] ) ||
332 - current_theme_supports( 'default-gradient-presets' );
333 - $theme_support_data['settings']['typography']['defaultFontSizes'] =
334 - ! isset( $theme_support_data['settings']['typography']['fontSizes'] ) ||
335 - current_theme_supports( 'default-font-sizes' );
336 - $theme_support_data['settings']['spacing']['defaultSpacingSizes'] =
337 - ! isset( $theme_support_data['settings']['spacing']['spacingSizes'] ) ||
338 - current_theme_supports( 'default-spacing-sizes' );
295 + if ( ! isset( $theme_support_data['settings']['color'] ) ) {
296 + $theme_support_data['settings']['color'] = array();
297 + }
339 298
340 - /*
341 - * Shadow presets are explicitly disabled for classic themes until a
342 - * decision is made for whether the default presets should match the
343 - * other presets or if they should be disabled by default in classic
344 - * themes. See https://github.com/WordPress/gutenberg/issues/59989.
345 - */
346 - $theme_support_data['settings']['shadow']['defaultPresets'] = false;
299 + $default_palette = false;
300 + if ( current_theme_supports( 'default-color-palette' ) ) {
301 + $default_palette = true;
302 + }
303 + if ( ! isset( $theme_support_data['settings']['color']['palette'] ) ) {
304 + // If the theme does not have any palette, we still want to show the core one.
305 + $default_palette = true;
306 + }
307 + $theme_support_data['settings']['color']['defaultPalette'] = $default_palette;
347 308
309 + $default_gradients = false;
310 + if ( current_theme_supports( 'default-gradient-presets' ) ) {
311 + $default_gradients = true;
312 + }
313 + if ( ! isset( $theme_support_data['settings']['color']['gradients'] ) ) {
314 + // If the theme does not have any gradients, we still want to show the core ones.
315 + $default_gradients = true;
316 + }
317 + $theme_support_data['settings']['color']['defaultGradients'] = $default_gradients;
318 +
319 + // Classic themes without a theme.json don't support global duotone.
320 + $theme_support_data['settings']['color']['defaultDuotone'] = false;
321 +
348 322 // Allow themes to enable all border settings via theme_support.
349 323 if ( current_theme_supports( 'border' ) ) {
350 324 $theme_support_data['settings']['border']['color'] = true;
351 325 $theme_support_data['settings']['border']['radius'] = true;
@@ -358,18 +332,23 @@
358 332 $theme_support_data['settings']['color']['link'] = true;
359 333 }
360 334 if ( current_theme_supports( 'experimental-link-color' ) ) {
361 335 _doing_it_wrong(
362 - "add_theme_support( 'experimental-link-color' )",
336 + current_theme_supports( 'experimental-link-color' ),
363 337 __( '`experimental-link-color` is no longer supported. Use `link-color` instead.', 'gutenberg' ),
364 338 '6.3.0'
365 339 );
366 340 }
367 341
342 + // BEGIN EXPERIMENTAL.
368 343 // Allow themes to enable appearance tools via theme_support.
344 + // This feature was backported for WordPress 6.2 as of https://core.trac.wordpress.org/ticket/56487
345 + // and then reverted as of https://core.trac.wordpress.org/ticket/57649
346 + // Not to backport until the issues are resolved.
369 347 if ( current_theme_supports( 'appearance-tools' ) ) {
370 348 $theme_support_data['settings']['appearanceTools'] = true;
371 349 }
350 + // END EXPERIMENTAL.
372 351 }
373 352 $with_theme_supports = new WP_Theme_JSON_Gutenberg( $theme_support_data );
374 353 $with_theme_supports->merge( static::$theme );
375 354 return $with_theme_supports;
@@ -379,9 +358,9 @@
379 358 * Gets the styles for blocks from the block.json file.
380 359 *
381 360 * @since 6.1.0
382 361 *
383 - * @return WP_Theme_JSON_Gutenberg
362 + * @return WP_Theme_JSON
384 363 */
385 364 public static function get_block_data() {
386 365 $registry = WP_Block_Type_Registry::get_instance();
387 366 $blocks = $registry->get_all_registered();
@@ -389,9 +368,9 @@
389 368 if ( null !== static::$blocks && static::has_same_registered_blocks( 'blocks' ) ) {
390 369 return static::$blocks;
391 370 }
392 371
393 - $config = array( 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA );
372 + $config = array( 'version' => 2 );
394 373 foreach ( $blocks as $block_name => $block_type ) {
395 374 if ( isset( $block_type->supports['__experimentalStyle'] ) ) {
396 375 $config['styles']['blocks'][ $block_name ] = static::remove_json_comments( $block_type->supports['__experimentalStyle'] );
397 376 }
@@ -397,9 +376,9 @@
397 376 }
398 377
399 378 if (
400 379 isset( $block_type->supports['spacing']['blockGap']['__experimentalDefault'] ) &&
401 - ! isset( $config['styles']['blocks'][ $block_name ]['spacing']['blockGap'] )
380 + null === _wp_array_get( $config, array( 'styles', 'blocks', $block_name, 'spacing', 'blockGap' ), null )
402 381 ) {
403 382 // Ensure an empty placeholder value exists for the block, if it provides a default blockGap value.
404 383 // The real blockGap value to be used will be determined when the styles are rendered for output.
405 384 $config['styles']['blocks'][ $block_name ]['spacing']['blockGap'] = null;
@@ -410,13 +389,14 @@
410 389 * Filters the data provided by the blocks for global styles & settings.
411 390 *
412 391 * @since 6.1.0
413 392 *
414 - * @param WP_Theme_JSON_Data_Gutenberg Class to access and update the underlying data.
393 + * @param WP_Theme_JSON_Data Class to access and update the underlying data.
415 394 */
416 - $theme_json = apply_filters( 'wp_theme_json_data_blocks', new WP_Theme_JSON_Data_Gutenberg( $config, 'blocks' ) );
417 - static::$blocks = $theme_json->get_theme_json();
395 + $theme_json = apply_filters( 'wp_theme_json_data_blocks', new WP_Theme_JSON_Data_Gutenberg( $config, 'blocks' ) );
396 + $config = $theme_json->get_data();
418 397
398 + static::$blocks = new WP_Theme_JSON_Gutenberg( $config, 'blocks' );
419 399 return static::$blocks;
420 400 }
421 401
422 402 /**
@@ -421,20 +401,20 @@
421 401
422 402 /**
423 403 * When given an array, this will remove any keys with the name `//`.
424 404 *
425 - * @param array $json_array The array to filter.
405 + * @param array $array The array to filter.
426 406 * @return array The filtered array.
427 407 */
428 - private static function remove_json_comments( $json_array ) {
429 - unset( $json_array['//'] );
430 - foreach ( $json_array as $k => $v ) {
408 + private static function remove_json_comments( $array ) {
409 + unset( $array['//'] );
410 + foreach ( $array as $k => $v ) {
431 411 if ( is_array( $v ) ) {
432 - $json_array[ $k ] = static::remove_json_comments( $v );
412 + $array[ $k ] = static::remove_json_comments( $v );
433 413 }
434 414 }
435 415
436 - return $json_array;
416 + return $array;
437 417 }
438 418
439 419 /**
440 420 * Returns the custom post type that contains the user's origin config
@@ -458,8 +438,19 @@
458 438 if ( ! $theme instanceof WP_Theme ) {
459 439 $theme = wp_get_theme();
460 440 }
461 441
442 + /*
443 + * Bail early if the theme does not support a theme.json.
444 + *
445 + * Since wp_theme_has_theme_json only supports the active
446 + * theme, the extra condition for whether $theme is the active theme is
447 + * present here.
448 + */
449 + if ( $theme->get_stylesheet() === get_stylesheet() && ! wp_theme_has_theme_json() ) {
450 + return array();
451 + }
452 +
462 453 $user_cpt = array();
463 454 $post_type_filter = 'wp_global_styles';
464 455 $stylesheet = $theme->get_stylesheet();
465 456 $args = array(
@@ -482,9 +473,9 @@
482 473 );
483 474
484 475 $global_style_query = new WP_Query();
485 476 $recent_posts = $global_style_query->query( $args );
486 - if ( count( $recent_posts ) === 1 && $recent_posts[0] instanceof WP_Post ) {
477 + if ( count( $recent_posts ) === 1 ) {
487 478 $user_cpt = get_object_vars( $recent_posts[0] );
488 479 } elseif ( $create_post ) {
489 480 $cpt_post_id = wp_insert_post(
490 481 array(
@@ -499,12 +490,9 @@
499 490 ),
500 491 true
501 492 );
502 493 if ( ! is_wp_error( $cpt_post_id ) ) {
503 - $post = get_post( $cpt_post_id );
504 - if ( $post instanceof WP_Post ) {
505 - $user_cpt = get_object_vars( $post );
506 - }
494 + $user_cpt = get_object_vars( get_post( $cpt_post_id ) );
507 495 }
508 496 }
509 497
510 498 return $user_cpt;
@@ -514,9 +502,9 @@
514 502 * Returns the user's origin config.
515 503 *
516 504 * @since 5.9.0
517 505 *
518 - * @return WP_Theme_JSON_Gutenberg Entity that holds styles for user data.
506 + * @return WP_Theme_JSON Entity that holds styles for user data.
519 507 */
520 508 public static function get_user_data() {
521 509 if ( null !== static::$user && static::has_same_registered_blocks( 'user' ) ) {
522 510 return static::$user;
@@ -535,13 +523,13 @@
535 523 * Filters the data provided by the user for global styles & settings.
536 524 *
537 525 * @since 6.1.0
538 526 *
539 - * @param WP_Theme_JSON_Data_Gutenberg Class to access and update the underlying data.
527 + * @param WP_Theme_JSON_Data Class to access and update the underlying data.
540 528 */
541 529 $theme_json = apply_filters( 'wp_theme_json_data_user', new WP_Theme_JSON_Data_Gutenberg( $config, 'custom' ) );
542 -
543 - return $theme_json->get_theme_json();
530 + $config = $theme_json->get_data();
531 + return new WP_Theme_JSON_Gutenberg( $config, 'custom' );
544 532 }
545 533
546 534 // Very important to verify that the flag isGlobalStylesUserThemeJSON is true.
547 535 // If it's not true then the content was not escaped and is not safe.
@@ -556,9 +544,10 @@
556 544 }
557 545
558 546 /** This filter is documented in wp-includes/class-wp-theme-json-resolver.php */
559 547 $theme_json = apply_filters( 'wp_theme_json_data_user', new WP_Theme_JSON_Data_Gutenberg( $config, 'custom' ) );
560 - static::$user = $theme_json->get_theme_json();
548 + $config = $theme_json->get_data();
549 + static::$user = new WP_Theme_JSON_Gutenberg( $config, 'custom' );
561 550
562 551 return static::$user;
563 552 }
564 553
@@ -594,9 +583,9 @@
594 583 *
595 584 * @param string $origin Optional. To what level should we merge data:'default', 'blocks', 'theme' or 'custom'.
596 585 * 'custom' is used as default value as well as fallback value if the origin is unknown.
597 586 *
598 - * @return WP_Theme_JSON_Gutenberg
587 + * @return WP_Theme_JSON
599 588 */
600 589 public static function get_merged_data( $origin = 'custom' ) {
601 590 if ( is_array( $origin ) ) {
602 591 _deprecated_argument( __FUNCTION__, '5.9.0' );
@@ -604,8 +593,9 @@
604 593
605 594 $result = new WP_Theme_JSON_Gutenberg();
606 595 $result->merge( static::get_core_data() );
607 596 if ( 'default' === $origin ) {
597 + $result->set_spacing_sizes();
608 598 return $result;
609 599 }
610 600
611 601 $result->merge( static::get_block_data() );
@@ -614,12 +604,14 @@
614 604 }
615 605
616 606 $result->merge( static::get_theme_data() );
617 607 if ( 'theme' === $origin ) {
608 + $result->set_spacing_sizes();
618 609 return $result;
619 610 }
620 611
621 612 $result->merge( static::get_user_data() );
613 + $result->set_spacing_sizes();
622 614 return $result;
623 615 }
624 616
625 617 /**
@@ -671,10 +663,8 @@
671 663 * @param bool $template Optional. Use template theme directory. Default false.
672 664 * @return string The whole file path or empty if the file doesn't exist.
673 665 */
674 666 protected static function get_file_path_from_theme( $file_name, $template = false ) {
675 - // TODO: Remove this method from core on 6.3 release.
676 - _deprecated_function( __METHOD__, '6.3.0' );
677 667 $path = $template ? get_template_directory() : get_stylesheet_directory();
678 668 $candidate = $path . '/' . $file_name;
679 669
680 670 return is_readable( $candidate ) ? $candidate : '';
@@ -718,57 +708,17 @@
718 708 return $nested_json_files;
719 709 }
720 710
721 711 /**
722 - * Determines if a supplied style variation matches the provided scope.
723 - *
724 - * For backwards compatibility, if a variation does not define any scope
725 - * related property, e.g. `blockTypes`, it is assumed to be a theme style
726 - * variation.
727 - *
728 - * @since 6.6.0
729 - *
730 - * @param array $variation Theme.json shaped style variation object.
731 - * @param string $scope Scope to check e.g. theme, block etc.
732 - *
733 - * @return boolean
734 - */
735 - private static function style_variation_has_scope( $variation, $scope ) {
736 - if ( 'block' === $scope ) {
737 - return isset( $variation['blockTypes'] );
738 - }
739 -
740 - if ( 'theme' === $scope ) {
741 - return ! isset( $variation['blockTypes'] );
742 - }
743 -
744 - return false;
745 - }
746 -
747 - /**
748 712 * Returns the style variations defined by the theme (parent and child).
749 713 *
750 714 * @since 6.2.0 Returns parent theme variations if theme is a child.
751 - * @since 6.6.0 Added configurable scope parameter to allow filtering
752 - * theme.json partial files by the scope to which they
753 - * can be applied e.g. theme vs block etc.
754 715 *
755 - * @param string $scope The scope or type of style variation to retrieve e.g. theme, block etc.
756 716 * @return array
757 717 */
758 - public static function get_style_variations( $scope = 'theme' ) {
759 - return static::get_style_variations_from_directory( get_stylesheet_directory(), $scope );
760 - }
761 -
762 - /**
763 - * Returns the style variation files defined by the theme (parent and child).
764 - *
765 - * @since 6.7.0
766 - *
767 - * @return array An array of style variation files.
768 - */
769 - protected static function get_style_variation_files_from_current_theme() {
718 + public static function get_style_variations() {
770 719 $variation_files = array();
720 + $variations = array();
771 721 $base_directory = get_stylesheet_directory() . '/styles';
772 722 $template_directory = get_template_directory() . '/styles';
773 723 if ( is_dir( $base_directory ) ) {
774 724 $variation_files = static::recursively_iterate_json( $base_directory );
@@ -784,35 +734,12 @@
784 734 }
785 735 }
786 736 $variation_files = array_merge( $variation_files, $variation_files_parent );
787 737 }
788 -
789 - return $variation_files;
790 - }
791 -
792 - /**
793 - * Returns the style variations in the given directory.
794 - *
795 - * @since 6.7.0
796 - *
797 - * @param string $directory The directory to get the style variations from.
798 - * @param string $scope The scope or type of style variation to retrieve e.g. theme, block etc.
799 - * @return array
800 - */
801 - public static function get_style_variations_from_directory( $directory, $scope = 'theme' ) {
802 - $variation_files = array();
803 - $variations = array();
804 - if ( is_dir( $directory ) ) {
805 - if ( get_stylesheet_directory() === $directory ) {
806 - $variation_files = static::get_style_variation_files_from_current_theme();
807 - } else {
808 - $variation_files = static::recursively_iterate_json( $directory );
809 - }
810 - }
811 738 ksort( $variation_files );
812 739 foreach ( $variation_files as $path => $file ) {
813 - $decoded_file = self::read_json_file( $path );
814 - if ( is_array( $decoded_file ) && static::style_variation_has_scope( $decoded_file, $scope ) ) {
740 + $decoded_file = wp_json_file_decode( $path, array( 'associative' => true ) );
741 + if ( is_array( $decoded_file ) ) {
815 742 $translated = static::translate( $decoded_file, wp_get_theme()->get( 'TextDomain' ) );
816 743 $variation = ( new WP_Theme_JSON_Gutenberg( $translated ) )->get_raw_data();
817 744 if ( empty( $variation['title'] ) ) {
818 745 $variation['title'] = basename( $path, '.json' );
@@ -820,185 +747,6 @@
820 747 $variations[] = $variation;
821 748 }
822 749 }
823 750 return $variations;
824 - }
825 -
826 -
827 - /**
828 - * Resolves relative paths in theme.json styles to theme absolute paths
829 - * and returns them in an array that can be embedded
830 - * as the value of `_link` object in REST API responses.
831 - *
832 - * @since 6.6.0
833 - * @since 6.7.0 Added support for resolving block styles.
834 - *
835 - * @param WP_Theme_JSON_Gutenberg $theme_json A theme json instance.
836 - * @return array An array of resolved paths.
837 - */
838 - public static function get_resolved_theme_uris( $theme_json ) {
839 - $resolved_theme_uris = array();
840 -
841 - if ( ! $theme_json instanceof WP_Theme_JSON_Gutenberg ) {
842 - return $resolved_theme_uris;
843 - }
844 -
845 - $theme_json_data = $theme_json->get_raw_data();
846 -
847 - // Using the same file convention when registering web fonts. See: WP_Font_Face_Resolver:: to_theme_file_uri.
848 - $placeholder = 'file:./';
849 -
850 - // Top level styles.
851 - $background_image_url = $theme_json_data['styles']['background']['backgroundImage']['url'] ?? null;
852 - if (
853 - isset( $background_image_url ) &&
854 - is_string( $background_image_url ) &&
855 - // Skip if the src doesn't start with the placeholder, as there's nothing to replace.
856 - str_starts_with( $background_image_url, $placeholder ) ) {
857 - $file_type = wp_check_filetype( $background_image_url );
858 - $src_url = str_replace( $placeholder, '', $background_image_url );
859 - $resolved_theme_uri = array(
860 - 'name' => $background_image_url,
861 - 'href' => sanitize_url( get_theme_file_uri( $src_url ) ),
862 - 'target' => 'styles.background.backgroundImage.url',
863 - );
864 - if ( isset( $file_type['type'] ) ) {
865 - $resolved_theme_uri['type'] = $file_type['type'];
866 - }
867 - $resolved_theme_uris[] = $resolved_theme_uri;
868 - }
869 -
870 - // Block styles.
871 - if ( ! empty( $theme_json_data['styles']['blocks'] ) ) {
872 - foreach ( $theme_json_data['styles']['blocks'] as $block_name => $block_styles ) {
873 - if ( ! isset( $block_styles['background']['backgroundImage']['url'] ) ) {
874 - continue;
875 - }
876 - $background_image_url = $block_styles['background']['backgroundImage']['url'] ?? null;
877 - if (
878 - isset( $background_image_url ) &&
879 - is_string( $background_image_url ) &&
880 - // Skip if the src doesn't start with the placeholder, as there's nothing to replace.
881 - str_starts_with( $background_image_url, $placeholder ) ) {
882 - $file_type = wp_check_filetype( $background_image_url );
883 - $src_url = str_replace( $placeholder, '', $background_image_url );
884 - $resolved_theme_uri = array(
885 - 'name' => $background_image_url,
886 - 'href' => sanitize_url( get_theme_file_uri( $src_url ) ),
887 - 'target' => "styles.blocks.{$block_name}.background.backgroundImage.url",
888 - );
889 - if ( isset( $file_type['type'] ) ) {
890 - $resolved_theme_uri['type'] = $file_type['type'];
891 - }
892 - $resolved_theme_uris[] = $resolved_theme_uri;
893 - }
894 - }
895 - }
896 -
897 - return $resolved_theme_uris;
898 - }
899 -
900 - /**
901 - * Resolves relative paths in theme.json styles to theme absolute paths
902 - * and merges them with incoming theme JSON.
903 - *
904 - * @since 6.6.0
905 - *
906 - * @param WP_Theme_JSON_Gutenberg $theme_json A theme json instance.
907 - * @return WP_Theme_JSON_Gutenberg Theme merged with resolved paths, if any found.
908 - */
909 - public static function resolve_theme_file_uris( $theme_json ) {
910 - $resolved_urls = static::get_resolved_theme_uris( $theme_json );
911 - if ( empty( $resolved_urls ) ) {
912 - return $theme_json;
913 - }
914 -
915 - $resolved_theme_json_data = $theme_json->get_raw_data();
916 -
917 - foreach ( $resolved_urls as $resolved_url ) {
918 - $path = explode( '.', $resolved_url['target'] );
919 - _wp_array_set( $resolved_theme_json_data, $path, $resolved_url['href'] );
920 - }
921 -
922 - return new WP_Theme_JSON_Gutenberg( $resolved_theme_json_data );
923 - }
924 -
925 - /**
926 - * Adds variations sourced from block style variations files to the supplied theme.json data.
927 - *
928 - * @since 6.6.0
929 - *
930 - * @param array $data Array following the theme.json specification.
931 - * @param array $variations Shared block style variations.
932 - * @return array Theme json data including shared block style variation definitions.
933 - */
934 - private static function inject_variations_from_block_style_variation_files( $data, $variations ) {
935 - if ( empty( $variations ) ) {
936 - return $data;
937 - }
938 -
939 - foreach ( $variations as $variation ) {
940 - if ( empty( $variation['styles'] ) || empty( $variation['blockTypes'] ) ) {
941 - continue;
942 - }
943 -
944 - $variation_name = $variation['slug'] ?? _wp_to_kebab_case( $variation['title'] );
945 -
946 - foreach ( $variation['blockTypes'] as $block_type ) {
947 - // First, override partial styles with any top-level styles.
948 - $top_level_data = $data['styles']['variations'][ $variation_name ] ?? array();
949 - if ( ! empty( $top_level_data ) ) {
950 - $variation['styles'] = array_replace_recursive( $variation['styles'], $top_level_data );
951 - }
952 -
953 - // Then, override styles so far with any block-level styles.
954 - $block_level_data = $data['styles']['blocks'][ $block_type ]['variations'][ $variation_name ] ?? array();
955 - if ( ! empty( $block_level_data ) ) {
956 - $variation['styles'] = array_replace_recursive( $variation['styles'], $block_level_data );
957 - }
958 -
959 - $path = array( 'styles', 'blocks', $block_type, 'variations', $variation_name );
960 - _wp_array_set( $data, $path, $variation['styles'] );
961 - }
962 - }
963 -
964 - return $data;
965 - }
966 -
967 - /**
968 - * Adds variations sourced from the block styles registry to the supplied theme.json data.
969 - *
970 - * @since 6.6.0
971 - *
972 - * @param array $data Array following the theme.json specification.
973 - * @return array Theme json data including variations from the block styles registry.
974 - */
975 - private static function inject_variations_from_block_styles_registry( $data ) {
976 - $registry = WP_Block_Styles_Registry::get_instance();
977 - $styles = $registry->get_all_registered();
978 -
979 - foreach ( $styles as $block_type => $variations ) {
980 - foreach ( $variations as $variation_name => $variation ) {
981 - if ( empty( $variation['style_data'] ) ) {
982 - continue;
983 - }
984 -
985 - // First, override registry styles with any top-level styles.
986 - $top_level_data = $data['styles']['variations'][ $variation_name ] ?? array();
987 - if ( ! empty( $top_level_data ) ) {
988 - $variation['style_data'] = array_replace_recursive( $variation['style_data'], $top_level_data );
989 - }
990 -
991 - // Then, override styles so far with any block-level styles.
992 - $block_level_data = $data['styles']['blocks'][ $block_type ]['variations'][ $variation_name ] ?? array();
993 - if ( ! empty( $block_level_data ) ) {
994 - $variation['style_data'] = array_replace_recursive( $variation['style_data'], $block_level_data );
995 - }
996 -
997 - $path = array( 'styles', 'blocks', $block_type, 'variations', $variation_name );
998 - _wp_array_set( $data, $path, $variation['style_data'] );
999 - }
1000 - }
1001 -
1002 - return $data;
1003 751 }
1004 752 }