From 9ff5888a1fcd5aa218cbdab5e58c09953bd9bd8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Fri, 28 Oct 2022 14:30:34 +0200 Subject: [PATCH] Add `wp_theme_has_theme_json` as a public API to know whether a theme has a `theme.json` (#45168) --- lib/block-supports/layout.php | 4 +- lib/client-assets.php | 2 +- lib/compat/wordpress-6.0/block-patterns.php | 2 +- .../class-wp-theme-json-resolver-6-0.php | 2 +- .../get-global-styles-and-settings.php | 2 +- .../wordpress-6.1/block-editor-settings.php | 2 +- .../get-global-styles-and-settings.php | 2 +- .../wordpress-6.1/template-parts-screen.php | 2 +- lib/compat/wordpress-6.2/default-filters.php | 27 ++++ .../get-global-styles-and-settings.php | 47 +++++++ .../block-editor-settings-mobile.php | 2 +- ...class-wp-theme-json-resolver-gutenberg.php | 2 +- lib/load.php | 2 + phpunit/class-wp-theme-json-resolver-test.php | 15 +-- .../block-theme-child-no-theme-json/style.css | 8 ++ .../default-child-no-theme-json/style.css | 8 ++ phpunit/data/themedir1/default/style.css | 13 ++ phpunit/wp-theme-json-test.php | 120 ++++++++++++++++++ 18 files changed, 237 insertions(+), 25 deletions(-) create mode 100644 lib/compat/wordpress-6.2/default-filters.php create mode 100644 lib/compat/wordpress-6.2/get-global-styles-and-settings.php create mode 100644 phpunit/data/themedir1/block-theme-child-no-theme-json/style.css create mode 100644 phpunit/data/themedir1/default-child-no-theme-json/style.css create mode 100644 phpunit/data/themedir1/default/style.css create mode 100644 phpunit/wp-theme-json-test.php diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php index 0734936b2610ba..a50e1fb8837178 100644 --- a/lib/block-supports/layout.php +++ b/lib/block-supports/layout.php @@ -477,7 +477,7 @@ function gutenberg_restore_group_inner_container( $block_content, $block ) { preg_quote( $tag_name, '/' ) ); if ( - WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() || + wp_theme_has_theme_json() || 1 === preg_match( $group_with_inner_container_regex, $block_content ) || ( isset( $block['attrs']['layout']['type'] ) && 'flex' === $block['attrs']['layout']['type'] ) ) { @@ -542,7 +542,7 @@ function gutenberg_restore_image_outer_container( $block_content, $block ) { )/iUx"; if ( - WP_Theme_JSON_Resolver::theme_has_support() || + wp_theme_has_theme_json() || 0 === preg_match( $image_with_align, $block_content, $matches ) ) { return $block_content; diff --git a/lib/client-assets.php b/lib/client-assets.php index f1b94c0d46abf5..ea199750fa10b3 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -318,7 +318,7 @@ function gutenberg_register_packages_styles( $styles ) { ); // Only load the default layout and margin styles for themes without theme.json file. - if ( ! WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() ) { + if ( ! wp_theme_has_theme_json() ) { $wp_edit_blocks_dependencies[] = 'wp-editor-classic-layout-styles'; } diff --git a/lib/compat/wordpress-6.0/block-patterns.php b/lib/compat/wordpress-6.0/block-patterns.php index 6ba5a150355308..c42ec73152219a 100644 --- a/lib/compat/wordpress-6.0/block-patterns.php +++ b/lib/compat/wordpress-6.0/block-patterns.php @@ -15,7 +15,7 @@ function _register_remote_theme_patterns() { return; } - if ( ! WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() ) { + if ( ! wp_theme_has_theme_json() ) { return; } diff --git a/lib/compat/wordpress-6.0/class-wp-theme-json-resolver-6-0.php b/lib/compat/wordpress-6.0/class-wp-theme-json-resolver-6-0.php index b85e8e335037af..45779d395e6291 100644 --- a/lib/compat/wordpress-6.0/class-wp-theme-json-resolver-6-0.php +++ b/lib/compat/wordpress-6.0/class-wp-theme-json-resolver-6-0.php @@ -86,7 +86,7 @@ public static function get_theme_data( $deprecated = array(), $options = array() * and merge the static::$theme upon that. */ $theme_support_data = WP_Theme_JSON_Gutenberg::get_from_editor_settings( get_default_block_editor_settings() ); - if ( ! static::theme_has_support() ) { + if ( ! wp_theme_has_theme_json() ) { if ( ! isset( $theme_support_data['settings']['color'] ) ) { $theme_support_data['settings']['color'] = array(); } diff --git a/lib/compat/wordpress-6.0/get-global-styles-and-settings.php b/lib/compat/wordpress-6.0/get-global-styles-and-settings.php index 1dfafe9f7631d3..9ed3e891182cb5 100644 --- a/lib/compat/wordpress-6.0/get-global-styles-and-settings.php +++ b/lib/compat/wordpress-6.0/get-global-styles-and-settings.php @@ -85,7 +85,7 @@ function gutenberg_get_global_styles_svg_filters() { } } - $supports_theme_json = WP_Theme_JSON_Resolver_Gutenberg::theme_has_support(); + $supports_theme_json = wp_theme_has_theme_json(); $origins = array( 'default', 'theme', 'custom' ); if ( ! $supports_theme_json ) { diff --git a/lib/compat/wordpress-6.1/block-editor-settings.php b/lib/compat/wordpress-6.1/block-editor-settings.php index 3181329475df4f..cafe91e787dc68 100644 --- a/lib/compat/wordpress-6.1/block-editor-settings.php +++ b/lib/compat/wordpress-6.1/block-editor-settings.php @@ -68,7 +68,7 @@ function gutenberg_get_block_editor_settings( $settings ) { } } - if ( WP_Theme_JSON_Resolver::theme_has_support() ) { + if ( wp_theme_has_theme_json() ) { $block_classes = array( 'css' => 'styles', '__unstableType' => 'theme', diff --git a/lib/compat/wordpress-6.1/get-global-styles-and-settings.php b/lib/compat/wordpress-6.1/get-global-styles-and-settings.php index 1837aa04dbb20d..35c540ce1c57a6 100644 --- a/lib/compat/wordpress-6.1/get-global-styles-and-settings.php +++ b/lib/compat/wordpress-6.1/get-global-styles-and-settings.php @@ -83,7 +83,7 @@ function gutenberg_get_global_stylesheet( $types = array() ) { } } $tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data(); - $supports_theme_json = WP_Theme_JSON_Resolver_Gutenberg::theme_has_support(); + $supports_theme_json = wp_theme_has_theme_json(); if ( empty( $types ) && ! $supports_theme_json ) { $types = array( 'variables', 'presets', 'base-layout-styles' ); } elseif ( empty( $types ) ) { diff --git a/lib/compat/wordpress-6.1/template-parts-screen.php b/lib/compat/wordpress-6.1/template-parts-screen.php index d9b785100b8d99..c8b5958bedcd4d 100644 --- a/lib/compat/wordpress-6.1/template-parts-screen.php +++ b/lib/compat/wordpress-6.1/template-parts-screen.php @@ -116,7 +116,7 @@ static function( $classes ) { 'styles' => get_block_editor_theme_styles(), 'defaultTemplateTypes' => $indexed_template_types, 'defaultTemplatePartAreas' => get_allowed_block_template_part_areas(), - 'supportsLayout' => WP_Theme_JSON_Resolver::theme_has_support(), + 'supportsLayout' => wp_theme_has_theme_json(), 'supportsTemplatePartsMode' => ! wp_is_block_theme() && current_theme_supports( 'block-template-parts' ), '__unstableHomeTemplate' => gutenberg_resolve_home_template(), ); diff --git a/lib/compat/wordpress-6.2/default-filters.php b/lib/compat/wordpress-6.2/default-filters.php new file mode 100644 index 00000000000000..ac1ce19b425512 --- /dev/null +++ b/lib/compat/wordpress-6.2/default-filters.php @@ -0,0 +1,27 @@ + add_action( 'switch_theme', array( 'WP_Theme_JSON_Resolver', 'clean_cached_data' ) ); + * > add_action( 'start_previewing_theme', array( 'WP_Theme_JSON_Resolver', 'clean_cached_data' ) ); + */ +add_action( 'switch_theme', 'wp_theme_clean_theme_json_cached_data' ); +add_action( 'start_previewing_theme', 'wp_theme_clean_theme_json_cached_data' ); diff --git a/lib/compat/wordpress-6.2/get-global-styles-and-settings.php b/lib/compat/wordpress-6.2/get-global-styles-and-settings.php new file mode 100644 index 00000000000000..4dbd9d0ba8bde1 --- /dev/null +++ b/lib/compat/wordpress-6.2/get-global-styles-and-settings.php @@ -0,0 +1,47 @@ +assertFalse( $default ); - $this->assertTrue( $has_theme_json_support ); - } - public function test_add_theme_supports_are_loaded_for_themes_without_theme_json() { switch_theme( 'default' ); $color_palette = array( @@ -165,7 +152,7 @@ public function test_add_theme_supports_are_loaded_for_themes_without_theme_json remove_theme_support( 'custom-line-height' ); remove_theme_support( 'editor-color-palette' ); - $this->assertFalse( WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() ); + $this->assertFalse( wp_theme_has_theme_json() ); $this->assertTrue( $settings['typography']['lineHeight'] ); $this->assertSame( $color_palette, $settings['color']['palette']['theme'] ); } diff --git a/phpunit/data/themedir1/block-theme-child-no-theme-json/style.css b/phpunit/data/themedir1/block-theme-child-no-theme-json/style.css new file mode 100644 index 00000000000000..344441288258ec --- /dev/null +++ b/phpunit/data/themedir1/block-theme-child-no-theme-json/style.css @@ -0,0 +1,8 @@ +/* +Theme Name: Block Theme Child with no theme.json +Theme URI: https://wordpress.org/ +Description: For testing purposes only. +Template: block-theme +Version: 1.0.0 +Text Domain: block-theme-child-no-theme-json +*/ diff --git a/phpunit/data/themedir1/default-child-no-theme-json/style.css b/phpunit/data/themedir1/default-child-no-theme-json/style.css new file mode 100644 index 00000000000000..8f971990d9fec0 --- /dev/null +++ b/phpunit/data/themedir1/default-child-no-theme-json/style.css @@ -0,0 +1,8 @@ +/* +Theme Name: Default Child Theme with no theme.json +Theme URI: https://wordpress.org/ +Description: For testing purposes only. +Template: default +Version: 1.0.0 +Text Domain: default-child-no-theme-json +*/ diff --git a/phpunit/data/themedir1/default/style.css b/phpunit/data/themedir1/default/style.css new file mode 100644 index 00000000000000..e73392422dd641 --- /dev/null +++ b/phpunit/data/themedir1/default/style.css @@ -0,0 +1,13 @@ +/* +Theme Name: WordPress Default +Theme URI: http://wordpress.org/ +Description: The default WordPress theme based on the famous Kubrick. +Version: 1.6 +Author: Michael Heilemann +Author URI: http://binarybonsai.com/ + +This is just a stub to test the loading of the above metadata. +*/ + + + diff --git a/phpunit/wp-theme-json-test.php b/phpunit/wp-theme-json-test.php new file mode 100644 index 00000000000000..0d92d33faf88de --- /dev/null +++ b/phpunit/wp-theme-json-test.php @@ -0,0 +1,120 @@ +theme_root = realpath( __DIR__ . '/data/themedir1' ); + + $this->orig_theme_dir = $GLOBALS['wp_theme_directories']; + + // /themes is necessary as theme.php functions assume /themes is the root if there is only one root. + $GLOBALS['wp_theme_directories'] = array( WP_CONTENT_DIR . '/themes', $this->theme_root ); + + add_filter( 'theme_root', array( $this, 'filter_set_theme_root' ) ); + add_filter( 'stylesheet_root', array( $this, 'filter_set_theme_root' ) ); + add_filter( 'template_root', array( $this, 'filter_set_theme_root' ) ); + $this->queries = array(); + // Clear caches. + wp_clean_themes_cache(); + unset( $GLOBALS['wp_themes'] ); + } + + public function tear_down() { + $GLOBALS['wp_theme_directories'] = $this->orig_theme_dir; + wp_clean_themes_cache(); + unset( $GLOBALS['wp_themes'] ); + parent::tear_down(); + } + + public function filter_set_theme_root() { + return $this->theme_root; + } + + /** + * Test that it reports correctly themes that have a theme.json. + * + * @group theme_json + * + * @covers wp_theme_has_theme_json + */ + public function test_theme_has_theme_json() { + switch_theme( 'block-theme' ); + $this->assertTrue( wp_theme_has_theme_json() ); + } + + /** + * Test that it reports correctly themes that do not have a theme.json. + * + * @group theme_json + * + * @covers wp_theme_has_theme_json + */ + public function test_theme_has_no_theme_json() { + switch_theme( 'default' ); + $this->assertFalse( wp_theme_has_theme_json() ); + } + + /** + * Test it reports correctly child themes that have a theme.json. + * + * @group theme_json + * + * @covers wp_theme_has_theme_json + */ + public function test_child_theme_has_theme_json() { + switch_theme( 'block-theme-child' ); + $this->assertTrue( wp_theme_has_theme_json() ); + } + + /** + * Test that it reports correctly child themes that do not have a theme.json + * and the parent does. + * + * @group theme_json + * + * @covers wp_theme_has_theme_json + */ + public function test_child_theme_has_not_theme_json_but_parent_has() { + switch_theme( 'block-theme-child-no-theme-json' ); + $this->assertTrue( wp_theme_has_theme_json() ); + } + + /** + * Test that it reports correctly child themes that do not have a theme.json + * and the parent does not either. + * + * @group theme_json + * + * @covers wp_theme_has_theme_json + */ + public function test_neither_child_or_parent_themes_have_theme_json() { + switch_theme( 'default-child-no-theme-json' ); + $this->assertFalse( wp_theme_has_theme_json() ); + } + + /** + * Test that switching themes recalculates theme support. + * + * @group theme_json + * + * @covers wp_theme_has_theme_json + */ + public function test_switching_themes_recalculates_support() { + // The "default" theme doesn't have theme.json support. + switch_theme( 'default' ); + $default = wp_theme_has_theme_json(); + + // Switch to a theme that does have support. + switch_theme( 'block-theme' ); + $block_theme = wp_theme_has_theme_json(); + + $this->assertFalse( $default ); + $this->assertTrue( $block_theme ); + } +}