From c8660e3f87e764cee4ef672faedaf87cebf2d706 Mon Sep 17 00:00:00 2001 From: ramon Date: Wed, 16 Oct 2024 15:57:58 +1100 Subject: [PATCH 1/8] A pretty basic caching test for resolved theme URIs in WP_Theme_JSON_Resolver --- ...class-wp-theme-json-resolver-gutenberg.php | 33 ++++++++++++++----- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/lib/class-wp-theme-json-resolver-gutenberg.php b/lib/class-wp-theme-json-resolver-gutenberg.php index 2231cb0f11538f..bd0f204863842b 100644 --- a/lib/class-wp-theme-json-resolver-gutenberg.php +++ b/lib/class-wp-theme-json-resolver-gutenberg.php @@ -91,6 +91,14 @@ class WP_Theme_JSON_Resolver_Gutenberg { */ 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. @@ -696,20 +704,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(); } /** @@ -850,6 +860,11 @@ public static function get_resolved_theme_uris( $theme_json ) { return $resolved_theme_uris; } + $current_stylesheet_directory = get_stylesheet_directory(); + if ( $current_stylesheet_directory && ! empty( static::$resolved_theme_uris_cache[ $current_stylesheet_directory ] ) ) { + return static::$resolved_theme_uris_cache[ $current_stylesheet_directory ]; + } + $theme_json_data = $theme_json->get_raw_data(); // Using the same file convention when registering web fonts. See: WP_Font_Face_Resolver:: to_theme_file_uri. @@ -901,7 +916,9 @@ public static function get_resolved_theme_uris( $theme_json ) { } } } - + if ( $current_stylesheet_directory ) { + static::$resolved_theme_uris_cache[ $current_stylesheet_directory ] = $resolved_theme_uris; + } return $resolved_theme_uris; } From 6dea724b754516c86009b20b4b8cf638d6a10ff5 Mon Sep 17 00:00:00 2001 From: ramon Date: Fri, 18 Oct 2024 15:59:56 +1100 Subject: [PATCH 2/8] Add a test --- phpunit/class-wp-theme-json-resolver-test.php | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/phpunit/class-wp-theme-json-resolver-test.php b/phpunit/class-wp-theme-json-resolver-test.php index d2339f2496290c..bc4b28173cef06 100644 --- a/phpunit/class-wp-theme-json-resolver-test.php +++ b/phpunit/class-wp-theme-json-resolver-test.php @@ -31,6 +31,20 @@ class WP_Theme_JSON_Resolver_Gutenberg_Test extends WP_UnitTestCase { */ private static $property_blocks_cache_orig_value; + /** + * WP_Theme_JSON_Resolver_Gutenberg::$resolved_theme_uris_cache property. + * + * @var ReflectionProperty + */ + private static $property_resolved_theme_uris_cache; + + /** + * Original value of the WP_Theme_JSON_Resolver_Gutenberg::$resolved_theme_uris_cache property. + * + * @var array + */ + private static $property_resolved_theme_uris_cache_orig_value; + /** * WP_Theme_JSON_Resolver_Gutenberg::$core property. * @@ -81,11 +95,16 @@ public static function set_up_before_class() { static::$property_core = new ReflectionProperty( WP_Theme_JSON_Resolver_Gutenberg::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_Gutenberg::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(); } @@ -1350,6 +1369,54 @@ public function test_get_resolved_theme_uris() { $this->assertSame( $expected_data, $actual ); } + public function test_get_resolved_theme_uris_cache() { + $theme_json = new WP_Theme_JSON_Gutenberg( + array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'background' => array( + 'backgroundImage' => array( + 'url' => 'file:./example/img/image.png', + ), + ), + 'blocks' => array( + 'core/quote' => array( + 'background' => array( + 'backgroundImage' => array( + 'url' => 'file:./example/img/quote.jpg', + ), + ), + ), + 'core/verse' => array( + 'background' => array( + 'backgroundImage' => array( + 'url' => 'file:./example/img/verse.gif', + ), + ), + ), + ), + ), + ) + ); + + /* + * This filter callback normalizes the return value from `get_theme_file_uri` + * to guard against changes in test environments. + * The test suite otherwise returns full system dir path, e.g., + * /wordpress-phpunit/includes/../data/themedir1/default/example/img/image.png + */ + $filter_theme_file_uri_callback = function ( $file ) { + return 'https://example.org/wp-content/themes/example-theme/example/' . explode( 'example/', $file )[1]; + }; + add_filter( 'theme_file_uri', $filter_theme_file_uri_callback ); + $actual = WP_Theme_JSON_Resolver_Gutenberg::get_resolved_theme_uris( $theme_json ); + remove_filter( 'theme_file_uri', $filter_theme_file_uri_callback ); + + $current_stylesheet_directory = get_stylesheet_directory(); + $expected_data = array( "$current_stylesheet_directory" => $actual ); + $this->assertSame( $expected_data, static::$property_resolved_theme_uris_cache->getValue() ); + } + /** * Tests that block style variations data gets merged in the following * priority order, from highest priority to lowest. From 436486f036e94754b2c1c56d8984998cbce78c0a Mon Sep 17 00:00:00 2001 From: ramon Date: Mon, 21 Oct 2024 13:29:53 +1100 Subject: [PATCH 3/8] Merge tests with the same data --- phpunit/class-wp-theme-json-resolver-test.php | 51 ++----------------- 1 file changed, 4 insertions(+), 47 deletions(-) diff --git a/phpunit/class-wp-theme-json-resolver-test.php b/phpunit/class-wp-theme-json-resolver-test.php index bc4b28173cef06..614be1a403a3a9 100644 --- a/phpunit/class-wp-theme-json-resolver-test.php +++ b/phpunit/class-wp-theme-json-resolver-test.php @@ -1366,55 +1366,12 @@ public function test_get_resolved_theme_uris() { $actual = WP_Theme_JSON_Resolver_Gutenberg::get_resolved_theme_uris( $theme_json ); remove_filter( 'theme_file_uri', $filter_theme_file_uri_callback ); - $this->assertSame( $expected_data, $actual ); - } - - public function test_get_resolved_theme_uris_cache() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'styles' => array( - 'background' => array( - 'backgroundImage' => array( - 'url' => 'file:./example/img/image.png', - ), - ), - 'blocks' => array( - 'core/quote' => array( - 'background' => array( - 'backgroundImage' => array( - 'url' => 'file:./example/img/quote.jpg', - ), - ), - ), - 'core/verse' => array( - 'background' => array( - 'backgroundImage' => array( - 'url' => 'file:./example/img/verse.gif', - ), - ), - ), - ), - ), - ) - ); - - /* - * This filter callback normalizes the return value from `get_theme_file_uri` - * to guard against changes in test environments. - * The test suite otherwise returns full system dir path, e.g., - * /wordpress-phpunit/includes/../data/themedir1/default/example/img/image.png - */ - $filter_theme_file_uri_callback = function ( $file ) { - return 'https://example.org/wp-content/themes/example-theme/example/' . explode( 'example/', $file )[1]; - }; - add_filter( 'theme_file_uri', $filter_theme_file_uri_callback ); - $actual = WP_Theme_JSON_Resolver_Gutenberg::get_resolved_theme_uris( $theme_json ); - remove_filter( 'theme_file_uri', $filter_theme_file_uri_callback ); + $this->assertSame( $expected_data, $actual, 'Resolved theme uris do not match.' ); + // Test that resolved theme uris are cached. $current_stylesheet_directory = get_stylesheet_directory(); - $expected_data = array( "$current_stylesheet_directory" => $actual ); - $this->assertSame( $expected_data, static::$property_resolved_theme_uris_cache->getValue() ); + $expected_cache_data = array( "$current_stylesheet_directory" => $actual ); + $this->assertSame( $expected_cache_data, static::$property_resolved_theme_uris_cache->getValue(), 'Resolved theme uris cache data does not match.' ); } /** From 5cdb27eb044ae0a87876a0fd3ef79cde46f7c56d Mon Sep 17 00:00:00 2001 From: ramon Date: Mon, 21 Oct 2024 13:58:34 +1100 Subject: [PATCH 4/8] Add annotation for version --- lib/class-wp-theme-json-resolver-gutenberg.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/class-wp-theme-json-resolver-gutenberg.php b/lib/class-wp-theme-json-resolver-gutenberg.php index bd0f204863842b..9c89f8b6db72f0 100644 --- a/lib/class-wp-theme-json-resolver-gutenberg.php +++ b/lib/class-wp-theme-json-resolver-gutenberg.php @@ -849,6 +849,7 @@ public static function get_style_variations_from_directory( $directory, $scope = * * @since 6.6.0 * @since 6.7.0 Added support for resolving block styles. + * @since 6.8.0 Added caching for resolved theme URIs. * * @param WP_Theme_JSON_Gutenberg $theme_json A theme json instance. * @return array An array of resolved paths. From 2f172a96f572db99dd2af491177a80d1d1ba060c Mon Sep 17 00:00:00 2001 From: ramon Date: Mon, 21 Oct 2024 14:14:25 +1100 Subject: [PATCH 5/8] Backport entry --- backport-changelog/6.8/7596.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 backport-changelog/6.8/7596.md diff --git a/backport-changelog/6.8/7596.md b/backport-changelog/6.8/7596.md new file mode 100644 index 00000000000000..2644b1ff947183 --- /dev/null +++ b/backport-changelog/6.8/7596.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7596 + +* https://github.com/WordPress/gutenberg/pull/66155 From 739d40ca6b1edf5af0772c2a118b0912aa814c68 Mon Sep 17 00:00:00 2001 From: ramon Date: Mon, 21 Oct 2024 14:56:21 +1100 Subject: [PATCH 6/8] Use hashed key built using stringified theme.json --- lib/class-wp-theme-json-resolver-gutenberg.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/class-wp-theme-json-resolver-gutenberg.php b/lib/class-wp-theme-json-resolver-gutenberg.php index 9c89f8b6db72f0..e7d45af2dc73af 100644 --- a/lib/class-wp-theme-json-resolver-gutenberg.php +++ b/lib/class-wp-theme-json-resolver-gutenberg.php @@ -861,9 +861,11 @@ public static function get_resolved_theme_uris( $theme_json ) { return $resolved_theme_uris; } - $current_stylesheet_directory = get_stylesheet_directory(); - if ( $current_stylesheet_directory && ! empty( static::$resolved_theme_uris_cache[ $current_stylesheet_directory ] ) ) { - return static::$resolved_theme_uris_cache[ $current_stylesheet_directory ]; + $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 ]; } $theme_json_data = $theme_json->get_raw_data(); @@ -917,9 +919,7 @@ public static function get_resolved_theme_uris( $theme_json ) { } } } - if ( $current_stylesheet_directory ) { - static::$resolved_theme_uris_cache[ $current_stylesheet_directory ] = $resolved_theme_uris; - } + static::$resolved_theme_uris_cache[ $resolved_theme_uris_cache_key ] = $resolved_theme_uris; return $resolved_theme_uris; } From b9762ebb4a8410c1620ed12565f5042c507dd554 Mon Sep 17 00:00:00 2001 From: ramon Date: Mon, 21 Oct 2024 15:02:40 +1100 Subject: [PATCH 7/8] Fix your tests, man! --- phpunit/class-wp-theme-json-resolver-test.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpunit/class-wp-theme-json-resolver-test.php b/phpunit/class-wp-theme-json-resolver-test.php index 614be1a403a3a9..bed1a171263f4b 100644 --- a/phpunit/class-wp-theme-json-resolver-test.php +++ b/phpunit/class-wp-theme-json-resolver-test.php @@ -1369,8 +1369,8 @@ public function test_get_resolved_theme_uris() { $this->assertSame( $expected_data, $actual, 'Resolved theme uris do not match.' ); // Test that resolved theme uris are cached. - $current_stylesheet_directory = get_stylesheet_directory(); - $expected_cache_data = array( "$current_stylesheet_directory" => $actual ); + $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.' ); } From 6140eb0a0f6cb80ffd73d492e4bccb392a8e8c51 Mon Sep 17 00:00:00 2001 From: ramon Date: Thu, 24 Oct 2024 17:01:22 +1100 Subject: [PATCH 8/8] remove dupe call --- lib/class-wp-theme-json-resolver-gutenberg.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/class-wp-theme-json-resolver-gutenberg.php b/lib/class-wp-theme-json-resolver-gutenberg.php index e7d45af2dc73af..5c6c8872bbfe36 100644 --- a/lib/class-wp-theme-json-resolver-gutenberg.php +++ b/lib/class-wp-theme-json-resolver-gutenberg.php @@ -868,8 +868,6 @@ public static function get_resolved_theme_uris( $theme_json ) { return static::$resolved_theme_uris_cache[ $resolved_theme_uris_cache_key ]; } - $theme_json_data = $theme_json->get_raw_data(); - // Using the same file convention when registering web fonts. See: WP_Font_Face_Resolver:: to_theme_file_uri. $placeholder = 'file:./';