From 84a59fe5f7e9f9b32c680b4cef3f5943acb5ff38 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Mon, 6 Feb 2023 19:57:41 +0000 Subject: [PATCH] Themes: Add caching to `WP_Theme::is_block_theme()`. This changeset adds a `block_theme` entry in the theme cache data, similar to the existing entries `headers`, `errors`, `stylesheet`, and `template`. Props spacedmonkey, costdev, joemcgill, flixos90, mukesh27, adamsilverstein. Fixes #57114. git-svn-id: https://develop.svn.wordpress.org/trunk@55236 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/class-wp-theme.php | 96 +++++++++++++++++---------- tests/phpunit/tests/theme/wpTheme.php | 57 ++++++++++++++++ 2 files changed, 118 insertions(+), 35 deletions(-) diff --git a/src/wp-includes/class-wp-theme.php b/src/wp-includes/class-wp-theme.php index f95f49e205..5cf8f9437a 100644 --- a/src/wp-includes/class-wp-theme.php +++ b/src/wp-includes/class-wp-theme.php @@ -113,6 +113,14 @@ final class WP_Theme implements ArrayAccess { */ private $headers_sanitized; + /** + * Is this theme a block theme. + * + * @since 6.2.0 + * @var bool + */ + private $block_theme; + /** * Header name from the theme's style.css after being translated. * @@ -250,7 +258,7 @@ final class WP_Theme implements ArrayAccess { $cache = $this->cache_get( 'theme' ); if ( is_array( $cache ) ) { - foreach ( array( 'errors', 'headers', 'template' ) as $key ) { + foreach ( array( 'block_theme', 'errors', 'headers', 'template' ) as $key ) { if ( isset( $cache[ $key ] ) ) { $this->$key = $cache[ $key ]; } @@ -275,14 +283,16 @@ final class WP_Theme implements ArrayAccess { } else { $this->errors = new WP_Error( 'theme_no_stylesheet', __( 'Stylesheet is missing.' ) ); } - $this->template = $this->stylesheet; + $this->template = $this->stylesheet; + $this->block_theme = false; $this->cache_add( 'theme', array( - 'headers' => $this->headers, - 'errors' => $this->errors, - 'stylesheet' => $this->stylesheet, - 'template' => $this->template, + 'block_theme' => $this->block_theme, + 'headers' => $this->headers, + 'errors' => $this->errors, + 'stylesheet' => $this->stylesheet, + 'template' => $this->template, ) ); if ( ! file_exists( $this->theme_root ) ) { // Don't cache this one. @@ -293,13 +303,15 @@ final class WP_Theme implements ArrayAccess { $this->headers['Name'] = $this->stylesheet; $this->errors = new WP_Error( 'theme_stylesheet_not_readable', __( 'Stylesheet is not readable.' ) ); $this->template = $this->stylesheet; + $this->block_theme = false; $this->cache_add( 'theme', array( - 'headers' => $this->headers, - 'errors' => $this->errors, - 'stylesheet' => $this->stylesheet, - 'template' => $this->template, + 'block_theme' => $this->block_theme, + 'headers' => $this->headers, + 'errors' => $this->errors, + 'stylesheet' => $this->stylesheet, + 'template' => $this->template, ) ); return; @@ -327,9 +339,10 @@ final class WP_Theme implements ArrayAccess { $this->cache_add( 'theme', array( - 'headers' => $this->headers, - 'errors' => $this->errors, - 'stylesheet' => $this->stylesheet, + 'block_theme' => $this->is_block_theme(), + 'headers' => $this->headers, + 'errors' => $this->errors, + 'stylesheet' => $this->stylesheet, ) ); @@ -363,10 +376,11 @@ final class WP_Theme implements ArrayAccess { $this->cache_add( 'theme', array( - 'headers' => $this->headers, - 'errors' => $this->errors, - 'stylesheet' => $this->stylesheet, - 'template' => $this->template, + 'block_theme' => $this->is_block_theme(), + 'headers' => $this->headers, + 'errors' => $this->errors, + 'stylesheet' => $this->stylesheet, + 'template' => $this->template, ) ); return; @@ -399,10 +413,11 @@ final class WP_Theme implements ArrayAccess { $this->cache_add( 'theme', array( - 'headers' => $this->headers, - 'errors' => $this->errors, - 'stylesheet' => $this->stylesheet, - 'template' => $this->template, + 'block_theme' => $this->is_block_theme(), + 'headers' => $this->headers, + 'errors' => $this->errors, + 'stylesheet' => $this->stylesheet, + 'template' => $this->template, ) ); $this->parent = new WP_Theme( $this->template, $this->theme_root, $this ); @@ -426,10 +441,11 @@ final class WP_Theme implements ArrayAccess { $_child->cache_add( 'theme', array( - 'headers' => $_child->headers, - 'errors' => $_child->errors, - 'stylesheet' => $_child->stylesheet, - 'template' => $_child->template, + 'block_theme' => $_child->is_block_theme(), + 'headers' => $_child->headers, + 'errors' => $_child->errors, + 'stylesheet' => $_child->stylesheet, + 'template' => $_child->template, ) ); // The two themes actually reference each other with the Template header. @@ -445,10 +461,11 @@ final class WP_Theme implements ArrayAccess { $this->cache_add( 'theme', array( - 'headers' => $this->headers, - 'errors' => $this->errors, - 'stylesheet' => $this->stylesheet, - 'template' => $this->template, + 'block_theme' => $this->is_block_theme(), + 'headers' => $this->headers, + 'errors' => $this->errors, + 'stylesheet' => $this->stylesheet, + 'template' => $this->template, ) ); } @@ -465,10 +482,11 @@ final class WP_Theme implements ArrayAccess { // We're good. If we didn't retrieve from cache, set it. if ( ! is_array( $cache ) ) { $cache = array( - 'headers' => $this->headers, - 'errors' => $this->errors, - 'stylesheet' => $this->stylesheet, - 'template' => $this->template, + 'block_theme' => $this->is_block_theme(), + 'headers' => $this->headers, + 'errors' => $this->errors, + 'stylesheet' => $this->stylesheet, + 'template' => $this->template, ); // If the parent theme is in another root, we'll want to cache this. Avoids an entire branch of filesystem calls above. if ( isset( $theme_root_template ) ) { @@ -762,6 +780,7 @@ final class WP_Theme implements ArrayAccess { $this->errors = null; $this->headers_sanitized = null; $this->name_translated = null; + $this->block_theme = null; $this->headers = array(); $this->__construct( $this->stylesheet, $this->theme_root ); } @@ -1491,18 +1510,25 @@ final class WP_Theme implements ArrayAccess { * @return bool */ public function is_block_theme() { + if ( isset( $this->block_theme ) ) { + return $this->block_theme; + } + $paths_to_index_block_template = array( $this->get_file_path( '/block-templates/index.html' ), $this->get_file_path( '/templates/index.html' ), ); + $this->block_theme = false; + foreach ( $paths_to_index_block_template as $path_to_index_block_template ) { if ( is_file( $path_to_index_block_template ) && is_readable( $path_to_index_block_template ) ) { - return true; + $this->block_theme = true; + break; } } - return false; + return $this->block_theme; } /** diff --git a/tests/phpunit/tests/theme/wpTheme.php b/tests/phpunit/tests/theme/wpTheme.php index 0ded32d77b..05e15a9354 100644 --- a/tests/phpunit/tests/theme/wpTheme.php +++ b/tests/phpunit/tests/theme/wpTheme.php @@ -275,6 +275,63 @@ class Tests_Theme_wpTheme extends WP_UnitTestCase { $this->assertSame( $expected, $theme->is_block_theme() ); } + /** + * @ticket 57114 + * + * @covers WP_Theme::is_block_theme + * + * @dataProvider data_is_block_theme + */ + public function test_is_block_theme_property( $theme_dir, $expected ) { + $theme = new WP_Theme( $theme_dir, $this->theme_root ); + $theme->is_block_theme(); + $reflection = new ReflectionClass( $theme ); + $reflection_property = $reflection->getProperty( 'block_theme' ); + $reflection_property->setAccessible( true ); + + $this->assertSame( $expected, $reflection_property->getValue( $theme ) ); + } + + /** + * @ticket 57114 + * + * @covers WP_Theme::is_block_theme + * @covers WP_Theme::cache_get + */ + public function test_is_block_theme_check_cache() { + $filter = new MockAction(); + add_filter( 'theme_file_path', array( $filter, 'filter' ) ); + + $theme1 = new WP_Theme( 'block-theme', $this->theme_root ); + // First run. + $this->assertTrue( $theme1->is_block_theme(), 'is_block_theme should return true on first run' ); + + $theme2 = new WP_Theme( 'block-theme', $this->theme_root ); + // Second run. + $this->assertTrue( $theme2->is_block_theme(), 'is_block_theme should return true on second run' ); + $this->assertCount( 0, $filter->get_events(), 'Should only be 0, as second run should be cached' ); + } + + /** + * @ticket 57114 + * + * @covers WP_Theme::is_block_theme + * @covers WP_Theme::cache_delete + */ + public function test_is_block_theme_delete_cache() { + $filter = new MockAction(); + add_filter( 'theme_file_path', array( $filter, 'filter' ) ); + + $theme = new WP_Theme( 'block-theme', $this->theme_root ); + // First run. + $this->assertTrue( $theme->is_block_theme(), 'is_block_theme should return true on first run' ); + // Clear cache. + $theme->cache_delete(); + // Second run. + $this->assertTrue( $theme->is_block_theme(), 'is_block_theme should return true on second run' ); + $this->assertCount( 2, $filter->get_events(), 'Should only be 4, as second run should not be cached' ); + } + /** * Test get_files for an existing theme. *