diff --git a/src/wp-includes/class-wp-theme-json-resolver.php b/src/wp-includes/class-wp-theme-json-resolver.php index d63a84353cd46..6f0ee0086db15 100644 --- a/src/wp-includes/class-wp-theme-json-resolver.php +++ b/src/wp-includes/class-wp-theme-json-resolver.php @@ -91,6 +91,14 @@ class WP_Theme_JSON_Resolver { */ protected static $theme_json_file_cache = array(); + /** + * Cache for resolved files per theme. + * + * @since 6.8.0 + * @var array + */ + protected static $resolved_theme_uris_cache = array(); + /** * Processes a file that adheres to the theme.json schema * and returns an array with its contents, or a void array if none found. @@ -739,20 +747,22 @@ protected static function get_file_path_from_theme( $file_name, $template = fals * and `$i18n_schema` variables to reset. * @since 6.1.0 Added the `$blocks` and `$blocks_cache` variables * to reset. + * @since 6.8.0 Added the `$resolved_theme_uris_cache` variable to reset. */ public static function clean_cached_data() { - static::$core = null; - static::$blocks = null; - static::$blocks_cache = array( + static::$core = null; + static::$blocks = null; + static::$blocks_cache = array( 'core' => array(), 'blocks' => array(), 'theme' => array(), 'user' => array(), ); - static::$theme = null; - static::$user = null; - static::$user_custom_post_type_id = null; - static::$i18n_schema = null; + static::$theme = null; + static::$user = null; + static::$user_custom_post_type_id = null; + static::$i18n_schema = null; + static::$resolved_theme_uris_cache = array(); } /** @@ -849,6 +859,7 @@ public static function get_style_variations( $scope = 'theme' ) { * * @since 6.6.0 * @since 6.7.0 Resolve relative paths in block styles. + * @since 6.8.0 Added caching for resolved theme URIs. * * @param WP_Theme_JSON $theme_json A theme json instance. * @return array An array of resolved paths. @@ -860,7 +871,13 @@ public static function get_resolved_theme_uris( $theme_json ) { return $resolved_theme_uris; } - $theme_json_data = $theme_json->get_raw_data(); + $theme_json_data = $theme_json->get_raw_data(); + $resolved_theme_uris_cache_key = md5( wp_json_encode( $theme_json_data ) ); + + if ( ! empty( static::$resolved_theme_uris_cache[ $resolved_theme_uris_cache_key ] ) ) { + return static::$resolved_theme_uris_cache[ $resolved_theme_uris_cache_key ]; + } + /* * The same file convention when registering web fonts. * See: WP_Font_Face_Resolver::to_theme_file_uri. @@ -914,7 +931,7 @@ public static function get_resolved_theme_uris( $theme_json ) { } } } - + static::$resolved_theme_uris_cache[ $resolved_theme_uris_cache_key ] = $resolved_theme_uris; return $resolved_theme_uris; } diff --git a/tests/phpunit/tests/theme/wpThemeJsonResolver.php b/tests/phpunit/tests/theme/wpThemeJsonResolver.php index 4fb3784f1a41b..bbd5fd40683cd 100644 --- a/tests/phpunit/tests/theme/wpThemeJsonResolver.php +++ b/tests/phpunit/tests/theme/wpThemeJsonResolver.php @@ -33,6 +33,20 @@ class Tests_Theme_wpThemeJsonResolver extends WP_UnitTestCase { */ private static $property_blocks_cache_orig_value; + /** + * WP_Theme_JSON_Resolver::$resolved_theme_uris_cache property. + * + * @var ReflectionProperty + */ + private static $property_resolved_theme_uris_cache; + + /** + * Original value of the WP_Theme_JSON_Resolver::$resolved_theme_uris_cache property. + * + * @var array + */ + private static $property_resolved_theme_uris_cache_orig_value; + /** * WP_Theme_JSON_Resolver::$core property. * @@ -83,11 +97,16 @@ public static function set_up_before_class() { static::$property_core = new ReflectionProperty( WP_Theme_JSON_Resolver::class, 'core' ); static::$property_core->setAccessible( true ); static::$property_core_orig_value = static::$property_core->getValue(); + + static::$property_resolved_theme_uris_cache = new ReflectionProperty( WP_Theme_JSON_Resolver::class, 'resolved_theme_uris_cache' ); + static::$property_resolved_theme_uris_cache->setAccessible( true ); + static::$property_resolved_theme_uris_cache_orig_value = static::$property_resolved_theme_uris_cache->getValue(); } public static function tear_down_after_class() { static::$property_blocks_cache->setValue( null, static::$property_blocks_cache_orig_value ); static::$property_core->setValue( null, static::$property_core_orig_value ); + static::$property_resolved_theme_uris_cache->setValue( null, static::$property_resolved_theme_uris_cache_orig_value ); parent::tear_down_after_class(); } @@ -1322,11 +1341,13 @@ public function test_resolve_theme_file_uris() { } /** - * Tests that them uris are resolved and bundled with other metadata in an array. + * Tests that them uris are resolved and bundled with other metadata in an array + * and cached. * * @covers WP_Theme_JSON_Resolver::get_resolved_theme_uris * @ticket 61273 * @ticket 61588 + * @ticket 62261 */ public function test_get_resolved_theme_uris() { $theme_json = new WP_Theme_JSON( @@ -1381,7 +1402,13 @@ public function test_get_resolved_theme_uris() { $actual = WP_Theme_JSON_Resolver::get_resolved_theme_uris( $theme_json ); - $this->assertSame( $expected_data, $actual ); + $this->assertSame( $expected_data, $actual, 'Resolved theme uris do not match.' ); + + // Test that resolved theme uris are cached. + $cache_key = md5( wp_json_encode( $theme_json->get_raw_data() ) ); + $expected_cache_data = array( "$cache_key" => $actual ); + + $this->assertSame( $expected_cache_data, static::$property_resolved_theme_uris_cache->getValue(), 'Resolved theme uris cache data does not match.' ); } /**