Skip to content

Commit d346653

Browse files
committed
Themes: Introduce wp_theme_has_theme_json() for public consumption.
Adds `wp_theme_has_theme_json()` for public consumption, to replace the private internal Core-only `WP_Theme_JSON_Resolver::theme_has_support()` method. This new global function checks if a theme or its parent has a `theme.json` file. For performance, results are cached as an integer `1` or `0` in the `'theme_json'` group with `'wp_theme_has_theme_json'` key. This is a non-persistent cache. Why? To make the derived data from `theme.json` is always fresh from the potential modifications done via hooks that can use dynamic data (modify the stylesheet depending on some option, settings depending on user permissions, etc.). Also adds a new public function `wp_clean_theme_json_cache()` to clear the cache on `'switch_theme'` and `start_previewing_theme'`. References: * [WordPress/gutenberg#45168 Gutenberg PR 45168] Add `wp_theme_has_theme_json` as a public API to know whether a theme has a `theme.json`. * [WordPress/gutenberg#45380 Gutenberg PR 45380] Deprecate `WP_Theme_JSON_Resolver:theme_has_support()`. * [WordPress/gutenberg#46150 Gutenberg PR 46150] Make `theme.json` object caches non-persistent. * [WordPress/gutenberg#45979 Gutenberg PR 45979] Don't check if constants set by `wp_initial_constants()` are defined. * [WordPress/gutenberg#45950 Gutenberg PR 45950] Cleaner logic in `wp_theme_has_theme_json`. Follow-up to [54493], [53282], [52744], [52049], [50959]. Props oandregal, afragen, alexstine, aristath, azaozz, costdev, flixos90, hellofromTonya, mamaduka, mcsf, ocean90, spacedmonkey. Fixes #56975. Built from https://develop.svn.wordpress.org/trunk@55086 git-svn-id: http://core.svn.wordpress.org/trunk@54619 1a063a9b-81f0-0310-95a4-ce76da25c4cd
1 parent 88848eb commit d346653

14 files changed

+95
-39
lines changed

wp-admin/edit-form-blocks.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ static function( $classes ) {
203203
'unlockNonce' => wp_create_nonce( 'update-post_' . $post->ID ),
204204
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
205205
),
206-
'supportsLayout' => WP_Theme_JSON_Resolver::theme_has_support(),
206+
'supportsLayout' => wp_theme_has_theme_json(),
207207
'supportsTemplateMode' => current_theme_supports( 'block-templates' ),
208208

209209
// Whether or not to load the 'postcustom' meta box is stored as a user meta

wp-admin/site-editor.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ static function( $classes ) {
7474
'styles' => get_block_editor_theme_styles(),
7575
'defaultTemplateTypes' => $indexed_template_types,
7676
'defaultTemplatePartAreas' => get_allowed_block_template_part_areas(),
77-
'supportsLayout' => WP_Theme_JSON_Resolver::theme_has_support(),
77+
'supportsLayout' => wp_theme_has_theme_json(),
7878
'supportsTemplatePartsMode' => ! wp_is_block_theme() && current_theme_supports( 'block-template-parts' ),
7979
'__unstableHomeTemplate' => $home_template,
8080
);

wp-includes/block-editor.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ function get_block_editor_settings( array $custom_settings, $block_editor_contex
417417
}
418418
}
419419

420-
if ( WP_Theme_JSON_Resolver::theme_has_support() ) {
420+
if ( wp_theme_has_theme_json() ) {
421421
$block_classes = array(
422422
'css' => 'styles',
423423
'__unstableType' => 'theme',

wp-includes/block-patterns.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ function _register_remote_theme_patterns() {
139139
return;
140140
}
141141

142-
if ( ! WP_Theme_JSON_Resolver::theme_has_support() ) {
142+
if ( ! wp_theme_has_theme_json() ) {
143143
return;
144144
}
145145

wp-includes/block-supports/layout.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ function wp_restore_group_inner_container( $block_content, $block ) {
464464
);
465465

466466
if (
467-
WP_Theme_JSON_Resolver::theme_has_support() ||
467+
wp_theme_has_theme_json() ||
468468
1 === preg_match( $group_with_inner_container_regex, $block_content ) ||
469469
( isset( $block['attrs']['layout']['type'] ) && 'flex' === $block['attrs']['layout']['type'] )
470470
) {
@@ -527,7 +527,7 @@ function wp_restore_image_outer_container( $block_content, $block ) {
527527
)/iUx";
528528

529529
if (
530-
WP_Theme_JSON_Resolver::theme_has_support() ||
530+
wp_theme_has_theme_json() ||
531531
0 === preg_match( $image_with_align, $block_content, $matches )
532532
) {
533533
return $block_content;

wp-includes/block-template-utils.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ function _get_block_templates_files( $template_type ) {
347347
* @return array Template item.
348348
*/
349349
function _add_block_template_info( $template_item ) {
350-
if ( ! WP_Theme_JSON_Resolver::theme_has_support() ) {
350+
if ( ! wp_theme_has_theme_json() ) {
351351
return $template_item;
352352
}
353353

@@ -370,7 +370,7 @@ function _add_block_template_info( $template_item ) {
370370
* @return array Template info.
371371
*/
372372
function _add_block_template_part_area_info( $template_info ) {
373-
if ( WP_Theme_JSON_Resolver::theme_has_support() ) {
373+
if ( wp_theme_has_theme_json() ) {
374374
$theme_data = WP_Theme_JSON_Resolver::get_theme_data( array(), array( 'with_supports' => false ) )->get_template_parts();
375375
}
376376

wp-includes/class-wp-theme-json-resolver.php

+6-19
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,6 @@ class WP_Theme_JSON_Resolver {
5757
*/
5858
protected static $theme = null;
5959

60-
/**
61-
* Whether or not the theme supports theme.json.
62-
*
63-
* @since 5.8.0
64-
* @var bool
65-
*/
66-
protected static $theme_has_support = null;
67-
6860
/**
6961
* Container for data coming from the user.
7062
*
@@ -295,7 +287,7 @@ public static function get_theme_data( $deprecated = array(), $options = array()
295287
* and merge the static::$theme upon that.
296288
*/
297289
$theme_support_data = WP_Theme_JSON::get_from_editor_settings( get_default_block_editor_settings() );
298-
if ( ! static::theme_has_support() ) {
290+
if ( ! wp_theme_has_theme_json() ) {
299291
if ( ! isset( $theme_support_data['settings']['color'] ) ) {
300292
$theme_support_data['settings']['color'] = array();
301293
}
@@ -421,11 +413,11 @@ public static function get_user_data_from_wp_global_styles( $theme, $create_post
421413
/*
422414
* Bail early if the theme does not support a theme.json.
423415
*
424-
* Since WP_Theme_JSON_Resolver::theme_has_support() only supports the active
416+
* Since wp_theme_has_theme_json() only supports the active
425417
* theme, the extra condition for whether $theme is the active theme is
426418
* present here.
427419
*/
428-
if ( $theme->get_stylesheet() === get_stylesheet() && ! static::theme_has_support() ) {
420+
if ( $theme->get_stylesheet() === get_stylesheet() && ! wp_theme_has_theme_json() ) {
429421
return array();
430422
}
431423

@@ -602,18 +594,14 @@ public static function get_user_global_styles_post_id() {
602594
*
603595
* @since 5.8.0
604596
* @since 5.9.0 Added a check in the parent theme.
597+
* @deprecated 6.2.0 Use wp_theme_has_theme_json() instead.
605598
*
606599
* @return bool
607600
*/
608601
public static function theme_has_support() {
609-
if ( ! isset( static::$theme_has_support ) ) {
610-
static::$theme_has_support = (
611-
static::get_file_path_from_theme( 'theme.json' ) !== '' ||
612-
static::get_file_path_from_theme( 'theme.json', true ) !== ''
613-
);
614-
}
602+
_deprecated_function( __METHOD__, '6.2.0', 'wp_theme_has_theme_json()' );
615603

616-
return static::$theme_has_support;
604+
return wp_theme_has_theme_json();
617605
}
618606

619607
/**
@@ -656,7 +644,6 @@ public static function clean_cached_data() {
656644
static::$theme = null;
657645
static::$user = null;
658646
static::$user_custom_post_type_id = null;
659-
static::$theme_has_support = null;
660647
static::$i18n_schema = null;
661648
}
662649

wp-includes/default-filters.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -346,8 +346,8 @@
346346
add_action( 'init', '_register_core_block_patterns_and_categories' );
347347
add_action( 'init', 'check_theme_switched', 99 );
348348
add_action( 'init', array( 'WP_Block_Supports', 'init' ), 22 );
349-
add_action( 'switch_theme', array( 'WP_Theme_JSON_Resolver', 'clean_cached_data' ) );
350-
add_action( 'start_previewing_theme', array( 'WP_Theme_JSON_Resolver', 'clean_cached_data' ) );
349+
add_action( 'switch_theme', 'wp_clean_theme_json_cache' );
350+
add_action( 'start_previewing_theme', 'wp_clean_theme_json_cache' );
351351
add_action( 'after_switch_theme', '_wp_menus_changed' );
352352
add_action( 'after_switch_theme', '_wp_sidebars_changed' );
353353
add_action( 'wp_print_styles', 'print_emoji_styles' );

wp-includes/global-styles-and-settings.php

+71-2
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ function wp_get_global_stylesheet( $types = array() ) {
102102

103103
$tree = WP_Theme_JSON_Resolver::get_merged_data();
104104

105-
$supports_theme_json = WP_Theme_JSON_Resolver::theme_has_support();
105+
$supports_theme_json = wp_theme_has_theme_json();
106106
if ( empty( $types ) && ! $supports_theme_json ) {
107107
$types = array( 'variables', 'presets', 'base-layout-styles' );
108108
} elseif ( empty( $types ) ) {
@@ -184,7 +184,7 @@ function wp_get_global_styles_svg_filters() {
184184
}
185185
}
186186

187-
$supports_theme_json = WP_Theme_JSON_Resolver::theme_has_support();
187+
$supports_theme_json = wp_theme_has_theme_json();
188188

189189
$origins = array( 'default', 'theme', 'custom' );
190190
if ( ! $supports_theme_json ) {
@@ -255,3 +255,72 @@ function ( $item ) {
255255
}
256256
}
257257
}
258+
259+
/**
260+
* Checks whether a theme or its parent has a theme.json file.
261+
*
262+
* @since 6.2.0
263+
*
264+
* @return bool Returns true if theme or its parent has a theme.json file, false otherwise.
265+
*/
266+
function wp_theme_has_theme_json() {
267+
/*
268+
* By using the 'theme_json' group, this data is marked to be non-persistent across requests.
269+
* @see `wp_cache_add_non_persistent_groups()`.
270+
*
271+
* The rationale for this is to make sure derived data from theme.json
272+
* is always fresh from the potential modifications done via hooks
273+
* that can use dynamic data (modify the stylesheet depending on some option,
274+
* settings depending on user permissions, etc.).
275+
* For some of the existing hooks to modify theme.json behavior:
276+
* @see https://make.wordpress.org/core/2022/10/10/filters-for-theme-json-data/
277+
*
278+
* A different alternative considered was to invalidate the cache upon certain
279+
* events such as options add/update/delete, user meta, etc.
280+
* It was judged not enough, hence this approach.
281+
* @see https://github.com/WordPress/gutenberg/pull/45372
282+
*/
283+
$cache_group = 'theme_json';
284+
$cache_key = 'wp_theme_has_theme_json';
285+
$theme_has_support = wp_cache_get( $cache_key, $cache_group );
286+
287+
/*
288+
* $theme_has_support is stored as an int in the cache.
289+
*
290+
* The reason not to store it as a boolean is to avoid working
291+
* with the $found parameter which apparently had some issues in some implementations
292+
* @see https://developer.wordpress.org/reference/functions/wp_cache_get/
293+
*
294+
* Ignore cache when `WP_DEBUG` is enabled, so it doesn't interfere with the theme
295+
* developer's workflow.
296+
*
297+
* @todo Replace `WP_DEBUG` once an "in development mode" check is available in Core.
298+
*/
299+
if ( ! WP_DEBUG && is_int( $theme_has_support ) ) {
300+
return (bool) $theme_has_support;
301+
}
302+
303+
// Does the theme have its own theme.json?
304+
$theme_has_support = is_readable( get_stylesheet_directory() . '/theme.json' );
305+
306+
// Look up the parent if the child does not have a theme.json.
307+
if ( ! $theme_has_support ) {
308+
$theme_has_support = is_readable( get_template_directory() . '/theme.json' );
309+
}
310+
311+
$theme_has_support = $theme_has_support ? 1 : 0;
312+
313+
wp_cache_set( $cache_key, $theme_has_support, $cache_group );
314+
315+
return (bool) $theme_has_support;
316+
}
317+
318+
/**
319+
* Cleans the caches under the theme_json group.
320+
*
321+
* @since 6.2.0
322+
*/
323+
function wp_clean_theme_json_cache() {
324+
wp_cache_delete( 'wp_theme_has_theme_json', 'theme_json' );
325+
WP_Theme_JSON_Resolver::clean_cached_data();
326+
}

wp-includes/load.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,7 @@ function wp_start_object_cache() {
753753
)
754754
);
755755

756-
wp_cache_add_non_persistent_groups( array( 'counts', 'plugins' ) );
756+
wp_cache_add_non_persistent_groups( array( 'counts', 'plugins', 'theme_json' ) );
757757
}
758758

759759
$first_init = false;

wp-includes/ms-blogs.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ function switch_to_blog( $new_blog_id, $deprecated = null ) {
575575
);
576576
}
577577

578-
wp_cache_add_non_persistent_groups( array( 'counts', 'plugins' ) );
578+
wp_cache_add_non_persistent_groups( array( 'counts', 'plugins', 'theme_json' ) );
579579
}
580580
}
581581

@@ -666,7 +666,7 @@ function restore_current_blog() {
666666
);
667667
}
668668

669-
wp_cache_add_non_persistent_groups( array( 'counts', 'plugins' ) );
669+
wp_cache_add_non_persistent_groups( array( 'counts', 'plugins', 'theme_json' ) );
670670
}
671671
}
672672

wp-includes/script-loader.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -1620,7 +1620,7 @@ function wp_default_styles( $styles ) {
16201620
);
16211621

16221622
// Only load the default layout and margin styles for themes without theme.json file.
1623-
if ( ! WP_Theme_JSON_Resolver::theme_has_support() ) {
1623+
if ( ! wp_theme_has_theme_json() ) {
16241624
$wp_edit_blocks_dependencies[] = 'wp-editor-classic-layout-styles';
16251625
}
16261626

@@ -3667,7 +3667,7 @@ function _wp_theme_json_webfonts_handler() {
36673667
* @since 6.1.0
36683668
*/
36693669
function wp_enqueue_classic_theme_styles() {
3670-
if ( ! WP_Theme_JSON_Resolver::theme_has_support() ) {
3670+
if ( ! wp_theme_has_theme_json() ) {
36713671
$suffix = wp_scripts_get_suffix();
36723672
wp_register_style( 'classic-theme-styles', '/' . WPINC . "/css/classic-themes$suffix.css", array(), true );
36733673
wp_enqueue_style( 'classic-theme-styles' );
@@ -3685,7 +3685,7 @@ function wp_enqueue_classic_theme_styles() {
36853685
* @return array A filtered array of editor settings.
36863686
*/
36873687
function wp_add_editor_classic_theme_styles( $editor_settings ) {
3688-
if ( WP_Theme_JSON_Resolver::theme_has_support() ) {
3688+
if ( wp_theme_has_theme_json() ) {
36893689
return $editor_settings;
36903690
}
36913691

wp-includes/theme-templates.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ function the_block_template_skip_link() {
209209
* @since 5.8.0
210210
*/
211211
function wp_enable_block_templates() {
212-
if ( wp_is_block_theme() || WP_Theme_JSON_Resolver::theme_has_support() ) {
212+
if ( wp_is_block_theme() || wp_theme_has_theme_json() ) {
213213
add_theme_support( 'block-templates' );
214214
}
215215
}

wp-includes/version.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*
1717
* @global string $wp_version
1818
*/
19-
$wp_version = '6.2-alpha-55085';
19+
$wp_version = '6.2-alpha-55086';
2020

2121
/**
2222
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.

0 commit comments

Comments
 (0)