diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index e3b92aca2f9e53..1ee24f86969baa 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -988,7 +988,6 @@ public function process_blocks_custom_css( $css, $selector ) { * - `variables`: only the CSS Custom Properties for presets & custom ones. * - `styles`: only the styles section in theme.json. * - `presets`: only the classes for the presets. - * - `custom-css`: only the css from global styles.css. * @param array $origins A list of origins to include. By default it includes VALID_ORIGINS. * @param array $options An array of options for now used for internal purposes only (may change without notice). * The options currently supported are 'scope' that makes sure all style are scoped to a given selector, @@ -1081,25 +1080,33 @@ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets' $stylesheet .= $this->get_preset_classes( $setting_nodes, $origins ); } - // Load the custom CSS last so it has the highest specificity. - if ( in_array( 'custom-css', $types, true ) ) { - // Add the global styles root CSS. - $stylesheet .= _wp_array_get( $this->theme_json, array( 'styles', 'css' ) ); + return $stylesheet; + } - // Add the global styles block CSS. - if ( isset( $this->theme_json['styles']['blocks'] ) ) { - foreach ( $this->theme_json['styles']['blocks'] as $name => $node ) { - $custom_block_css = _wp_array_get( $this->theme_json, array( 'styles', 'blocks', $name, 'css' ) ); - if ( $custom_block_css ) { - $selector = static::$blocks_metadata[ $name ]['selector']; - $stylesheet .= $this->process_blocks_custom_css( $custom_block_css, $selector ); - } + /** + * Returns the global styles custom css. + * + * @since 6.2.0 + * + * @return string + */ + public function get_custom_css() { + // Add the global styles root CSS. + $stylesheet = _wp_array_get( $this->theme_json, array( 'styles', 'css' ), '' ); + + // Add the global styles block CSS. + if ( isset( $this->theme_json['styles']['blocks'] ) ) { + foreach ( $this->theme_json['styles']['blocks'] as $name => $node ) { + $custom_block_css = _wp_array_get( $this->theme_json, array( 'styles', 'blocks', $name, 'css' ) ); + if ( $custom_block_css ) { + $selector = static::$blocks_metadata[ $name ]['selector']; + $stylesheet .= $this->process_blocks_custom_css( $custom_block_css, $selector ); } } } - return $stylesheet; } + /** * Returns the page templates of the active theme. * diff --git a/lib/compat/wordpress-6.2/block-editor-settings.php b/lib/compat/wordpress-6.2/block-editor-settings.php index 7323d34eb667ce..2fd8dc1e2f6bb8 100644 --- a/lib/compat/wordpress-6.2/block-editor-settings.php +++ b/lib/compat/wordpress-6.2/block-editor-settings.php @@ -16,7 +16,7 @@ function gutenberg_get_block_editor_settings_6_2( $settings ) { if ( wp_theme_has_theme_json() ) { // Add the custom CSS as separate style sheet so any invalid CSS entered by users does not break other global styles. $settings['styles'][] = array( - 'css' => gutenberg_get_global_stylesheet( array( 'custom-css' ) ), + 'css' => gutenberg_get_global_styles_custom_css(), '__unstableType' => 'user', 'isGlobalStyles' => true, ); 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 index 86199807081ecc..e02a0466a0b98f 100644 --- a/lib/compat/wordpress-6.2/get-global-styles-and-settings.php +++ b/lib/compat/wordpress-6.2/get-global-styles-and-settings.php @@ -59,14 +59,45 @@ function wp_theme_has_theme_json_clean_cache() { } } +/** + * Gets the global styles custom css from theme.json. + * + * @return string + */ +function gutenberg_get_global_styles_custom_css() { + // Ignore cache when `WP_DEBUG` is enabled, so it doesn't interfere with the theme developers workflow. + $can_use_cached = ! WP_DEBUG; + $cache_key = 'gutenberg_get_global_custom_css'; + $cache_group = 'theme_json'; + if ( $can_use_cached ) { + $cached = wp_cache_get( $cache_key, $cache_group ); + if ( $cached ) { + return $cached; + } + } + + if ( ! wp_theme_has_theme_json() ) { + return ''; + } + + $tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data(); + $stylesheet = $tree->get_custom_css(); + + if ( $can_use_cached ) { + wp_cache_set( $cache_key, $stylesheet, $cache_group ); + } + + return $stylesheet; +} + /** * Returns the stylesheet resulting of merging core, theme, and user data. * * @param array $types Types of styles to load. Optional. - * It accepts as values: 'variables', 'presets', 'styles', 'base-layout-styles, and 'custom-css'. + * It accepts as values: 'variables', 'presets', 'styles', 'base-layout-styles. * If empty, it'll load the following: * - for themes without theme.json: 'variables', 'presets', 'base-layout-styles'. - * - for themes with theme.json: 'variables', 'presets', 'styles', 'custom-css'. + * - for themes with theme.json: 'variables', 'presets', 'styles'. * * @return string Stylesheet. */ @@ -86,7 +117,7 @@ function gutenberg_get_global_stylesheet( $types = array() ) { if ( empty( $types ) && ! $supports_theme_json ) { $types = array( 'variables', 'presets', 'base-layout-styles' ); } elseif ( empty( $types ) ) { - $types = array( 'variables', 'presets', 'styles', 'custom-css' ); + $types = array( 'variables', 'presets', 'styles' ); } /* @@ -194,6 +225,7 @@ function _gutenberg_clean_theme_json_caches() { wp_cache_delete( 'gutenberg_get_global_stylesheet', 'theme_json' ); wp_cache_delete( 'gutenberg_get_global_settings_custom', 'theme_json' ); wp_cache_delete( 'gutenberg_get_global_settings_theme', 'theme_json' ); + wp_cache_delete( 'gutenberg_get_global_custom_css', 'theme_json' ); WP_Theme_JSON_Resolver_Gutenberg::clean_cached_data(); } diff --git a/lib/compat/wordpress-6.2/script-loader.php b/lib/compat/wordpress-6.2/script-loader.php index 6ad6b2b9ec78bd..05c2019cbd4f64 100644 --- a/lib/compat/wordpress-6.2/script-loader.php +++ b/lib/compat/wordpress-6.2/script-loader.php @@ -167,3 +167,25 @@ function( $settings ) { }, 100 ); + +/** + * Enqueues the global styles custom css. + * + * @since 6.2.0 + */ +function gutenberg_enqueue_global_styles_custom_css() { + if ( ! wp_is_block_theme() ) { + return; + } + + // Don't enqueue Customizer's custom CSS separately. + remove_action( 'wp_head', 'wp_custom_css_cb', 101 ); + + $custom_css = wp_get_custom_css(); + $custom_css .= gutenberg_get_global_styles_custom_css(); + + if ( ! empty( $custom_css ) ) { + wp_add_inline_style( 'global-styles', $custom_css ); + } +} +add_action( 'wp_enqueue_scripts', 'gutenberg_enqueue_global_styles_custom_css' ); diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index d3f745b1779e41..fc118f5bb34bfd 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -1615,18 +1615,23 @@ public function test_update_separator_declarations() { } - public function test_get_stylesheet_handles_custom_css() { + public function test_get_custom_css_handles_global_custom_css() { $theme_json = new WP_Theme_JSON_Gutenberg( array( 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'styles' => array( - 'css' => 'body { color:purple; }', + 'css' => 'body {color:purple;}', + 'blocks' => array( + 'core/paragraph' => array( + 'css' => 'color:red;', + ), + ), ), ) ); - $custom_css = 'body { color:purple; }'; - $this->assertEquals( $custom_css, $theme_json->get_stylesheet( array( 'custom-css' ) ) ); + $custom_css = 'body {color:purple;}p{color:red;}'; + $this->assertEquals( $custom_css, $theme_json->get_custom_css() ); } /**