wp/wp-includes/global-styles-and-settings.php
changeset 22 8c2e4d02f4ef
parent 21 48c4eec2b7e6
equal deleted inserted replaced
21:48c4eec2b7e6 22:8c2e4d02f4ef
   140  * @since 5.9.0
   140  * @since 5.9.0
   141  * @since 6.1.0 Added 'base-layout-styles' support.
   141  * @since 6.1.0 Added 'base-layout-styles' support.
   142  * @since 6.6.0 Resolves relative paths in theme.json styles to theme absolute paths.
   142  * @since 6.6.0 Resolves relative paths in theme.json styles to theme absolute paths.
   143  *
   143  *
   144  * @param array $types Optional. Types of styles to load.
   144  * @param array $types Optional. Types of styles to load.
   145  *                     It accepts as values 'variables', 'presets', 'styles', 'base-layout-styles'.
   145  *                     See {@see 'WP_Theme_JSON::get_stylesheet'} for all valid types.
   146  *                     If empty, it'll load the following:
   146  *                     If empty, it'll load the following:
   147  *                     - for themes without theme.json: 'variables', 'presets', 'base-layout-styles'.
   147  *                     - for themes without theme.json: 'variables', 'presets', 'base-layout-styles'.
   148  *                     - for themes with theme.json: 'variables', 'presets', 'styles'.
   148  *                     - for themes with theme.json: 'variables', 'presets', 'styles'.
   149  * @return string Stylesheet.
   149  * @return string Stylesheet.
   150  */
   150  */
   242 
   242 
   243 	return $stylesheet;
   243 	return $stylesheet;
   244 }
   244 }
   245 
   245 
   246 /**
   246 /**
   247  * Gets the global styles custom CSS from theme.json.
       
   248  *
       
   249  * @since 6.2.0
       
   250  *
       
   251  * @return string The global styles custom CSS.
       
   252  */
       
   253 function wp_get_global_styles_custom_css() {
       
   254 	if ( ! wp_theme_has_theme_json() ) {
       
   255 		return '';
       
   256 	}
       
   257 	/*
       
   258 	 * Ignore cache when the development mode is set to 'theme', so it doesn't interfere with the theme
       
   259 	 * developer's workflow.
       
   260 	 */
       
   261 	$can_use_cached = ! wp_is_development_mode( 'theme' );
       
   262 
       
   263 	/*
       
   264 	 * By using the 'theme_json' group, this data is marked to be non-persistent across requests.
       
   265 	 * @see `wp_cache_add_non_persistent_groups()`.
       
   266 	 *
       
   267 	 * The rationale for this is to make sure derived data from theme.json
       
   268 	 * is always fresh from the potential modifications done via hooks
       
   269 	 * that can use dynamic data (modify the stylesheet depending on some option,
       
   270 	 * settings depending on user permissions, etc.).
       
   271 	 * See some of the existing hooks to modify theme.json behavior:
       
   272 	 * @see https://make.wordpress.org/core/2022/10/10/filters-for-theme-json-data/
       
   273 	 *
       
   274 	 * A different alternative considered was to invalidate the cache upon certain
       
   275 	 * events such as options add/update/delete, user meta, etc.
       
   276 	 * It was judged not enough, hence this approach.
       
   277 	 * @see https://github.com/WordPress/gutenberg/pull/45372
       
   278 	 */
       
   279 	$cache_key   = 'wp_get_global_styles_custom_css';
       
   280 	$cache_group = 'theme_json';
       
   281 	if ( $can_use_cached ) {
       
   282 		$cached = wp_cache_get( $cache_key, $cache_group );
       
   283 		if ( $cached ) {
       
   284 			return $cached;
       
   285 		}
       
   286 	}
       
   287 
       
   288 	$tree       = WP_Theme_JSON_Resolver::get_merged_data();
       
   289 	$stylesheet = $tree->get_custom_css();
       
   290 
       
   291 	if ( $can_use_cached ) {
       
   292 		wp_cache_set( $cache_key, $stylesheet, $cache_group );
       
   293 	}
       
   294 
       
   295 	return $stylesheet;
       
   296 }
       
   297 
       
   298 /**
       
   299  * Adds global style rules to the inline style for each block.
   247  * Adds global style rules to the inline style for each block.
   300  *
   248  *
   301  * @since 6.1.0
   249  * @since 6.1.0
       
   250  * @since 6.7.0 Resolve relative paths in block styles.
   302  *
   251  *
   303  * @global WP_Styles $wp_styles
   252  * @global WP_Styles $wp_styles
   304  */
   253  */
   305 function wp_add_global_styles_for_blocks() {
   254 function wp_add_global_styles_for_blocks() {
   306 	global $wp_styles;
   255 	global $wp_styles;
   307 
   256 
   308 	$tree        = WP_Theme_JSON_Resolver::get_merged_data();
   257 	$tree        = WP_Theme_JSON_Resolver::get_merged_data();
       
   258 	$tree        = WP_Theme_JSON_Resolver::resolve_theme_file_uris( $tree );
   309 	$block_nodes = $tree->get_styles_block_nodes();
   259 	$block_nodes = $tree->get_styles_block_nodes();
       
   260 
       
   261 	$can_use_cached = ! wp_is_development_mode( 'theme' );
       
   262 	$update_cache   = false;
       
   263 
       
   264 	if ( $can_use_cached ) {
       
   265 		// Hash the merged WP_Theme_JSON data to bust cache on settings or styles change.
       
   266 		$cache_hash = md5( wp_json_encode( $tree->get_raw_data() ) );
       
   267 		$cache_key  = 'wp_styles_for_blocks';
       
   268 		$cached     = get_transient( $cache_key );
       
   269 
       
   270 		// Reset the cached data if there is no value or if the hash has changed.
       
   271 		if ( ! is_array( $cached ) || $cached['hash'] !== $cache_hash ) {
       
   272 			$cached = array(
       
   273 				'hash'   => $cache_hash,
       
   274 				'blocks' => array(),
       
   275 			);
       
   276 
       
   277 			// Update the cache if the hash has changed.
       
   278 			$update_cache = true;
       
   279 		}
       
   280 	}
       
   281 
   310 	foreach ( $block_nodes as $metadata ) {
   282 	foreach ( $block_nodes as $metadata ) {
   311 		$block_css = $tree->get_styles_for_block( $metadata );
   283 
   312 
   284 		if ( $can_use_cached ) {
   313 		if ( ! wp_should_load_separate_core_block_assets() ) {
   285 			// Use the block name as the key for cached CSS data. Otherwise, use a hash of the metadata.
       
   286 			$cache_node_key = isset( $metadata['name'] ) ? $metadata['name'] : md5( wp_json_encode( $metadata ) );
       
   287 
       
   288 			if ( isset( $cached['blocks'][ $cache_node_key ] ) ) {
       
   289 				$block_css = $cached['blocks'][ $cache_node_key ];
       
   290 			} else {
       
   291 				$block_css                           = $tree->get_styles_for_block( $metadata );
       
   292 				$cached['blocks'][ $cache_node_key ] = $block_css;
       
   293 
       
   294 				// Update the cache if the cache contents have changed.
       
   295 				$update_cache = true;
       
   296 			}
       
   297 		} else {
       
   298 			$block_css = $tree->get_styles_for_block( $metadata );
       
   299 		}
       
   300 
       
   301 		if ( ! wp_should_load_block_assets_on_demand() ) {
   314 			wp_add_inline_style( 'global-styles', $block_css );
   302 			wp_add_inline_style( 'global-styles', $block_css );
   315 			continue;
   303 			continue;
   316 		}
   304 		}
   317 
   305 
   318 		$stylesheet_handle = 'global-styles';
   306 		$stylesheet_handle = 'global-styles';
   319 
   307 
   320 		/*
   308 		/*
   321 		 * When `wp_should_load_separate_core_block_assets()` is true, block styles are
   309 		 * When `wp_should_load_block_assets_on_demand()` is true, block styles are
   322 		 * enqueued for each block on the page in class WP_Block's render function.
   310 		 * enqueued for each block on the page in class WP_Block's render function.
   323 		 * This means there will be a handle in the styles queue for each of those blocks.
   311 		 * This means there will be a handle in the styles queue for each of those blocks.
   324 		 * Block-specific global styles should be attached to the global-styles handle, but
   312 		 * Block-specific global styles should be attached to the global-styles handle, but
   325 		 * only for blocks on the page, thus we check if the block's handle is in the queue
   313 		 * only for blocks on the page, thus we check if the block's handle is in the queue
   326 		 * before adding the inline style.
   314 		 * before adding the inline style.
   327 		 * This conditional loading only applies to core blocks.
   315 		 * This conditional loading only applies to core blocks.
       
   316 		 * TODO: Explore how this could be expanded to third-party blocks as well.
   328 		 */
   317 		 */
   329 		if ( isset( $metadata['name'] ) ) {
   318 		if ( isset( $metadata['name'] ) ) {
   330 			if ( str_starts_with( $metadata['name'], 'core/' ) ) {
   319 			if ( str_starts_with( $metadata['name'], 'core/' ) ) {
   331 				$block_name   = str_replace( 'core/', '', $metadata['name'] );
   320 				$block_name   = str_replace( 'core/', '', $metadata['name'] );
   332 				$block_handle = 'wp-block-' . $block_name;
   321 				$block_handle = 'wp-block-' . $block_name;
   352 					wp_add_inline_style( $stylesheet_handle, $block_css );
   341 					wp_add_inline_style( $stylesheet_handle, $block_css );
   353 				}
   342 				}
   354 			}
   343 			}
   355 		}
   344 		}
   356 	}
   345 	}
       
   346 
       
   347 	if ( $update_cache ) {
       
   348 		set_transient( $cache_key, $cached );
       
   349 	}
   357 }
   350 }
   358 
   351 
   359 /**
   352 /**
   360  * Gets the block name from a given theme.json path.
   353  * Gets the block name from a given theme.json path.
   361  *
   354  *