Skip to content

Commit 9ff5888

Browse files
authored
Add wp_theme_has_theme_json as a public API to know whether a theme has a theme.json (#45168)
1 parent 05e92d0 commit 9ff5888

18 files changed

+237
-25
lines changed

lib/block-supports/layout.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ function gutenberg_restore_group_inner_container( $block_content, $block ) {
477477
preg_quote( $tag_name, '/' )
478478
);
479479
if (
480-
WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() ||
480+
wp_theme_has_theme_json() ||
481481
1 === preg_match( $group_with_inner_container_regex, $block_content ) ||
482482
( isset( $block['attrs']['layout']['type'] ) && 'flex' === $block['attrs']['layout']['type'] )
483483
) {
@@ -542,7 +542,7 @@ function gutenberg_restore_image_outer_container( $block_content, $block ) {
542542
)/iUx";
543543

544544
if (
545-
WP_Theme_JSON_Resolver::theme_has_support() ||
545+
wp_theme_has_theme_json() ||
546546
0 === preg_match( $image_with_align, $block_content, $matches )
547547
) {
548548
return $block_content;

lib/client-assets.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ function gutenberg_register_packages_styles( $styles ) {
318318
);
319319

320320
// Only load the default layout and margin styles for themes without theme.json file.
321-
if ( ! WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() ) {
321+
if ( ! wp_theme_has_theme_json() ) {
322322
$wp_edit_blocks_dependencies[] = 'wp-editor-classic-layout-styles';
323323
}
324324

lib/compat/wordpress-6.0/block-patterns.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ function _register_remote_theme_patterns() {
1515
return;
1616
}
1717

18-
if ( ! WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() ) {
18+
if ( ! wp_theme_has_theme_json() ) {
1919
return;
2020
}
2121

lib/compat/wordpress-6.0/class-wp-theme-json-resolver-6-0.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ public static function get_theme_data( $deprecated = array(), $options = array()
8686
* and merge the static::$theme upon that.
8787
*/
8888
$theme_support_data = WP_Theme_JSON_Gutenberg::get_from_editor_settings( get_default_block_editor_settings() );
89-
if ( ! static::theme_has_support() ) {
89+
if ( ! wp_theme_has_theme_json() ) {
9090
if ( ! isset( $theme_support_data['settings']['color'] ) ) {
9191
$theme_support_data['settings']['color'] = array();
9292
}

lib/compat/wordpress-6.0/get-global-styles-and-settings.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ function gutenberg_get_global_styles_svg_filters() {
8585
}
8686
}
8787

88-
$supports_theme_json = WP_Theme_JSON_Resolver_Gutenberg::theme_has_support();
88+
$supports_theme_json = wp_theme_has_theme_json();
8989

9090
$origins = array( 'default', 'theme', 'custom' );
9191
if ( ! $supports_theme_json ) {

lib/compat/wordpress-6.1/block-editor-settings.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ function gutenberg_get_block_editor_settings( $settings ) {
6868
}
6969
}
7070

71-
if ( WP_Theme_JSON_Resolver::theme_has_support() ) {
71+
if ( wp_theme_has_theme_json() ) {
7272
$block_classes = array(
7373
'css' => 'styles',
7474
'__unstableType' => 'theme',

lib/compat/wordpress-6.1/get-global-styles-and-settings.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ function gutenberg_get_global_stylesheet( $types = array() ) {
8383
}
8484
}
8585
$tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data();
86-
$supports_theme_json = WP_Theme_JSON_Resolver_Gutenberg::theme_has_support();
86+
$supports_theme_json = wp_theme_has_theme_json();
8787
if ( empty( $types ) && ! $supports_theme_json ) {
8888
$types = array( 'variables', 'presets', 'base-layout-styles' );
8989
} elseif ( empty( $types ) ) {

lib/compat/wordpress-6.1/template-parts-screen.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ static function( $classes ) {
116116
'styles' => get_block_editor_theme_styles(),
117117
'defaultTemplateTypes' => $indexed_template_types,
118118
'defaultTemplatePartAreas' => get_allowed_block_template_part_areas(),
119-
'supportsLayout' => WP_Theme_JSON_Resolver::theme_has_support(),
119+
'supportsLayout' => wp_theme_has_theme_json(),
120120
'supportsTemplatePartsMode' => ! wp_is_block_theme() && current_theme_supports( 'block-template-parts' ),
121121
'__unstableHomeTemplate' => gutenberg_resolve_home_template(),
122122
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
/**
3+
* Sets up the default filters and actions for most
4+
* of the WordPress hooks.
5+
*
6+
* If you need to remove a default hook, this file will
7+
* give you the priority to use for removing the hook.
8+
*
9+
* Not all of the default hooks are found in this file.
10+
* For instance, administration-related hooks are located in
11+
* wp-admin/includes/admin-filters.php.
12+
*
13+
* If a hook should only be called from a specific context
14+
* (admin area, multisite environment…), please move it
15+
* to a more appropriate file instead.
16+
*
17+
* @package gutenberg
18+
*/
19+
20+
/**
21+
* Note for backport: we should also remove the existing filters:
22+
*
23+
* > add_action( 'switch_theme', array( 'WP_Theme_JSON_Resolver', 'clean_cached_data' ) );
24+
* > add_action( 'start_previewing_theme', array( 'WP_Theme_JSON_Resolver', 'clean_cached_data' ) );
25+
*/
26+
add_action( 'switch_theme', 'wp_theme_clean_theme_json_cached_data' );
27+
add_action( 'start_previewing_theme', 'wp_theme_clean_theme_json_cached_data' );
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
/**
3+
* API to interact with global settings & styles.
4+
*
5+
* @package gutenberg
6+
*/
7+
8+
if ( ! function_exists( 'wp_theme_has_theme_json' ) ) {
9+
/**
10+
* Whether a theme or its parent have a theme.json file.
11+
*
12+
* @param boolean $clear_cache Whether the cache should be cleared and theme support recomputed. Default is false.
13+
*
14+
* @return boolean
15+
*/
16+
function wp_theme_has_theme_json( $clear_cache = false ) {
17+
static $theme_has_support = null;
18+
19+
if ( true === $clear_cache ) {
20+
$theme_has_support = null;
21+
}
22+
23+
if ( null !== $theme_has_support ) {
24+
return $theme_has_support;
25+
}
26+
27+
// Has the own theme a theme.json?
28+
$theme_has_support = is_readable( get_stylesheet_directory() . '/theme.json' );
29+
30+
// Look up the parent if the child does not have a theme.json.
31+
if ( ! $theme_has_support ) {
32+
$theme_has_support = is_readable( get_template_directory() . '/theme.json' );
33+
}
34+
35+
return $theme_has_support;
36+
}
37+
}
38+
39+
if ( ! function_exists( 'wp_theme_clean_theme_json_cached_data' ) ) {
40+
/**
41+
* Clean theme.json related cached data.
42+
*/
43+
function wp_theme_clean_theme_json_cached_data() {
44+
wp_theme_has_theme_json( true );
45+
WP_Theme_JSON_Resolver_Gutenberg::clean_cached_data();
46+
}
47+
}

lib/experimental/block-editor-settings-mobile.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ function gutenberg_get_block_editor_settings_mobile( $settings ) {
2222
isset( $_GET['context'] ) &&
2323
'mobile' === $_GET['context']
2424
) {
25-
if ( WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() ) {
25+
if ( wp_theme_has_theme_json() ) {
2626
$settings['__experimentalStyles'] = gutenberg_get_global_styles();
2727
}
2828

lib/experimental/class-wp-theme-json-resolver-gutenberg.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public static function get_theme_data( $deprecated = array(), $settings = array(
7373
* and merge the static::$theme upon that.
7474
*/
7575
$theme_support_data = WP_Theme_JSON_Gutenberg::get_from_editor_settings( get_default_block_editor_settings() );
76-
if ( ! static::theme_has_support() ) {
76+
if ( ! wp_theme_has_theme_json() ) {
7777
if ( ! isset( $theme_support_data['settings']['color'] ) ) {
7878
$theme_support_data['settings']['color'] = array();
7979
}

lib/load.php

+2
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ function gutenberg_is_experiment_enabled( $name ) {
8888
require __DIR__ . '/compat/wordpress-6.1/block-editor-settings.php';
8989
require __DIR__ . '/compat/wordpress-6.1/persisted-preferences.php';
9090
require __DIR__ . '/compat/wordpress-6.1/get-global-styles-and-settings.php';
91+
require __DIR__ . '/compat/wordpress-6.2/get-global-styles-and-settings.php';
92+
require __DIR__ . '/compat/wordpress-6.2/default-filters.php';
9193
require __DIR__ . '/compat/wordpress-6.1/class-wp-theme-json-data-gutenberg.php';
9294
require __DIR__ . '/compat/wordpress-6.1/class-wp-theme-json-6-1.php';
9395
require __DIR__ . '/compat/wordpress-6.1/class-wp-theme-json-resolver-6-1.php';

phpunit/class-wp-theme-json-resolver-test.php

+1-14
Original file line numberDiff line numberDiff line change
@@ -125,19 +125,6 @@ public function test_translations_are_applied() {
125125
);
126126
}
127127

128-
public function test_switching_themes_recalculates_data() {
129-
// The "default" theme doesn't have theme.json support.
130-
switch_theme( 'default' );
131-
$default = WP_Theme_JSON_Resolver_Gutenberg::theme_has_support();
132-
133-
// Switch to a theme that does have support.
134-
switch_theme( 'block-theme' );
135-
$has_theme_json_support = WP_Theme_JSON_Resolver_Gutenberg::theme_has_support();
136-
137-
$this->assertFalse( $default );
138-
$this->assertTrue( $has_theme_json_support );
139-
}
140-
141128
public function test_add_theme_supports_are_loaded_for_themes_without_theme_json() {
142129
switch_theme( 'default' );
143130
$color_palette = array(
@@ -165,7 +152,7 @@ public function test_add_theme_supports_are_loaded_for_themes_without_theme_json
165152
remove_theme_support( 'custom-line-height' );
166153
remove_theme_support( 'editor-color-palette' );
167154

168-
$this->assertFalse( WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() );
155+
$this->assertFalse( wp_theme_has_theme_json() );
169156
$this->assertTrue( $settings['typography']['lineHeight'] );
170157
$this->assertSame( $color_palette, $settings['color']['palette']['theme'] );
171158
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/*
2+
Theme Name: Block Theme Child with no theme.json
3+
Theme URI: https://wordpress.org/
4+
Description: For testing purposes only.
5+
Template: block-theme
6+
Version: 1.0.0
7+
Text Domain: block-theme-child-no-theme-json
8+
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/*
2+
Theme Name: Default Child Theme with no theme.json
3+
Theme URI: https://wordpress.org/
4+
Description: For testing purposes only.
5+
Template: default
6+
Version: 1.0.0
7+
Text Domain: default-child-no-theme-json
8+
*/
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
Theme Name: WordPress Default
3+
Theme URI: http://wordpress.org/
4+
Description: The default WordPress theme based on the famous <a href="http://binarybonsai.com/kubrick/">Kubrick</a>.
5+
Version: 1.6
6+
Author: Michael Heilemann
7+
Author URI: http://binarybonsai.com/
8+
9+
This is just a stub to test the loading of the above metadata.
10+
*/
11+
12+
13+

phpunit/wp-theme-json-test.php

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
<?php
2+
/**
3+
* Tests theme.json related public APIs.
4+
*
5+
* @package Gutenberg
6+
*/
7+
8+
class WP_Theme_Json_Test extends WP_UnitTestCase {
9+
10+
public function set_up() {
11+
parent::set_up();
12+
$this->theme_root = realpath( __DIR__ . '/data/themedir1' );
13+
14+
$this->orig_theme_dir = $GLOBALS['wp_theme_directories'];
15+
16+
// /themes is necessary as theme.php functions assume /themes is the root if there is only one root.
17+
$GLOBALS['wp_theme_directories'] = array( WP_CONTENT_DIR . '/themes', $this->theme_root );
18+
19+
add_filter( 'theme_root', array( $this, 'filter_set_theme_root' ) );
20+
add_filter( 'stylesheet_root', array( $this, 'filter_set_theme_root' ) );
21+
add_filter( 'template_root', array( $this, 'filter_set_theme_root' ) );
22+
$this->queries = array();
23+
// Clear caches.
24+
wp_clean_themes_cache();
25+
unset( $GLOBALS['wp_themes'] );
26+
}
27+
28+
public function tear_down() {
29+
$GLOBALS['wp_theme_directories'] = $this->orig_theme_dir;
30+
wp_clean_themes_cache();
31+
unset( $GLOBALS['wp_themes'] );
32+
parent::tear_down();
33+
}
34+
35+
public function filter_set_theme_root() {
36+
return $this->theme_root;
37+
}
38+
39+
/**
40+
* Test that it reports correctly themes that have a theme.json.
41+
*
42+
* @group theme_json
43+
*
44+
* @covers wp_theme_has_theme_json
45+
*/
46+
public function test_theme_has_theme_json() {
47+
switch_theme( 'block-theme' );
48+
$this->assertTrue( wp_theme_has_theme_json() );
49+
}
50+
51+
/**
52+
* Test that it reports correctly themes that do not have a theme.json.
53+
*
54+
* @group theme_json
55+
*
56+
* @covers wp_theme_has_theme_json
57+
*/
58+
public function test_theme_has_no_theme_json() {
59+
switch_theme( 'default' );
60+
$this->assertFalse( wp_theme_has_theme_json() );
61+
}
62+
63+
/**
64+
* Test it reports correctly child themes that have a theme.json.
65+
*
66+
* @group theme_json
67+
*
68+
* @covers wp_theme_has_theme_json
69+
*/
70+
public function test_child_theme_has_theme_json() {
71+
switch_theme( 'block-theme-child' );
72+
$this->assertTrue( wp_theme_has_theme_json() );
73+
}
74+
75+
/**
76+
* Test that it reports correctly child themes that do not have a theme.json
77+
* and the parent does.
78+
*
79+
* @group theme_json
80+
*
81+
* @covers wp_theme_has_theme_json
82+
*/
83+
public function test_child_theme_has_not_theme_json_but_parent_has() {
84+
switch_theme( 'block-theme-child-no-theme-json' );
85+
$this->assertTrue( wp_theme_has_theme_json() );
86+
}
87+
88+
/**
89+
* Test that it reports correctly child themes that do not have a theme.json
90+
* and the parent does not either.
91+
*
92+
* @group theme_json
93+
*
94+
* @covers wp_theme_has_theme_json
95+
*/
96+
public function test_neither_child_or_parent_themes_have_theme_json() {
97+
switch_theme( 'default-child-no-theme-json' );
98+
$this->assertFalse( wp_theme_has_theme_json() );
99+
}
100+
101+
/**
102+
* Test that switching themes recalculates theme support.
103+
*
104+
* @group theme_json
105+
*
106+
* @covers wp_theme_has_theme_json
107+
*/
108+
public function test_switching_themes_recalculates_support() {
109+
// The "default" theme doesn't have theme.json support.
110+
switch_theme( 'default' );
111+
$default = wp_theme_has_theme_json();
112+
113+
// Switch to a theme that does have support.
114+
switch_theme( 'block-theme' );
115+
$block_theme = wp_theme_has_theme_json();
116+
117+
$this->assertFalse( $default );
118+
$this->assertTrue( $block_theme );
119+
}
120+
}

0 commit comments

Comments
 (0)