From 74d3772816c20cf40294714061a3f69e891144f6 Mon Sep 17 00:00:00 2001 From: Joe McGill Date: Fri, 27 Oct 2023 19:23:24 +0000 Subject: [PATCH] Upgrade/Install: Skip registering theme block patterns during the upgrade process. This fixes a bug during the database upgrade process where a theme's `functions.php` file may not be loaded, leading to potential exceptions if the theme's pattern files use symbols (classes, functions, constants, etc.) that are declared only when the `functions.php` file is loaded. To do so, a check for `wp_get_active_and_valid_themes()` is added early to `_register_theme_block_patterns()`, which returns early if no active or valid themes are returned. Props fabiankaegy, rajinsharwar, pbiron, huzaifaalmesbah, hellofromTonya, peterwilsoncc, joemcgill. Reviewed by hellofromTonya. Merges [57021] to the 6.4 branch. Fixes #59723. git-svn-id: https://develop.svn.wordpress.org/branches/6.4@57023 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/block-patterns.php | 11 ++++ .../tests/blocks/wpBlockPatternsRegistry.php | 64 +++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/src/wp-includes/block-patterns.php b/src/wp-includes/block-patterns.php index 7f20d9a894..b74f75611f 100644 --- a/src/wp-includes/block-patterns.php +++ b/src/wp-includes/block-patterns.php @@ -328,6 +328,17 @@ function _register_remote_theme_patterns() { * @access private */ function _register_theme_block_patterns() { + + /* + * During the bootstrap process, a check for active and valid themes is run. + * If no themes are returned, the theme's functions.php file will not be loaded, + * which can lead to errors if patterns expect some variables or constants to + * already be set at this point, so bail early if that is the case. + */ + if ( empty( wp_get_active_and_valid_themes() ) ) { + return; + } + /* * Register patterns for the active theme. If the theme is a child theme, * let it override any patterns from the parent theme that shares the same slug. diff --git a/tests/phpunit/tests/blocks/wpBlockPatternsRegistry.php b/tests/phpunit/tests/blocks/wpBlockPatternsRegistry.php index 61298d1b16..01050a2c5f 100644 --- a/tests/phpunit/tests/blocks/wpBlockPatternsRegistry.php +++ b/tests/phpunit/tests/blocks/wpBlockPatternsRegistry.php @@ -482,4 +482,68 @@ class Tests_Blocks_wpBlockPattersRegistry extends WP_UnitTestCase { $result = $this->registry->is_registered( 'test/one' ); $this->assertTrue( $result ); } + + /** + * Ensures theme patterns are registered on init. + * + * @ticket 59723 + * + * @covers ::_register_theme_block_patterns + */ + public function test_register_theme_block_patterns_on_init() { + // This test needs to use access static class properties. + $registry = WP_Block_Patterns_Registry::get_instance(); + + // Ensure we're using a theme with patterns. + switch_theme( 'twentytwentythree' ); + + $theme = wp_get_theme(); + $theme_patterns = array_values( wp_list_pluck( $theme->get_block_patterns(), 'slug' ) ); + + // This helper is fired on the init hook. + _register_theme_block_patterns(); + + $registered = wp_list_pluck( $registry->get_all_registered(), 'name' ); + + // Cleanup patterns registry. + foreach ( $theme_patterns as $pattern ) { + $registry->unregister( $pattern ); + } + + $this->assertSameSets( $theme_patterns, array_intersect( $theme_patterns, $registered ), 'Could not confirm theme patterns were registered.' ); + } + + /** + * Ensures theme patterns are not registered when no themes are active and valid. + * + * @ticket 59723 + * + * @covers ::_register_theme_block_patterns + */ + public function test_register_theme_block_patterns_on_init_skipped_during_install() { + // This test needs to use access static class properties. + $registry = WP_Block_Patterns_Registry::get_instance(); + + // Ensure we're using a theme with patterns. + switch_theme( 'twentytwentythree' ); + + $theme = wp_get_theme(); + $theme_patterns = array_values( wp_list_pluck( $theme->get_block_patterns(), 'slug' ) ); + + /* + * This will short-circuit theme activation. + * @see wp_get_active_and_valid_themes(). + */ + wp_installing( true ); + + // This helper is fired on the init hook. + _register_theme_block_patterns(); + + $registered = wp_list_pluck( $registry->get_all_registered(), 'name' ); + + // Cleanup. + wp_installing( false ); + + $this->assertEmpty( array_intersect( $theme_patterns, $registered ), 'Theme patterns were were incorrectly registered.' ); + } }