diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 0d2520ff9682a4..6ee8a004125a04 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -1284,21 +1284,68 @@ protected function process_blocks_custom_css( $css, $selector ) { * @return string The global styles custom CSS. */ public function get_custom_css() { - // Add the global styles root CSS. - $stylesheet = $this->theme_json['styles']['css'] ?? ''; + $block_custom_css = ''; + $block_nodes = $this->get_block_custom_css_nodes(); + foreach ( $block_nodes as $node ) { + $block_custom_css .= $this->get_block_custom_css( $node['css'], $node['selector'] ); + } + + return $this->get_base_custom_css() . $block_custom_css; + } + + /** + * Returns the global styles base custom CSS. + * + * @since 6.6.0 + * + * @return string The global styles base custom CSS. + */ + public function get_base_custom_css() { + return isset( $this->theme_json['styles']['css'] ) ? $this->theme_json['styles']['css'] : ''; + } + + /** + * Returns the block nodes with custom CSS. + * + * @since 6.6.0 + * + * @return array The block nodes. + */ + public function get_block_custom_css_nodes() { + $block_nodes = array(); // 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 = $this->theme_json['styles']['blocks'][ $name ]['css'] ?? null; + $custom_block_css = isset( $this->theme_json['styles']['blocks'][ $name ]['css'] ) + ? $this->theme_json['styles']['blocks'][ $name ]['css'] + : null; if ( $custom_block_css ) { - $selector = static::$blocks_metadata[ $name ]['selector']; - $stylesheet .= $this->process_blocks_custom_css( $custom_block_css, $selector ); + $block_nodes[] = array( + 'name' => $name, + 'selector' => static::$blocks_metadata[ $name ]['selector'], + 'css' => $custom_block_css, + ); } } } - return $stylesheet; + return $block_nodes; + } + + + /** + * Returns the global styles custom CSS for a single block. + * + * @since 6.6.0 + * + * @param array $css The block css node. + * @param string $selector The block selector. + * + * @return string The global styles custom CSS for the block. + */ + public function get_block_custom_css( $css, $selector ) { + return $this->process_blocks_custom_css( $css, $selector ); } /** diff --git a/lib/global-styles-and-settings.php b/lib/global-styles-and-settings.php index a4df8576158ab0..3aeaf745fe49f1 100644 --- a/lib/global-styles-and-settings.php +++ b/lib/global-styles-and-settings.php @@ -168,6 +168,82 @@ function gutenberg_get_global_styles_custom_css() { return $stylesheet; } +/** + * Gets the global styles base custom CSS from theme.json. + * + * @since 6.6.0 + * + * @return string The global base custom CSS. + */ +function gutenberg_get_global_styles_base_custom_css() { + if ( ! wp_theme_has_theme_json() ) { + return ''; + } + + $can_use_cached = ! WP_DEBUG; + + $cache_key = 'gutenberg_get_global_styles_base_custom_css'; + $cache_group = 'theme_json'; + if ( $can_use_cached ) { + $cached = wp_cache_get( $cache_key, $cache_group ); + if ( $cached ) { + return $cached; + } + } + + $tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data(); + $stylesheet = $tree->get_base_custom_css(); + + if ( $can_use_cached ) { + wp_cache_set( $cache_key, $stylesheet, $cache_group ); + } + + return $stylesheet; +} + +/** + * Adds the global styles per-block custom CSS from theme.json + * to the inline style for each block. + * + * @since 6.6.0 + * + * @global WP_Styles $wp_styles + */ +function gutenberg_add_global_styles_block_custom_css() { + global $wp_styles; + + if ( ! wp_theme_has_theme_json() || ! wp_should_load_separate_core_block_assets() ) { + return; + } + + $tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data(); + $block_nodes = $tree->get_block_custom_css_nodes(); + + foreach ( $block_nodes as $metadata ) { + $block_css = $tree->get_block_custom_css( $metadata['css'], $metadata['selector'] ); + + $stylesheet_handle = 'global-styles'; + + /** + * When `wp_should_load_separate_core_block_assets()` is true, follow a similar + * logic to the one in `gutenberg_add_global_styles_for_blocks` to add the custom + * css only when the block is rendered. + */ + if ( isset( $metadata['name'] ) ) { + if ( str_starts_with( $metadata['name'], 'core/' ) ) { + $block_name = str_replace( 'core/', '', $metadata['name'] ); + $block_handle = 'wp-block-' . $block_name; + if ( in_array( $block_handle, $wp_styles->queue, true ) ) { + wp_add_inline_style( $stylesheet_handle, $block_css ); + } + } else { + wp_add_inline_style( $stylesheet_handle, $block_css ); + } + } + } +} + + /** * Adds global style rules to the inline style for each block. * @@ -238,6 +314,7 @@ function _gutenberg_clean_theme_json_caches() { 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_cache_delete( 'gutenberg_get_global_styles_base_custom_css', 'theme_json' ); WP_Theme_JSON_Resolver_Gutenberg::clean_cached_data(); } add_action( 'start_previewing_theme', '_gutenberg_clean_theme_json_caches' ); diff --git a/lib/script-loader.php b/lib/script-loader.php index 2b5c7bb08a676f..1c0e5f5a941fe6 100644 --- a/lib/script-loader.php +++ b/lib/script-loader.php @@ -53,6 +53,35 @@ function gutenberg_enqueue_global_styles() { // Add each block as an inline css. gutenberg_add_global_styles_for_blocks(); + + /** + * Add the custom CSS for the global styles. + * Before that, dequeue the Customizer's custom CSS + * and add it before the global styles custom CSS. + */ + // Don't enqueue Customizer's custom CSS separately. + remove_action( 'wp_head', 'wp_custom_css_cb', 101 ); + + $custom_css = wp_get_custom_css(); + + if ( ! wp_should_load_separate_core_block_assets() ) { + /** + * If loading all block assets together, add both + * the base and block custom CSS at once. Else load + * the base custom CSS only, and the block custom CSS + * will be added to the inline CSS for each block in + * gutenberg_add_global_styles_block_custom_css(). + */ + $custom_css .= gutenberg_get_global_styles_custom_css(); + } else { + $custom_css .= gutenberg_get_global_styles_base_custom_css(); + } + + if ( ! empty( $custom_css ) ) { + wp_add_inline_style( 'global-styles', $custom_css ); + } + + gutenberg_add_global_styles_block_custom_css(); } add_action( 'wp_enqueue_scripts', 'gutenberg_enqueue_global_styles' ); add_action( 'wp_footer', 'gutenberg_enqueue_global_styles', 1 ); @@ -63,6 +92,7 @@ function gutenberg_enqueue_global_styles() { * @since 6.2.0 */ function gutenberg_enqueue_global_styles_custom_css() { + _deprecated_function( __FUNCTION__, 'Gutenberg 17.8.0', 'gutenberg_enqueue_global_styles' ); if ( ! wp_is_block_theme() ) { return; } @@ -77,8 +107,6 @@ function gutenberg_enqueue_global_styles_custom_css() { wp_add_inline_style( 'global-styles', $custom_css ); } } -remove_action( 'wp_enqueue_scripts', 'wp_enqueue_global_styles_custom_css' ); -add_action( 'wp_enqueue_scripts', 'gutenberg_enqueue_global_styles_custom_css' ); /** * Function that enqueues the CSS Custom Properties coming from theme.json.