run:R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
23.8 KB
2026-03-11 16:18:51
R W Run
7.8 KB
2026-03-11 16:18:52
R W Run
36.1 KB
2026-03-11 16:18:51
R W Run
11.9 KB
2026-03-11 16:18:52
R W Run
18.94 KB
2026-03-11 16:18:52
R W Run
7.35 KB
2026-03-11 16:18:52
R W Run
28.6 KB
2026-03-11 16:18:51
R W Run
316 By
2026-03-11 16:18:51
R W Run
12.9 KB
2026-03-11 16:18:51
R W Run
61.02 KB
2026-03-11 16:18:52
R W Run
15 KB
2026-03-11 16:18:51
R W Run
112.05 KB
2026-03-11 16:18:51
R W Run
12.47 KB
2026-03-11 16:18:51
R W Run
15.07 KB
2026-03-11 16:18:52
R W Run
9.84 KB
2026-03-11 16:18:52
R W Run
13.17 KB
2026-03-11 16:18:52
R W Run
33.83 KB
2026-03-11 16:18:51
R W Run
42.63 KB
2026-03-11 16:18:51
R W Run
55.71 KB
2026-03-11 16:18:52
R W Run
12.53 KB
2026-03-11 16:18:51
R W Run
2.55 KB
2026-03-11 16:18:52
R W Run
28.92 KB
2026-03-11 16:18:52
R W Run
539 By
2026-03-11 16:18:51
R W Run
367 By
2026-03-11 16:18:52
R W Run
42.65 KB
2026-03-11 16:18:51
R W Run
401 By
2026-03-11 16:18:51
R W Run
6.61 KB
2026-03-11 16:18:51
R W Run
664 By
2026-03-11 16:18:52
R W Run
20.63 KB
2026-03-11 16:18:51
R W Run
2.18 KB
2026-03-11 16:18:52
R W Run
453 By
2026-03-11 16:18:52
R W Run
457 By
2026-03-11 16:18:51
R W Run
36.83 KB
2026-03-11 16:18:52
R W Run
2.41 KB
2026-03-11 16:18:52
R W Run
8.28 KB
2026-03-11 16:18:51
R W Run
13.89 KB
2026-03-11 16:18:51
R W Run
11.76 KB
2026-03-11 16:18:51
R W Run
2.65 KB
2026-03-11 16:18:51
R W Run
7.43 KB
2026-03-11 16:18:51
R W Run
17.46 KB
2026-03-11 16:18:51
R W Run
5.14 KB
2026-03-11 16:18:52
R W Run
16.7 KB
2026-03-11 16:18:51
R W Run
8.28 KB
2026-03-11 16:18:52
R W Run
2.92 KB
2026-03-11 16:18:52
R W Run
1.32 KB
2026-03-11 16:18:51
R W Run
4.6 KB
2026-03-11 16:18:52
R W Run
11.62 KB
2026-03-11 16:18:52
R W Run
2.5 KB
2026-03-11 16:18:51
R W Run
1.97 KB
2026-03-11 16:18:51
R W Run
11.25 KB
2026-03-11 16:18:52
R W Run
5.32 KB
2026-03-11 16:18:51
R W Run
10.99 KB
2026-03-11 16:18:52
R W Run
68.32 KB
2026-03-11 16:18:51
R W Run
6.34 KB
2026-03-11 16:18:51
R W Run
5.49 KB
2026-03-11 16:18:51
R W Run
1.99 KB
2026-03-11 16:18:52
R W Run
7.02 KB
2026-03-11 16:18:51
R W Run
4.91 KB
2026-03-11 16:18:52
R W Run
16.86 KB
2026-03-11 16:18:51
R W Run
24.23 KB
2026-03-11 16:18:51
R W Run
3.97 KB
2026-03-11 16:18:51
R W Run
47.66 KB
2026-03-11 16:18:51
R W Run
9.22 KB
2026-03-11 16:18:51
R W Run
25.51 KB
2026-03-11 16:18:51
R W Run
198.38 KB
2026-03-11 16:18:52
R W Run
56.65 KB
2026-03-11 16:18:51
R W Run
10.46 KB
2026-03-11 16:18:51
R W Run
10.95 KB
2026-03-11 16:18:52
R W Run
29.26 KB
2026-03-11 16:18:51
R W Run
70.91 KB
2026-03-11 16:18:52
R W Run
35.3 KB
2026-03-11 16:18:52
R W Run
16.61 KB
2026-03-11 16:18:52
R W Run
2.57 KB
2026-03-11 16:18:52
R W Run
39.83 KB
2026-03-11 16:18:51
R W Run
70.64 KB
2026-03-11 16:18:51
R W Run
15.56 KB
2026-03-11 16:18:52
R W Run
7.33 KB
2026-03-11 16:18:52
R W Run
253 By
2026-03-11 16:18:51
R W Run
7.96 KB
2026-03-11 16:18:52
R W Run
3.23 KB
2026-03-11 16:18:52
R W Run
969 By
2026-03-11 16:18:52
R W Run
16.28 KB
2026-03-11 16:18:51
R W Run
7.22 KB
2026-03-11 16:18:51
R W Run
12.95 KB
2026-03-11 16:18:51
R W Run
6.53 KB
2026-03-11 16:18:51
R W Run
3.42 KB
2026-03-11 16:18:52
R W Run
5.84 KB
2026-03-11 16:18:51
R W Run
1.97 KB
2026-03-11 16:18:51
R W Run
4.3 KB
2026-03-11 16:18:52
R W Run
2.91 KB
2026-03-11 16:18:51
R W Run
16.46 KB
2026-03-11 16:18:52
R W Run
40.6 KB
2026-03-11 16:18:51
R W Run
20.22 KB
2026-03-11 16:18:51
R W Run
36.11 KB
2026-03-11 16:18:52
R W Run
17.01 KB
2026-03-11 16:18:51
R W Run
7.27 KB
2026-03-11 16:18:52
R W Run
6.62 KB
2026-03-11 16:18:52
R W Run
16.49 KB
2026-03-11 16:18:52
R W Run
1.79 KB
2026-03-11 16:18:52
R W Run
29.82 KB
2026-03-11 16:18:51
R W Run
6.67 KB
2026-03-11 16:18:52
R W Run
8.98 KB
2026-03-11 16:18:52
R W Run
19.42 KB
2026-03-11 16:18:51
R W Run
12.01 KB
2026-03-11 16:18:51
R W Run
17.11 KB
2026-03-11 16:18:51
R W Run
6.74 KB
2026-03-11 16:18:52
R W Run
30.93 KB
2026-03-11 16:18:51
R W Run
4.99 KB
2026-03-11 16:18:51
R W Run
4.25 KB
2026-03-11 16:18:51
R W Run
24.72 KB
2026-03-11 16:18:51
R W Run
29.96 KB
2026-03-11 16:18:52
R W Run
6.41 KB
2026-03-11 16:18:51
R W Run
160 KB
2026-03-11 16:18:51
R W Run
6.72 KB
2026-03-11 16:18:52
R W Run
10.92 KB
2026-03-11 16:18:51
R W Run
4.77 KB
2026-03-11 16:18:51
R W Run
3.38 KB
2026-03-11 16:18:51
R W Run
11.18 KB
2026-03-11 16:18:51
R W Run
62.19 KB
2026-03-11 16:18:51
R W Run
2.46 KB
2026-03-11 16:18:51
R W Run
9.17 KB
2026-03-11 16:18:51
R W Run
32.15 KB
2026-03-11 16:18:51
R W Run
34.05 KB
2026-03-11 16:18:52
R W Run
7.15 KB
2026-03-11 16:18:51
R W Run
3.47 KB
2026-03-11 16:18:52
R W Run
1.87 KB
2026-03-11 16:18:52
R W Run
30.91 KB
2026-03-11 16:18:51
R W Run
7.29 KB
2026-03-11 16:18:52
R W Run
7.35 KB
2026-03-11 16:18:51
R W Run
12.54 KB
2026-03-11 16:18:51
R W Run
19.12 KB
2026-03-11 16:18:51
R W Run
18.12 KB
2026-03-11 16:18:52
R W Run
39.99 KB
2026-03-11 16:18:52
R W Run
5.17 KB
2026-03-11 16:18:52
R W Run
979 By
2026-03-11 16:18:51
R W Run
18.44 KB
2026-03-11 16:18:52
R W Run
10.24 KB
2026-03-11 16:18:51
R W Run
1.77 KB
2026-03-11 16:18:52
R W Run
34.9 KB
2026-03-11 16:18:51
R W Run
7.19 KB
2026-03-11 16:18:52
R W Run
160.5 KB
2026-03-11 16:18:51
R W Run
64.27 KB
2026-03-11 16:18:51
R W Run
27.95 KB
2026-03-11 16:18:51
R W Run
4.69 KB
2026-03-11 16:18:51
R W Run
2.94 KB
2026-03-11 16:18:51
R W Run
43.13 KB
2026-03-11 16:18:52
R W Run
2.25 KB
2026-03-11 16:18:52
R W Run
22.5 KB
2026-03-11 16:18:51
R W Run
13.01 KB
2026-03-11 16:18:52
R W Run
3.27 KB
2026-03-11 16:18:51
R W Run
18 KB
2026-03-11 16:18:51
R W Run
210.4 KB
2026-03-11 16:18:52
R W Run
25.86 KB
2026-03-11 16:18:52
R W Run
115.85 KB
2026-03-11 16:18:51
R W Run
373 By
2026-03-11 16:18:52
R W Run
343 By
2026-03-11 16:18:52
R W Run
338 By
2026-03-11 16:18:51
R W Run
100.73 KB
2026-03-11 16:18:52
R W Run
130.93 KB
2026-03-11 16:18:51
R W Run
19.1 KB
2026-03-11 16:18:51
R W Run
17.41 KB
2026-03-11 16:18:52
R W Run
41.98 KB
2026-03-11 16:18:52
R W Run
400 By
2026-03-11 16:18:52
R W Run
11.1 KB
2026-03-11 16:18:52
R W Run
37.02 KB
2026-03-11 16:18:51
R W Run
2.24 KB
2026-03-11 16:18:51
R W Run
188.13 KB
2026-03-11 16:18:51
R W Run
338 By
2026-03-11 16:18:51
R W Run
38 KB
2026-03-11 16:18:51
R W Run
4.02 KB
2026-03-11 16:18:52
R W Run
5.38 KB
2026-03-11 16:18:51
R W Run
3.05 KB
2026-03-11 16:18:52
R W Run
2.61 KB
2026-03-11 16:18:51
R W Run
1.16 KB
2026-03-11 16:18:52
R W Run
4.04 KB
2026-03-11 16:18:51
R W Run
3.71 KB
2026-03-11 16:18:51
R W Run
24.6 KB
2026-03-11 16:18:51
R W Run
9.56 KB
2026-03-11 16:18:51
R W Run
346.43 KB
2026-03-11 16:18:52
R W Run
281.84 KB
2026-03-11 16:18:52
R W Run
14.95 KB
2026-03-11 16:18:51
R W Run
8.44 KB
2026-03-11 16:18:52
R W Run
168.95 KB
2026-03-11 16:18:52
R W Run
20.71 KB
2026-03-11 16:18:52
R W Run
25.27 KB
2026-03-11 16:18:51
R W Run
5.72 KB
2026-03-11 16:18:51
R W Run
4.63 KB
2026-03-11 16:18:52
R W Run
81.73 KB
2026-03-11 16:18:51
R W Run
67.18 KB
2026-03-11 16:18:51
R W Run
156.36 KB
2026-03-11 16:18:52
R W Run
55.19 KB
2026-03-11 16:18:51
R W Run
162 By
2026-03-11 16:18:51
R W Run
61.72 KB
2026-03-11 16:18:51
R W Run
216.06 KB
2026-03-11 16:18:52
R W Run
65.09 KB
2026-03-11 16:18:51
R W Run
25.24 KB
2026-03-11 16:18:52
R W Run
4.81 KB
2026-03-11 16:18:51
R W Run
6.48 KB
2026-03-11 16:18:52
R W Run
21.25 KB
2026-03-11 16:18:51
R W Run
2.79 KB
2026-03-11 16:18:52
R W Run
89.69 KB
2026-03-11 16:18:52
R W Run
19.42 KB
2026-03-11 16:18:52
R W Run
3.69 KB
2026-03-11 16:18:52
R W Run
4.11 KB
2026-03-11 16:18:51
R W Run
40.74 KB
2026-03-11 16:18:51
R W Run
25.38 KB
2026-03-11 16:18:51
R W Run
43.31 KB
2026-03-11 16:18:52
R W Run
102.57 KB
2026-03-11 16:18:52
R W Run
6.18 KB
2026-03-11 16:18:51
R W Run
124.47 KB
2026-03-11 16:18:52
R W Run
35.65 KB
2026-03-11 16:18:52
R W Run
6.94 KB
2026-03-11 16:18:52
R W Run
67.04 KB
2026-03-11 16:18:52
R W Run
10.62 KB
2026-03-11 16:18:51
R W Run
289.35 KB
2026-03-11 16:18:52
R W Run
36.23 KB
2026-03-11 16:18:51
R W Run
200 By
2026-03-11 16:18:52
R W Run
200 By
2026-03-11 16:18:52
R W Run
98.29 KB
2026-03-11 16:18:52
R W Run
30.02 KB
2026-03-11 16:18:52
R W Run
19.03 KB
2026-03-11 16:18:52
R W Run
5.06 KB
2026-03-11 16:18:52
R W Run
255 By
2026-03-11 16:18:51
R W Run
22.66 KB
2026-03-11 16:18:52
R W Run
154.63 KB
2026-03-11 16:18:51
R W Run
9.68 KB
2026-03-11 16:18:51
R W Run
258 By
2026-03-11 16:18:51
R W Run
23.49 KB
2026-03-11 16:18:51
R W Run
3.16 KB
2026-03-11 16:18:51
R W Run
8.4 KB
2026-03-11 16:18:52
R W Run
441 By
2026-03-11 16:18:51
R W Run
7.39 KB
2026-03-11 16:18:51
R W Run
173 KB
2026-03-11 16:18:52
R W Run
544 By
2026-03-11 16:18:52
R W Run
4.17 KB
2026-03-11 16:18:51
R W Run
35.97 KB
2026-03-11 16:18:52
R W Run
1.69 KB
2026-03-11 16:18:51
R W Run
2.84 KB
2026-03-11 16:18:52
R W Run
6.09 KB
2026-03-11 16:18:51
R W Run
8.71 KB
2026-03-11 16:18:51
R W Run
131.84 KB
2026-03-11 16:18:51
R W Run
37.45 KB
2026-03-11 16:18:51
R W Run
173.89 KB
2026-03-11 16:18:51
R W Run
7.09 KB
2026-03-11 16:18:51
R W Run
6.41 KB
2026-03-11 16:18:51
R W Run
1.08 KB
2026-03-11 16:18:51
R W Run
69.46 KB
2026-03-11 16:18:52
R W Run
445 By
2026-03-11 16:18:51
R W Run
799 By
2026-03-11 16:18:52
R W Run
error_log
📄class-wp-theme-json-resolver.php
1<?php
2/**
3 * WP_Theme_JSON_Resolver class
4 *
5 * @package WordPress
6 * @subpackage Theme
7 * @since 5.8.0
8 */
9
10/**
11 * Class that abstracts the processing of the different data sources
12 * for site-level config and offers an API to work with them.
13 *
14 * This class is for internal core usage and is not supposed to be used by extenders (plugins and/or themes).
15 * This is a low-level API that may need to do breaking changes. Please,
16 * use get_global_settings(), get_global_styles(), and get_global_stylesheet() instead.
17 *
18 * @access private
19 */
20#[AllowDynamicProperties]
21class WP_Theme_JSON_Resolver {
22
23 /**
24 * Container for keep track of registered blocks.
25 *
26 * @since 6.1.0
27 * @var array
28 */
29 protected static $blocks_cache = array(
30 'core' => array(),
31 'blocks' => array(),
32 'theme' => array(),
33 'user' => array(),
34 );
35
36 /**
37 * Container for data coming from core.
38 *
39 * @since 5.8.0
40 * @var WP_Theme_JSON
41 */
42 protected static $core = null;
43
44 /**
45 * Container for data coming from the blocks.
46 *
47 * @since 6.1.0
48 * @var WP_Theme_JSON
49 */
50 protected static $blocks = null;
51
52 /**
53 * Container for data coming from the theme.
54 *
55 * @since 5.8.0
56 * @var WP_Theme_JSON
57 */
58 protected static $theme = null;
59
60 /**
61 * Container for data coming from the user.
62 *
63 * @since 5.9.0
64 * @var WP_Theme_JSON
65 */
66 protected static $user = null;
67
68 /**
69 * Stores the ID of the custom post type
70 * that holds the user data.
71 *
72 * @since 5.9.0
73 * @var int
74 */
75 protected static $user_custom_post_type_id = null;
76
77 /**
78 * Container to keep loaded i18n schema for `theme.json`.
79 *
80 * @since 5.8.0 As `$theme_json_i18n`.
81 * @since 5.9.0 Renamed from `$theme_json_i18n` to `$i18n_schema`.
82 * @var array
83 */
84 protected static $i18n_schema = null;
85
86 /**
87 * `theme.json` file cache.
88 *
89 * @since 6.1.0
90 * @var array
91 */
92 protected static $theme_json_file_cache = array();
93
94 /**
95 * Processes a file that adheres to the theme.json schema
96 * and returns an array with its contents, or a void array if none found.
97 *
98 * @since 5.8.0
99 * @since 6.1.0 Added caching.
100 *
101 * @param string $file_path Path to file. Empty if no file.
102 * @return array Contents that adhere to the theme.json schema.
103 */
104 protected static function read_json_file( $file_path ) {
105 if ( $file_path ) {
106 if ( array_key_exists( $file_path, static::$theme_json_file_cache ) ) {
107 return static::$theme_json_file_cache[ $file_path ];
108 }
109
110 $decoded_file = wp_json_file_decode( $file_path, array( 'associative' => true ) );
111 if ( is_array( $decoded_file ) ) {
112 static::$theme_json_file_cache[ $file_path ] = $decoded_file;
113 return static::$theme_json_file_cache[ $file_path ];
114 }
115 }
116
117 return array();
118 }
119
120 /**
121 * Returns a data structure used in theme.json translation.
122 *
123 * @since 5.8.0
124 * @deprecated 5.9.0
125 *
126 * @return array An array of theme.json fields that are translatable and the keys that are translatable.
127 */
128 public static function get_fields_to_translate() {
129 _deprecated_function( __METHOD__, '5.9.0' );
130 return array();
131 }
132
133 /**
134 * Given a theme.json structure modifies it in place to update certain values
135 * by its translated strings according to the language set by the user.
136 *
137 * @since 5.8.0
138 *
139 * @param array $theme_json The theme.json to translate.
140 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
141 * Default 'default'.
142 * @return array Returns the modified $theme_json_structure.
143 */
144 protected static function translate( $theme_json, $domain = 'default' ) {
145 if ( null === static::$i18n_schema ) {
146 $i18n_schema = wp_json_file_decode( __DIR__ . '/theme-i18n.json' );
147 static::$i18n_schema = null === $i18n_schema ? array() : $i18n_schema;
148 }
149
150 return translate_settings_using_i18n_schema( static::$i18n_schema, $theme_json, $domain );
151 }
152
153 /**
154 * Returns core's origin config.
155 *
156 * @since 5.8.0
157 *
158 * @return WP_Theme_JSON Entity that holds core data.
159 */
160 public static function get_core_data() {
161 if ( null !== static::$core && static::has_same_registered_blocks( 'core' ) ) {
162 return static::$core;
163 }
164
165 $config = static::read_json_file( __DIR__ . '/theme.json' );
166 $config = static::translate( $config );
167
168 /**
169 * Filters the default data provided by WordPress for global styles & settings.
170 *
171 * @since 6.1.0
172 *
173 * @param WP_Theme_JSON_Data $theme_json Class to access and update the underlying data.
174 */
175 $theme_json = apply_filters( 'wp_theme_json_data_default', new WP_Theme_JSON_Data( $config, 'default' ) );
176
177 /*
178 * Backward compatibility for extenders returning a WP_Theme_JSON_Data
179 * compatible class that is not a WP_Theme_JSON_Data object.
180 */
181 if ( $theme_json instanceof WP_Theme_JSON_Data ) {
182 static::$core = $theme_json->get_theme_json();
183 } else {
184 $config = $theme_json->get_data();
185 static::$core = new WP_Theme_JSON( $config, 'default' );
186 }
187
188 return static::$core;
189 }
190
191 /**
192 * Checks whether the registered blocks were already processed for this origin.
193 *
194 * @since 6.1.0
195 *
196 * @param string $origin Data source for which to cache the blocks.
197 * Valid values are 'core', 'blocks', 'theme', and 'user'.
198 * @return bool True on success, false otherwise.
199 */
200 protected static function has_same_registered_blocks( $origin ) {
201 // Bail out if the origin is invalid.
202 if ( ! isset( static::$blocks_cache[ $origin ] ) ) {
203 return false;
204 }
205
206 $registry = WP_Block_Type_Registry::get_instance();
207 $blocks = $registry->get_all_registered();
208
209 // Is there metadata for all currently registered blocks?
210 $block_diff = array_diff_key( $blocks, static::$blocks_cache[ $origin ] );
211 if ( empty( $block_diff ) ) {
212 return true;
213 }
214
215 foreach ( $blocks as $block_name => $block_type ) {
216 static::$blocks_cache[ $origin ][ $block_name ] = true;
217 }
218
219 return false;
220 }
221
222 /**
223 * Returns the theme's data.
224 *
225 * Data from theme.json will be backfilled from existing
226 * theme supports, if any. Note that if the same data
227 * is present in theme.json and in theme supports,
228 * the theme.json takes precedence.
229 *
230 * @since 5.8.0
231 * @since 5.9.0 Theme supports have been inlined and the `$theme_support_data` argument removed.
232 * @since 6.0.0 Added an `$options` parameter to allow the theme data to be returned without theme supports.
233 * @since 6.6.0 Add support for 'default-font-sizes' and 'default-spacing-sizes' theme supports.
234 * Added registration and merging of block style variations from partial theme.json files and the block styles registry.
235 *
236 * @param array $deprecated Deprecated. Not used.
237 * @param array $options {
238 * Options arguments.
239 *
240 * @type bool $with_supports Whether to include theme supports in the data. Default true.
241 * }
242 * @return WP_Theme_JSON Entity that holds theme data.
243 */
244 public static function get_theme_data( $deprecated = array(), $options = array() ) {
245 if ( ! empty( $deprecated ) ) {
246 _deprecated_argument( __METHOD__, '5.9.0' );
247 }
248
249 $options = wp_parse_args( $options, array( 'with_supports' => true ) );
250
251 if ( null === static::$theme || ! static::has_same_registered_blocks( 'theme' ) ) {
252 $wp_theme = wp_get_theme();
253 $theme_json_file = $wp_theme->get_file_path( 'theme.json' );
254 if ( is_readable( $theme_json_file ) ) {
255 $theme_json_data = static::read_json_file( $theme_json_file );
256 $theme_json_data = static::translate( $theme_json_data, $wp_theme->get( 'TextDomain' ) );
257 } else {
258 $theme_json_data = array( 'version' => WP_Theme_JSON::LATEST_SCHEMA );
259 }
260
261 /*
262 * Register variations defined by theme partials (theme.json files in the styles directory).
263 * This is required so the variations pass sanitization of theme.json data.
264 */
265 $variations = static::get_style_variations( 'block' );
266 wp_register_block_style_variations_from_theme_json_partials( $variations );
267
268 /*
269 * Source variations from the block registry and block style variation files. Then, merge them into the existing theme.json data.
270 *
271 * In case the same style properties are defined in several sources, this is how we should resolve the values,
272 * from higher to lower priority:
273 *
274 * - styles.blocks.blockType.variations from theme.json
275 * - styles.variations from theme.json
276 * - variations from block style variation files
277 * - variations from block styles registry
278 *
279 * See test_add_registered_block_styles_to_theme_data and test_unwraps_block_style_variations.
280 *
281 */
282 $theme_json_data = static::inject_variations_from_block_style_variation_files( $theme_json_data, $variations );
283 $theme_json_data = static::inject_variations_from_block_styles_registry( $theme_json_data );
284
285 /**
286 * Filters the data provided by the theme for global styles and settings.
287 *
288 * @since 6.1.0
289 *
290 * @param WP_Theme_JSON_Data $theme_json Class to access and update the underlying data.
291 */
292 $theme_json = apply_filters( 'wp_theme_json_data_theme', new WP_Theme_JSON_Data( $theme_json_data, 'theme' ) );
293
294 /*
295 * Backward compatibility for extenders returning a WP_Theme_JSON_Data
296 * compatible class that is not a WP_Theme_JSON_Data object.
297 */
298 if ( $theme_json instanceof WP_Theme_JSON_Data ) {
299 static::$theme = $theme_json->get_theme_json();
300 } else {
301 $config = $theme_json->get_data();
302 static::$theme = new WP_Theme_JSON( $config );
303 }
304
305 if ( $wp_theme->parent() ) {
306 // Get parent theme.json.
307 $parent_theme_json_file = $wp_theme->parent()->get_file_path( 'theme.json' );
308 if ( $theme_json_file !== $parent_theme_json_file && is_readable( $parent_theme_json_file ) ) {
309 $parent_theme_json_data = static::read_json_file( $parent_theme_json_file );
310 $parent_theme_json_data = static::translate( $parent_theme_json_data, $wp_theme->parent()->get( 'TextDomain' ) );
311 $parent_theme = new WP_Theme_JSON( $parent_theme_json_data );
312
313 /*
314 * Merge the child theme.json into the parent theme.json.
315 * The child theme takes precedence over the parent.
316 */
317 $parent_theme->merge( static::$theme );
318 static::$theme = $parent_theme;
319 }
320 }
321 }
322
323 if ( ! $options['with_supports'] ) {
324 return static::$theme;
325 }
326
327 /*
328 * We want the presets and settings declared in theme.json
329 * to override the ones declared via theme supports.
330 * So we take theme supports, transform it to theme.json shape
331 * and merge the static::$theme upon that.
332 */
333 $theme_support_data = WP_Theme_JSON::get_from_editor_settings( get_classic_theme_supports_block_editor_settings() );
334 if ( ! wp_theme_has_theme_json() ) {
335 /*
336 * Unlike block themes, classic themes without a theme.json disable
337 * default presets when custom preset theme support is added. This
338 * behavior can be overridden by using the corresponding default
339 * preset theme support.
340 */
341 $theme_support_data['settings']['color']['defaultPalette'] =
342 ! isset( $theme_support_data['settings']['color']['palette'] ) ||
343 current_theme_supports( 'default-color-palette' );
344 $theme_support_data['settings']['color']['defaultGradients'] =
345 ! isset( $theme_support_data['settings']['color']['gradients'] ) ||
346 current_theme_supports( 'default-gradient-presets' );
347 $theme_support_data['settings']['typography']['defaultFontSizes'] =
348 ! isset( $theme_support_data['settings']['typography']['fontSizes'] ) ||
349 current_theme_supports( 'default-font-sizes' );
350 $theme_support_data['settings']['spacing']['defaultSpacingSizes'] =
351 ! isset( $theme_support_data['settings']['spacing']['spacingSizes'] ) ||
352 current_theme_supports( 'default-spacing-sizes' );
353
354 /*
355 * Shadow presets are explicitly disabled for classic themes until a
356 * decision is made for whether the default presets should match the
357 * other presets or if they should be disabled by default in classic
358 * themes. See https://github.com/WordPress/gutenberg/issues/59989.
359 */
360 $theme_support_data['settings']['shadow']['defaultPresets'] = false;
361
362 // Allow themes to enable link color setting via theme_support.
363 if ( current_theme_supports( 'link-color' ) ) {
364 $theme_support_data['settings']['color']['link'] = true;
365 }
366
367 // Allow themes to enable all border settings via theme_support.
368 if ( current_theme_supports( 'border' ) ) {
369 $theme_support_data['settings']['border']['color'] = true;
370 $theme_support_data['settings']['border']['radius'] = true;
371 $theme_support_data['settings']['border']['style'] = true;
372 $theme_support_data['settings']['border']['width'] = true;
373 }
374
375 // Allow themes to enable appearance tools via theme_support.
376 if ( current_theme_supports( 'appearance-tools' ) ) {
377 $theme_support_data['settings']['appearanceTools'] = true;
378 }
379 }
380 $with_theme_supports = new WP_Theme_JSON( $theme_support_data );
381 $with_theme_supports->merge( static::$theme );
382 return $with_theme_supports;
383 }
384
385 /**
386 * Gets the styles for blocks from the block.json file.
387 *
388 * @since 6.1.0
389 *
390 * @return WP_Theme_JSON
391 */
392 public static function get_block_data() {
393 $registry = WP_Block_Type_Registry::get_instance();
394 $blocks = $registry->get_all_registered();
395
396 if ( null !== static::$blocks && static::has_same_registered_blocks( 'blocks' ) ) {
397 return static::$blocks;
398 }
399
400 $config = array( 'version' => WP_Theme_JSON::LATEST_SCHEMA );
401 foreach ( $blocks as $block_name => $block_type ) {
402 if ( isset( $block_type->supports['__experimentalStyle'] ) ) {
403 $config['styles']['blocks'][ $block_name ] = static::remove_json_comments( $block_type->supports['__experimentalStyle'] );
404 }
405
406 if (
407 isset( $block_type->supports['spacing']['blockGap']['__experimentalDefault'] ) &&
408 ! isset( $config['styles']['blocks'][ $block_name ]['spacing']['blockGap'] )
409 ) {
410 /*
411 * Ensure an empty placeholder value exists for the block, if it provides a default blockGap value.
412 * The real blockGap value to be used will be determined when the styles are rendered for output.
413 */
414 $config['styles']['blocks'][ $block_name ]['spacing']['blockGap'] = null;
415 }
416 }
417
418 /**
419 * Filters the data provided by the blocks for global styles & settings.
420 *
421 * @since 6.1.0
422 *
423 * @param WP_Theme_JSON_Data $theme_json Class to access and update the underlying data.
424 */
425 $theme_json = apply_filters( 'wp_theme_json_data_blocks', new WP_Theme_JSON_Data( $config, 'blocks' ) );
426
427 /*
428 * Backward compatibility for extenders returning a WP_Theme_JSON_Data
429 * compatible class that is not a WP_Theme_JSON_Data object.
430 */
431 if ( $theme_json instanceof WP_Theme_JSON_Data ) {
432 static::$blocks = $theme_json->get_theme_json();
433 } else {
434 $config = $theme_json->get_data();
435 static::$blocks = new WP_Theme_JSON( $config, 'blocks' );
436 }
437
438 return static::$blocks;
439 }
440
441 /**
442 * When given an array, this will remove any keys with the name `//`.
443 *
444 * @since 6.1.0
445 *
446 * @param array $input_array The array to filter.
447 * @return array The filtered array.
448 */
449 private static function remove_json_comments( $input_array ) {
450 unset( $input_array['//'] );
451 foreach ( $input_array as $k => $v ) {
452 if ( is_array( $v ) ) {
453 $input_array[ $k ] = static::remove_json_comments( $v );
454 }
455 }
456
457 return $input_array;
458 }
459
460 /**
461 * Returns the custom post type that contains the user's origin config
462 * for the active theme or an empty array if none are found.
463 *
464 * This can also create and return a new draft custom post type.
465 *
466 * @since 5.9.0
467 *
468 * @param WP_Theme $theme The theme object. If empty, it
469 * defaults to the active theme.
470 * @param bool $create_post Optional. Whether a new custom post
471 * type should be created if none are
472 * found. Default false.
473 * @param array $post_status_filter Optional. Filter custom post type by
474 * post status. Default `array( 'publish' )`,
475 * so it only fetches published posts.
476 * @return array Custom Post Type for the user's origin config.
477 */
478 public static function get_user_data_from_wp_global_styles( $theme, $create_post = false, $post_status_filter = array( 'publish' ) ) {
479 if ( ! $theme instanceof WP_Theme ) {
480 $theme = wp_get_theme();
481 }
482
483 /*
484 * Bail early if the theme does not support a theme.json.
485 *
486 * Since wp_theme_has_theme_json() only supports the active
487 * theme, the extra condition for whether $theme is the active theme is
488 * present here.
489 */
490 if ( $theme->get_stylesheet() === get_stylesheet() && ! wp_theme_has_theme_json() ) {
491 return array();
492 }
493
494 $user_cpt = array();
495 $post_type_filter = 'wp_global_styles';
496 $stylesheet = $theme->get_stylesheet();
497 $args = array(
498 'posts_per_page' => 1,
499 'orderby' => 'date',
500 'order' => 'desc',
501 'post_type' => $post_type_filter,
502 'post_status' => $post_status_filter,
503 'ignore_sticky_posts' => true,
504 'no_found_rows' => true,
505 'update_post_meta_cache' => false,
506 'update_post_term_cache' => false,
507 'tax_query' => array(
508 array(
509 'taxonomy' => 'wp_theme',
510 'field' => 'name',
511 'terms' => $stylesheet,
512 ),
513 ),
514 );
515
516 $global_style_query = new WP_Query();
517 $recent_posts = $global_style_query->query( $args );
518 if ( count( $recent_posts ) === 1 ) {
519 $user_cpt = get_object_vars( $recent_posts[0] );
520 } elseif ( $create_post ) {
521 $cpt_post_id = wp_insert_post(
522 array(
523 'post_content' => '{"version": ' . WP_Theme_JSON::LATEST_SCHEMA . ', "isGlobalStylesUserThemeJSON": true }',
524 'post_status' => 'publish',
525 'post_title' => 'Custom Styles', // Do not make string translatable, see https://core.trac.wordpress.org/ticket/54518.
526 'post_type' => $post_type_filter,
527 'post_name' => sprintf( 'wp-global-styles-%s', urlencode( $stylesheet ) ),
528 'tax_input' => array(
529 'wp_theme' => array( $stylesheet ),
530 ),
531 ),
532 true
533 );
534 if ( ! is_wp_error( $cpt_post_id ) ) {
535 $user_cpt = get_object_vars( get_post( $cpt_post_id ) );
536 }
537 }
538
539 return $user_cpt;
540 }
541
542 /**
543 * Returns the user's origin config.
544 *
545 * @since 5.9.0
546 * @since 6.6.0 The 'isGlobalStylesUserThemeJSON' flag is left on the user data.
547 * Register the block style variations coming from the user data.
548 *
549 * @return WP_Theme_JSON Entity that holds styles for user data.
550 */
551 public static function get_user_data() {
552 if ( null !== static::$user && static::has_same_registered_blocks( 'user' ) ) {
553 return static::$user;
554 }
555
556 $config = array();
557 $user_cpt = static::get_user_data_from_wp_global_styles( wp_get_theme() );
558
559 if ( array_key_exists( 'post_content', $user_cpt ) ) {
560 $decoded_data = json_decode( $user_cpt['post_content'], true );
561
562 $json_decoding_error = json_last_error();
563 if ( JSON_ERROR_NONE !== $json_decoding_error ) {
564 wp_trigger_error( __METHOD__, 'Error when decoding a theme.json schema for user data. ' . json_last_error_msg() );
565 /**
566 * Filters the data provided by the user for global styles & settings.
567 *
568 * @since 6.1.0
569 *
570 * @param WP_Theme_JSON_Data $theme_json Class to access and update the underlying data.
571 */
572 $theme_json = apply_filters( 'wp_theme_json_data_user', new WP_Theme_JSON_Data( $config, 'custom' ) );
573
574 /*
575 * Backward compatibility for extenders returning a WP_Theme_JSON_Data
576 * compatible class that is not a WP_Theme_JSON_Data object.
577 */
578 if ( $theme_json instanceof WP_Theme_JSON_Data ) {
579 return $theme_json->get_theme_json();
580 } else {
581 $config = $theme_json->get_data();
582 return new WP_Theme_JSON( $config, 'custom' );
583 }
584 }
585
586 /*
587 * Very important to verify that the flag isGlobalStylesUserThemeJSON is true.
588 * If it's not true then the content was not escaped and is not safe.
589 */
590 if (
591 is_array( $decoded_data ) &&
592 isset( $decoded_data['isGlobalStylesUserThemeJSON'] ) &&
593 $decoded_data['isGlobalStylesUserThemeJSON']
594 ) {
595 unset( $decoded_data['isGlobalStylesUserThemeJSON'] );
596 $config = $decoded_data;
597 }
598 }
599
600 /** This filter is documented in wp-includes/class-wp-theme-json-resolver.php */
601 $theme_json = apply_filters( 'wp_theme_json_data_user', new WP_Theme_JSON_Data( $config, 'custom' ) );
602
603 /*
604 * Backward compatibility for extenders returning a WP_Theme_JSON_Data
605 * compatible class that is not a WP_Theme_JSON_Data object.
606 */
607 if ( $theme_json instanceof WP_Theme_JSON_Data ) {
608 static::$user = $theme_json->get_theme_json();
609 } else {
610 $config = $theme_json->get_data();
611 static::$user = new WP_Theme_JSON( $config, 'custom' );
612 }
613
614 return static::$user;
615 }
616
617 /**
618 * Returns the data merged from multiple origins.
619 *
620 * There are four sources of data (origins) for a site:
621 *
622 * - default => WordPress
623 * - blocks => each one of the blocks provides data for itself
624 * - theme => the active theme
625 * - custom => data provided by the user
626 *
627 * The custom's has higher priority than the theme's, the theme's higher than blocks',
628 * and block's higher than default's.
629 *
630 * Unlike the getters
631 * {@link https://developer.wordpress.org/reference/classes/wp_theme_json_resolver/get_core_data/ get_core_data},
632 * {@link https://developer.wordpress.org/reference/classes/wp_theme_json_resolver/get_theme_data/ get_theme_data},
633 * and {@link https://developer.wordpress.org/reference/classes/wp_theme_json_resolver/get_user_data/ get_user_data},
634 * this method returns data after it has been merged with the previous origins.
635 * This means that if the same piece of data is declared in different origins
636 * (default, blocks, theme, custom), the last origin overrides the previous.
637 *
638 * For example, if the user has set a background color
639 * for the paragraph block, and the theme has done it as well,
640 * the user preference wins.
641 *
642 * @since 5.8.0
643 * @since 5.9.0 Added user data, removed the `$settings` parameter,
644 * added the `$origin` parameter.
645 * @since 6.1.0 Added block data and generation of spacingSizes array.
646 * @since 6.2.0 Changed ' $origin' parameter values to 'default', 'blocks', 'theme' or 'custom'.
647 *
648 * @param string $origin Optional. To what level should we merge data: 'default', 'blocks', 'theme' or 'custom'.
649 * 'custom' is used as default value as well as fallback value if the origin is unknown.
650 * @return WP_Theme_JSON
651 */
652 public static function get_merged_data( $origin = 'custom' ) {
653 if ( is_array( $origin ) ) {
654 _deprecated_argument( __FUNCTION__, '5.9.0' );
655 }
656
657 $result = new WP_Theme_JSON();
658 $result->merge( static::get_core_data() );
659 if ( 'default' === $origin ) {
660 return $result;
661 }
662
663 $result->merge( static::get_block_data() );
664 if ( 'blocks' === $origin ) {
665 return $result;
666 }
667
668 $result->merge( static::get_theme_data() );
669 if ( 'theme' === $origin ) {
670 return $result;
671 }
672
673 $result->merge( static::get_user_data() );
674
675 return $result;
676 }
677
678 /**
679 * Returns the ID of the custom post type
680 * that stores user data.
681 *
682 * @since 5.9.0
683 *
684 * @return integer|null
685 */
686 public static function get_user_global_styles_post_id() {
687 if ( null !== static::$user_custom_post_type_id ) {
688 return static::$user_custom_post_type_id;
689 }
690
691 $user_cpt = static::get_user_data_from_wp_global_styles( wp_get_theme(), true );
692
693 if ( array_key_exists( 'ID', $user_cpt ) ) {
694 static::$user_custom_post_type_id = $user_cpt['ID'];
695 }
696
697 return static::$user_custom_post_type_id;
698 }
699
700 /**
701 * Determines whether the active theme has a theme.json file.
702 *
703 * @since 5.8.0
704 * @since 5.9.0 Added a check in the parent theme.
705 * @deprecated 6.2.0 Use wp_theme_has_theme_json() instead.
706 *
707 * @return bool
708 */
709 public static function theme_has_support() {
710 _deprecated_function( __METHOD__, '6.2.0', 'wp_theme_has_theme_json()' );
711
712 return wp_theme_has_theme_json();
713 }
714
715 /**
716 * Builds the path to the given file and checks that it is readable.
717 *
718 * If it isn't, returns an empty string, otherwise returns the whole file path.
719 *
720 * @since 5.8.0
721 * @since 5.9.0 Adapted to work with child themes, added the `$template` argument.
722 *
723 * @param string $file_name Name of the file.
724 * @param bool $template Optional. Use template theme directory. Default false.
725 * @return string The whole file path or empty if the file doesn't exist.
726 */
727 protected static function get_file_path_from_theme( $file_name, $template = false ) {
728 $path = $template ? get_template_directory() : get_stylesheet_directory();
729 $candidate = $path . '/' . $file_name;
730
731 return is_readable( $candidate ) ? $candidate : '';
732 }
733
734 /**
735 * Cleans the cached data so it can be recalculated.
736 *
737 * @since 5.8.0
738 * @since 5.9.0 Added the `$user`, `$user_custom_post_type_id`,
739 * and `$i18n_schema` variables to reset.
740 * @since 6.1.0 Added the `$blocks` and `$blocks_cache` variables
741 * to reset.
742 */
743 public static function clean_cached_data() {
744 static::$core = null;
745 static::$blocks = null;
746 static::$blocks_cache = array(
747 'core' => array(),
748 'blocks' => array(),
749 'theme' => array(),
750 'user' => array(),
751 );
752 static::$theme = null;
753 static::$user = null;
754 static::$user_custom_post_type_id = null;
755 static::$i18n_schema = null;
756 }
757
758 /**
759 * Returns an array of all nested JSON files within a given directory.
760 *
761 * @since 6.2.0
762 *
763 * @param string $dir The directory to recursively iterate and list files of.
764 * @return array The merged array.
765 */
766 private static function recursively_iterate_json( $dir ) {
767 $nested_files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir ) );
768 $nested_json_files = iterator_to_array( new RegexIterator( $nested_files, '/^.+\.json$/i', RecursiveRegexIterator::GET_MATCH ) );
769 return $nested_json_files;
770 }
771
772 /**
773 * Determines if a supplied style variation matches the provided scope.
774 *
775 * For backwards compatibility, if a variation does not define any scope
776 * related property, e.g. `blockTypes`, it is assumed to be a theme style
777 * variation.
778 *
779 * @since 6.6.0
780 *
781 * @param array $variation Theme.json shaped style variation object.
782 * @param string $scope Scope to check e.g. theme, block etc.
783 * @return boolean
784 */
785 private static function style_variation_has_scope( $variation, $scope ) {
786 if ( 'block' === $scope ) {
787 return isset( $variation['blockTypes'] );
788 }
789
790 if ( 'theme' === $scope ) {
791 return ! isset( $variation['blockTypes'] );
792 }
793
794 return false;
795 }
796
797 /**
798 * Returns the style variations defined by the theme.
799 *
800 * @since 6.0.0
801 * @since 6.2.0 Returns parent theme variations if theme is a child.
802 * @since 6.6.0 Added configurable scope parameter to allow filtering
803 * theme.json partial files by the scope to which they
804 * can be applied e.g. theme vs block etc.
805 * Added basic caching for read theme.json partial files.
806 *
807 * @param string $scope The scope or type of style variation to retrieve e.g. theme, block etc.
808 * @return array
809 */
810 public static function get_style_variations( $scope = 'theme' ) {
811 $variation_files = array();
812 $variations = array();
813 $base_directory = get_stylesheet_directory() . '/styles';
814 $template_directory = get_template_directory() . '/styles';
815 if ( is_dir( $base_directory ) ) {
816 $variation_files = static::recursively_iterate_json( $base_directory );
817 }
818 if ( is_dir( $template_directory ) && $template_directory !== $base_directory ) {
819 $variation_files_parent = static::recursively_iterate_json( $template_directory );
820 // If the child and parent variation file basename are the same, only include the child theme's.
821 foreach ( $variation_files_parent as $parent_path => $parent ) {
822 foreach ( $variation_files as $child_path => $child ) {
823 if ( basename( $parent_path ) === basename( $child_path ) ) {
824 unset( $variation_files_parent[ $parent_path ] );
825 }
826 }
827 }
828 $variation_files = array_merge( $variation_files, $variation_files_parent );
829 }
830 ksort( $variation_files );
831 foreach ( $variation_files as $path => $file ) {
832 $decoded_file = self::read_json_file( $path );
833 if ( is_array( $decoded_file ) && static::style_variation_has_scope( $decoded_file, $scope ) ) {
834 $translated = static::translate( $decoded_file, wp_get_theme()->get( 'TextDomain' ) );
835 $variation = ( new WP_Theme_JSON( $translated ) )->get_raw_data();
836 if ( empty( $variation['title'] ) ) {
837 $variation['title'] = basename( $path, '.json' );
838 }
839 $variations[] = $variation;
840 }
841 }
842 return $variations;
843 }
844
845 /**
846 * Resolves relative paths in theme.json styles to theme absolute paths
847 * and returns them in an array that can be embedded
848 * as the value of `_link` object in REST API responses.
849 *
850 * @since 6.6.0
851 * @since 6.7.0 Resolve relative paths in block styles.
852 *
853 * @param WP_Theme_JSON $theme_json A theme json instance.
854 * @return array An array of resolved paths.
855 */
856 public static function get_resolved_theme_uris( $theme_json ) {
857 $resolved_theme_uris = array();
858
859 if ( ! $theme_json instanceof WP_Theme_JSON ) {
860 return $resolved_theme_uris;
861 }
862
863 $theme_json_data = $theme_json->get_raw_data();
864 /*
865 * The same file convention when registering web fonts.
866 * See: WP_Font_Face_Resolver::to_theme_file_uri.
867 */
868 $placeholder = 'file:./';
869
870 // Top level styles.
871 $background_image_url = $theme_json_data['styles']['background']['backgroundImage']['url'] ?? null;
872 if (
873 isset( $background_image_url ) &&
874 is_string( $background_image_url ) &&
875 // Skip if the src doesn't start with the placeholder, as there's nothing to replace.
876 str_starts_with( $background_image_url, $placeholder )
877 ) {
878 $file_type = wp_check_filetype( $background_image_url );
879 $src_url = str_replace( $placeholder, '', $background_image_url );
880 $resolved_theme_uri = array(
881 'name' => $background_image_url,
882 'href' => sanitize_url( get_theme_file_uri( $src_url ) ),
883 'target' => 'styles.background.backgroundImage.url',
884 );
885 if ( isset( $file_type['type'] ) ) {
886 $resolved_theme_uri['type'] = $file_type['type'];
887 }
888 $resolved_theme_uris[] = $resolved_theme_uri;
889 }
890
891 // Block styles.
892 if ( ! empty( $theme_json_data['styles']['blocks'] ) ) {
893 foreach ( $theme_json_data['styles']['blocks'] as $block_name => $block_styles ) {
894 if ( ! isset( $block_styles['background']['backgroundImage']['url'] ) ) {
895 continue;
896 }
897 $background_image_url = $block_styles['background']['backgroundImage']['url'];
898 if (
899 is_string( $background_image_url ) &&
900 // Skip if the src doesn't start with the placeholder, as there's nothing to replace.
901 str_starts_with( $background_image_url, $placeholder )
902 ) {
903 $file_type = wp_check_filetype( $background_image_url );
904 $src_url = str_replace( $placeholder, '', $background_image_url );
905 $resolved_theme_uri = array(
906 'name' => $background_image_url,
907 'href' => sanitize_url( get_theme_file_uri( $src_url ) ),
908 'target' => "styles.blocks.{$block_name}.background.backgroundImage.url",
909 );
910 if ( isset( $file_type['type'] ) ) {
911 $resolved_theme_uri['type'] = $file_type['type'];
912 }
913 $resolved_theme_uris[] = $resolved_theme_uri;
914 }
915 }
916 }
917
918 return $resolved_theme_uris;
919 }
920
921 /**
922 * Resolves relative paths in theme.json styles to theme absolute paths
923 * and merges them with incoming theme JSON.
924 *
925 * @since 6.6.0
926 *
927 * @param WP_Theme_JSON $theme_json A theme json instance.
928 * @return WP_Theme_JSON Theme merged with resolved paths, if any found.
929 */
930 public static function resolve_theme_file_uris( $theme_json ) {
931 $resolved_urls = static::get_resolved_theme_uris( $theme_json );
932 if ( empty( $resolved_urls ) ) {
933 return $theme_json;
934 }
935
936 $resolved_theme_json_data = $theme_json->get_raw_data();
937
938 foreach ( $resolved_urls as $resolved_url ) {
939 $path = explode( '.', $resolved_url['target'] );
940 _wp_array_set( $resolved_theme_json_data, $path, $resolved_url['href'] );
941 }
942
943 return new WP_Theme_JSON( $resolved_theme_json_data );
944 }
945
946 /**
947 * Adds variations sourced from block style variations files to the supplied theme.json data.
948 *
949 * @since 6.6.0
950 *
951 * @param array $data Array following the theme.json specification.
952 * @param array $variations Shared block style variations.
953 * @return array Theme json data including shared block style variation definitions.
954 */
955 private static function inject_variations_from_block_style_variation_files( $data, $variations ) {
956 if ( empty( $variations ) ) {
957 return $data;
958 }
959
960 foreach ( $variations as $variation ) {
961 if ( empty( $variation['styles'] ) || empty( $variation['blockTypes'] ) ) {
962 continue;
963 }
964
965 $variation_name = $variation['slug'] ?? _wp_to_kebab_case( $variation['title'] );
966
967 foreach ( $variation['blockTypes'] as $block_type ) {
968 // First, override partial styles with any top-level styles.
969 $top_level_data = $data['styles']['variations'][ $variation_name ] ?? array();
970 if ( ! empty( $top_level_data ) ) {
971 $variation['styles'] = array_replace_recursive( $variation['styles'], $top_level_data );
972 }
973
974 // Then, override styles so far with any block-level styles.
975 $block_level_data = $data['styles']['blocks'][ $block_type ]['variations'][ $variation_name ] ?? array();
976 if ( ! empty( $block_level_data ) ) {
977 $variation['styles'] = array_replace_recursive( $variation['styles'], $block_level_data );
978 }
979
980 $path = array( 'styles', 'blocks', $block_type, 'variations', $variation_name );
981 _wp_array_set( $data, $path, $variation['styles'] );
982 }
983 }
984
985 return $data;
986 }
987
988 /**
989 * Adds variations sourced from the block styles registry to the supplied theme.json data.
990 *
991 * @since 6.6.0
992 *
993 * @param array $data Array following the theme.json specification.
994 * @return array Theme json data including shared block style variation definitions.
995 */
996 private static function inject_variations_from_block_styles_registry( $data ) {
997 $registry = WP_Block_Styles_Registry::get_instance();
998 $styles = $registry->get_all_registered();
999
1000 foreach ( $styles as $block_type => $variations ) {
1001 foreach ( $variations as $variation_name => $variation ) {
1002 if ( empty( $variation['style_data'] ) ) {
1003 continue;
1004 }
1005
1006 // First, override registry styles with any top-level styles.
1007 $top_level_data = $data['styles']['variations'][ $variation_name ] ?? array();
1008 if ( ! empty( $top_level_data ) ) {
1009 $variation['style_data'] = array_replace_recursive( $variation['style_data'], $top_level_data );
1010 }
1011
1012 // Then, override styles so far with any block-level styles.
1013 $block_level_data = $data['styles']['blocks'][ $block_type ]['variations'][ $variation_name ] ?? array();
1014 if ( ! empty( $block_level_data ) ) {
1015 $variation['style_data'] = array_replace_recursive( $variation['style_data'], $block_level_data );
1016 }
1017
1018 $path = array( 'styles', 'blocks', $block_type, 'variations', $variation_name );
1019 _wp_array_set( $data, $path, $variation['style_data'] );
1020 }
1021 }
1022
1023 return $data;
1024 }
1025}
1026
Ui Ux Design – Teachers Night Out https://cardgames4educators.com Wed, 16 Oct 2024 22:24:18 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 https://cardgames4educators.com/wp-content/uploads/2024/06/cropped-Card-4-Educators-logo-32x32.png Ui Ux Design – Teachers Night Out https://cardgames4educators.com 32 32 Masters In English How English Speaker https://cardgames4educators.com/masters-in-english-how-english-speaker/ https://cardgames4educators.com/masters-in-english-how-english-speaker/#comments Mon, 27 May 2024 08:54:45 +0000 https://themexriver.com/wp/kadu/?p=1

Erat himenaeos neque id sagittis massa. Hac suscipit pulvinar dignissim platea magnis eu. Don tellus a pharetra inceptos efficitur dui pulvinar. Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent pulvinar odio volutpat parturient. Quisque risus finibus suspendisse mus purus magnis facilisi condimentum consectetur dui. Curae elit suspendisse cursus vehicula.

Turpis taciti class non vel pretium quis pulvinar tempor lobortis nunc. Libero phasellus parturient sapien volutpat malesuada ornare. Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae. Porta est tempor ex eget feugiat vulputate ipsum. Justo nec iaculis habitant diam arcu fermentum.

We offer comprehen sive emplo ment services such as assistance wit employer compliance.Our company is your strategic HR partner as instead of HR. john smithson

Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae.

Exploring Learning Landscapes in Academic

Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent.

]]>
https://cardgames4educators.com/masters-in-english-how-english-speaker/feed/ 1