--- a/wp/wp-includes/global-styles-and-settings.php Fri Sep 05 18:40:08 2025 +0200
+++ b/wp/wp-includes/global-styles-and-settings.php Fri Sep 05 18:52:52 2025 +0200
@@ -142,7 +142,7 @@
* @since 6.6.0 Resolves relative paths in theme.json styles to theme absolute paths.
*
* @param array $types Optional. Types of styles to load.
- * It accepts as values 'variables', 'presets', 'styles', 'base-layout-styles'.
+ * See {@see 'WP_Theme_JSON::get_stylesheet'} for all valid types.
* 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'.
@@ -244,61 +244,10 @@
}
/**
- * Gets the global styles custom CSS from theme.json.
- *
- * @since 6.2.0
- *
- * @return string The global styles custom CSS.
- */
-function wp_get_global_styles_custom_css() {
- if ( ! wp_theme_has_theme_json() ) {
- return '';
- }
- /*
- * Ignore cache when the development mode is set to 'theme', so it doesn't interfere with the theme
- * developer's workflow.
- */
- $can_use_cached = ! wp_is_development_mode( 'theme' );
-
- /*
- * By using the 'theme_json' group, this data is marked to be non-persistent across requests.
- * @see `wp_cache_add_non_persistent_groups()`.
- *
- * The rationale for this is to make sure derived data from theme.json
- * is always fresh from the potential modifications done via hooks
- * that can use dynamic data (modify the stylesheet depending on some option,
- * settings depending on user permissions, etc.).
- * See some of the existing hooks to modify theme.json behavior:
- * @see https://make.wordpress.org/core/2022/10/10/filters-for-theme-json-data/
- *
- * A different alternative considered was to invalidate the cache upon certain
- * events such as options add/update/delete, user meta, etc.
- * It was judged not enough, hence this approach.
- * @see https://github.com/WordPress/gutenberg/pull/45372
- */
- $cache_key = 'wp_get_global_styles_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::get_merged_data();
- $stylesheet = $tree->get_custom_css();
-
- if ( $can_use_cached ) {
- wp_cache_set( $cache_key, $stylesheet, $cache_group );
- }
-
- return $stylesheet;
-}
-
-/**
* Adds global style rules to the inline style for each block.
*
* @since 6.1.0
+ * @since 6.7.0 Resolve relative paths in block styles.
*
* @global WP_Styles $wp_styles
*/
@@ -306,11 +255,50 @@
global $wp_styles;
$tree = WP_Theme_JSON_Resolver::get_merged_data();
+ $tree = WP_Theme_JSON_Resolver::resolve_theme_file_uris( $tree );
$block_nodes = $tree->get_styles_block_nodes();
+
+ $can_use_cached = ! wp_is_development_mode( 'theme' );
+ $update_cache = false;
+
+ if ( $can_use_cached ) {
+ // Hash the merged WP_Theme_JSON data to bust cache on settings or styles change.
+ $cache_hash = md5( wp_json_encode( $tree->get_raw_data() ) );
+ $cache_key = 'wp_styles_for_blocks';
+ $cached = get_transient( $cache_key );
+
+ // Reset the cached data if there is no value or if the hash has changed.
+ if ( ! is_array( $cached ) || $cached['hash'] !== $cache_hash ) {
+ $cached = array(
+ 'hash' => $cache_hash,
+ 'blocks' => array(),
+ );
+
+ // Update the cache if the hash has changed.
+ $update_cache = true;
+ }
+ }
+
foreach ( $block_nodes as $metadata ) {
- $block_css = $tree->get_styles_for_block( $metadata );
+
+ if ( $can_use_cached ) {
+ // Use the block name as the key for cached CSS data. Otherwise, use a hash of the metadata.
+ $cache_node_key = isset( $metadata['name'] ) ? $metadata['name'] : md5( wp_json_encode( $metadata ) );
- if ( ! wp_should_load_separate_core_block_assets() ) {
+ if ( isset( $cached['blocks'][ $cache_node_key ] ) ) {
+ $block_css = $cached['blocks'][ $cache_node_key ];
+ } else {
+ $block_css = $tree->get_styles_for_block( $metadata );
+ $cached['blocks'][ $cache_node_key ] = $block_css;
+
+ // Update the cache if the cache contents have changed.
+ $update_cache = true;
+ }
+ } else {
+ $block_css = $tree->get_styles_for_block( $metadata );
+ }
+
+ if ( ! wp_should_load_block_assets_on_demand() ) {
wp_add_inline_style( 'global-styles', $block_css );
continue;
}
@@ -318,13 +306,14 @@
$stylesheet_handle = 'global-styles';
/*
- * When `wp_should_load_separate_core_block_assets()` is true, block styles are
+ * When `wp_should_load_block_assets_on_demand()` is true, block styles are
* enqueued for each block on the page in class WP_Block's render function.
* This means there will be a handle in the styles queue for each of those blocks.
* Block-specific global styles should be attached to the global-styles handle, but
* only for blocks on the page, thus we check if the block's handle is in the queue
* before adding the inline style.
* This conditional loading only applies to core blocks.
+ * TODO: Explore how this could be expanded to third-party blocks as well.
*/
if ( isset( $metadata['name'] ) ) {
if ( str_starts_with( $metadata['name'], 'core/' ) ) {
@@ -354,6 +343,10 @@
}
}
}
+
+ if ( $update_cache ) {
+ set_transient( $cache_key, $cached );
+ }
}
/**