From b7aa3a09bc4effc006c82d308f93f1641936eaba Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Fri, 4 Feb 2022 13:50:34 +0000 Subject: [PATCH] Fix: Classic themes using default presets are not working. This commit makes the presets provided by the theme via add_theme_support always create CSS Custom Properties, whether or not the theme has a theme.json file. This way, if the overwrites a core preset, the core CSS variables are also overwritten and use the theme value. Props oandregal, hellofromTonya, desrosj, costdev, pbearne, johnstonphilip, webmandesign. Fixes #54782. git-svn-id: https://develop.svn.wordpress.org/trunk@52675 602fd350-edb4-49c9-b593-d223f7449a82 --- .../global-styles-and-settings.php | 36 ++-- .../phpunit/tests/theme/globalStylesheet.php | 186 ++++++++++++++++++ 2 files changed, 211 insertions(+), 11 deletions(-) create mode 100644 tests/phpunit/tests/theme/globalStylesheet.php diff --git a/src/wp-includes/global-styles-and-settings.php b/src/wp-includes/global-styles-and-settings.php index 9db95a3e95..f8cd905fdc 100644 --- a/src/wp-includes/global-styles-and-settings.php +++ b/src/wp-includes/global-styles-and-settings.php @@ -103,26 +103,40 @@ function wp_get_global_stylesheet( $types = array() ) { } } + $tree = WP_Theme_JSON_Resolver::get_merged_data(); + $supports_theme_json = WP_Theme_JSON_Resolver::theme_has_support(); - $supports_link_color = get_theme_support( 'experimental-link-color' ); if ( empty( $types ) && ! $supports_theme_json ) { $types = array( 'variables', 'presets' ); } elseif ( empty( $types ) ) { $types = array( 'variables', 'styles', 'presets' ); } - $origins = array( 'default', 'theme', 'custom' ); - if ( ! $supports_theme_json && ! $supports_link_color ) { - // In this case we only enqueue the core presets (CSS Custom Properties + the classes). - $origins = array( 'default' ); - } elseif ( ! $supports_theme_json && $supports_link_color ) { - // For the legacy link color feature to work, the CSS Custom Properties - // should be in scope (either the core or the theme ones). - $origins = array( 'default', 'theme' ); + // If variables are part of the stylesheet, + // we add them for all origins (default, theme, user). + // This is so themes without a theme.json still work as before 5.9: + // they can override the default presets. + // See https://core.trac.wordpress.org/ticket/54782 + $styles_variables = ''; + if ( in_array( 'variables', $types ) ) { + $styles_variables = $tree->get_stylesheet( array( 'variables' ) ); + $types = array_diff( $types, array( 'variables' ) ); } - $tree = WP_Theme_JSON_Resolver::get_merged_data(); - $stylesheet = $tree->get_stylesheet( $types, $origins ); + // For the remaining types (presets, styles), we do consider origins: + // + // - themes without theme.json: only the classes for the presets defined by core + // - themes with theme.json: the presets and styles classes, both from core and the theme + $styles_rest = ''; + if ( ! empty( $types ) ) { + $origins = array( 'default', 'theme', 'custom' ); + if ( ! $supports_theme_json ) { + $origins = array( 'default' ); + } + $styles_rest = $tree->get_stylesheet( $types, $origins ); + } + + $stylesheet = $styles_variables . $styles_rest; if ( $can_use_cached ) { // Cache for a minute. diff --git a/tests/phpunit/tests/theme/globalStylesheet.php b/tests/phpunit/tests/theme/globalStylesheet.php new file mode 100644 index 0000000000..35bb561ae7 --- /dev/null +++ b/tests/phpunit/tests/theme/globalStylesheet.php @@ -0,0 +1,186 @@ +orig_theme_dir = $GLOBALS['wp_theme_directories']; + $this->theme_root = realpath( DIR_TESTDATA . '/themedir1' ); + + // /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 ); + + // Set up the new 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' ) ); + + // Clear caches. + wp_clean_themes_cache(); + unset( $GLOBALS['wp_themes'] ); + } + + public function tear_down() { + $GLOBALS['wp_theme_directories'] = $this->orig_theme_dir; + + // Clear up the filters to modify the theme root. + remove_filter( 'theme_root', array( $this, 'filter_set_theme_root' ) ); + remove_filter( 'stylesheet_root', array( $this, 'filter_set_theme_root' ) ); + remove_filter( 'template_root', array( $this, 'filter_set_theme_root' ) ); + + wp_clean_themes_cache(); + unset( $GLOBALS['wp_themes'] ); + + parent::tear_down(); + } + + public function filter_set_theme_root() { + return $this->theme_root; + } + + public function test_block_theme_using_variables() { + switch_theme( 'block-theme' ); + + $styles = wp_get_global_stylesheet( array( 'variables' ) ); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--small: 13px' ), 'small font size is 13px' ); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--medium: 20px' ), 'medium font size is 20px' ); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--large: 36px' ), 'large font size is 36px' ); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--x-large: 42px' ), 'x-large font size is 42px' ); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--custom: 100px;' ), 'custom font size is 100px' ); + + switch_theme( WP_DEFAULT_THEME ); + } + + public function test_block_theme_using_presets() { + switch_theme( 'block-theme' ); + + $styles = wp_get_global_stylesheet( array( 'presets' ) ); + $this->assertFalse( str_contains( $styles, '--wp--preset--font-size--small: 13px' ), 'small font size is not present' ); + $this->assertFalse( str_contains( $styles, '--wp--preset--font-size--medium: 20px' ), 'medium font size is not present' ); + $this->assertFalse( str_contains( $styles, '--wp--preset--font-size--large: 36px' ), 'large font size is not present' ); + $this->assertFalse( str_contains( $styles, '--wp--preset--font-size--x-large: 42px' ), 'x-large font size is not present' ); + $this->assertFalse( str_contains( $styles, '--wp--preset--font-size--custom: 100px;' ), 'custom font size is not present' ); + + switch_theme( WP_DEFAULT_THEME ); + } + + public function test_block_theme_using_defaults() { + switch_theme( 'block-theme' ); + + $styles = wp_get_global_stylesheet(); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--small: 13px' ), 'small font size is 13px' ); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--medium: 20px' ), 'medium font size is 20px' ); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--large: 36px' ), 'large font size is 36px' ); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--x-large: 42px' ), 'x-large font size is 42px' ); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--custom: 100px;' ), 'custom font size is 100px' ); + + switch_theme( WP_DEFAULT_THEME ); + } + + public function test_variables_in_classic_theme_with_no_presets_using_variables() { + $styles = wp_get_global_stylesheet( array( 'variables' ) ); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--small: 13px' ), 'small font size is 13px' ); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--medium: 20px' ), 'medium font size is 20px' ); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--large: 36px' ), 'large font size is 36px' ); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--x-large: 42px' ), 'x-large font size is 42px' ); + } + + public function test_variables_in_classic_theme_with_no_presets_using_presets() { + $styles = wp_get_global_stylesheet( array( 'presets' ) ); + $this->assertFalse( str_contains( $styles, '--wp--preset--font-size--small: 13px' ), 'small font size is not present' ); + $this->assertFalse( str_contains( $styles, '--wp--preset--font-size--medium: 20px' ), 'medium font size is not present' ); + $this->assertFalse( str_contains( $styles, '--wp--preset--font-size--large: 36px' ), 'large font size is not present' ); + $this->assertFalse( str_contains( $styles, '--wp--preset--font-size--x-large: 42px' ), 'x-large font size is not present' ); + } + + public function test_variables_in_classic_theme_with_no_presets_using_defaults() { + $styles = wp_get_global_stylesheet(); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--small: 13px' ), 'small font size is 13px' ); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--medium: 20px' ), 'medium font size is 20px' ); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--large: 36px' ), 'large font size is 36px' ); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--x-large: 42px' ), 'x-large font size is 42px' ); + } + + public function test_variables_in_classic_theme_with_presets_using_variables() { + add_theme_support( + 'editor-font-sizes', + array( + array( + 'name' => 'Small', + 'size' => 18, + 'slug' => 'small', + ), + array( + 'name' => 'Large', + 'size' => 26.25, + 'slug' => 'large', + ), + ) + ); + + $styles = wp_get_global_stylesheet( array( 'variables' ) ); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--small: 18px' ), 'small font size is 18px' ); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--medium: 20px' ), 'medium font size is 20px' ); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--large: 26.25px' ), 'large font size is 26.25px' ); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--x-large: 42px' ), 'x-large font size is 42px' ); + + remove_theme_support( 'editor-font-sizes' ); + } + + public function test_variables_in_classic_theme_with_presets_using_presets() { + add_theme_support( + 'editor-font-sizes', + array( + array( + 'name' => 'Small', + 'size' => 18, + 'slug' => 'small', + ), + array( + 'name' => 'Large', + 'size' => 26.25, + 'slug' => 'large', + ), + ) + ); + + $styles = wp_get_global_stylesheet( array( 'presets' ) ); + $this->assertFalse( str_contains( $styles, '--wp--preset--font-size--small: 18px' ), 'small font size is not present' ); + $this->assertFalse( str_contains( $styles, '--wp--preset--font-size--medium: 20px' ), 'medium font size is not present' ); + $this->assertFalse( str_contains( $styles, '--wp--preset--font-size--large: 26.25px' ), 'large font size is not present' ); + $this->assertFalse( str_contains( $styles, '--wp--preset--font-size--x-large: 42px' ), 'x-large font size is not present' ); + + remove_theme_support( 'editor-font-sizes' ); + } + + public function test_variables_in_classic_theme_with_presets_using_defaults() { + add_theme_support( + 'editor-font-sizes', + array( + array( + 'name' => 'Small', + 'size' => 18, + 'slug' => 'small', + ), + array( + 'name' => 'Large', + 'size' => 26.25, + 'slug' => 'large', + ), + ) + ); + + $styles = wp_get_global_stylesheet(); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--small: 18px' ), 'small font size is 18px' ); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--medium: 20px' ), 'medium font size is 20px' ); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--large: 26.25px' ), 'large font size is 26.25px' ); + $this->assertTrue( str_contains( $styles, '--wp--preset--font-size--x-large: 42px' ), 'small font size is 42px' ); + + remove_theme_support( 'editor-font-sizes' ); + } + +}