diff --git a/src/wp-includes/default-filters.php b/src/wp-includes/default-filters.php index a4ecf677e2af1..a4758c3c02374 100644 --- a/src/wp-includes/default-filters.php +++ b/src/wp-includes/default-filters.php @@ -606,7 +606,8 @@ add_action( 'enqueue_block_assets', 'wp_enqueue_classic_theme_styles' ); add_action( 'enqueue_block_assets', 'wp_enqueue_registered_block_scripts_and_styles' ); add_action( 'enqueue_block_assets', 'enqueue_block_styles_assets', 30 ); -add_action( 'wp_default_styles', 'wp_load_classic_theme_block_styles_on_demand', 0 ); // Must happen before wp_default_styles() and register_core_block_style_handles(). +add_action( 'init', 'wp_load_classic_theme_block_styles_on_demand', 8 ); // Must happen before register_core_block_style_handles() at priority 9. +add_action( 'wp_default_styles', 'wp_load_classic_theme_block_styles_on_demand', 0 ); // Must happen before wp_default_styles() when WP_Styles is constructed before init priority 9. /* * `wp_enqueue_registered_block_scripts_and_styles` is bound to both * `enqueue_block_editor_assets` and `enqueue_block_assets` hooks diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php index 134d86c26a08a..3ce18d4429236 100644 --- a/src/wp-includes/script-loader.php +++ b/src/wp-includes/script-loader.php @@ -3677,7 +3677,10 @@ function wp_remove_surrounding_empty_script_tags( $contents ) { * the filters are added to cause {@see wp_should_load_separate_core_block_assets()} to return true. * * @since 6.9.0 - * @since 7.0.0 This is now invoked at the `wp_default_styles` action with priority 0 instead of at `init` with priority 8. + * @since 7.0.0 This is also invoked at the `wp_default_styles` action with priority 0 so that filters are present when + * `WP_Styles` is constructed before `init` priority 9. The `init` action at priority 8 is retained so + * `register_core_block_style_handles()` can opt in to separate block assets without having to construct + * `WP_Styles` first. * * @see _add_default_theme_supports() */ @@ -3692,7 +3695,9 @@ function wp_load_classic_theme_block_styles_on_demand(): void { * `wp_template_enhancement_output_buffer` filters added, but do so at priority zero so that applications which * wish to stream responses can more easily turn this off. */ - add_filter( 'wp_should_output_buffer_template_for_enhancement', '__return_true', 0 ); + if ( false === has_filter( 'wp_should_output_buffer_template_for_enhancement', '__return_true' ) ) { + add_filter( 'wp_should_output_buffer_template_for_enhancement', '__return_true', 0 ); + } // If a site has opted out of the template enhancement output buffer, then bail. if ( ! wp_should_output_buffer_template_for_enhancement() ) { @@ -3707,7 +3712,9 @@ function wp_load_classic_theme_block_styles_on_demand(): void { * this to be easily overridden by themes which wish to opt out. If a site has explicitly opted out of loading * separate block styles, then abort. */ - add_filter( 'should_load_separate_core_block_assets', '__return_true', 0 ); + if ( false === has_filter( 'should_load_separate_core_block_assets', '__return_true' ) ) { + add_filter( 'should_load_separate_core_block_assets', '__return_true', 0 ); + } if ( ! wp_should_load_separate_core_block_assets() ) { return; } @@ -3717,13 +3724,17 @@ function wp_load_classic_theme_block_styles_on_demand(): void { * As above, a priority of zero allows for this to be easily overridden by themes which wish to opt out. If a site * has explicitly opted out of loading block styles on demand, then abort. */ - add_filter( 'should_load_block_assets_on_demand', '__return_true', 0 ); + if ( false === has_filter( 'should_load_block_assets_on_demand', '__return_true' ) ) { + add_filter( 'should_load_block_assets_on_demand', '__return_true', 0 ); + } if ( ! wp_should_load_block_assets_on_demand() ) { return; } // Add hooks which require the presence of the output buffer. Ideally the above two filters could be added here, but they run too early. - add_action( 'wp_template_enhancement_output_buffer_started', 'wp_hoist_late_printed_styles' ); + if ( false === has_action( 'wp_template_enhancement_output_buffer_started', 'wp_hoist_late_printed_styles' ) ) { + add_action( 'wp_template_enhancement_output_buffer_started', 'wp_hoist_late_printed_styles' ); + } } /** diff --git a/tests/phpunit/tests/blocks/classicThemeBlockStylesOnDemand.php b/tests/phpunit/tests/blocks/classicThemeBlockStylesOnDemand.php new file mode 100644 index 0000000000000..ceaa1c35097cf --- /dev/null +++ b/tests/phpunit/tests/blocks/classicThemeBlockStylesOnDemand.php @@ -0,0 +1,128 @@ +original_wp_styles = $wp_styles; + } + + public function tear_down() { + global $wp_styles; + $wp_styles = $this->original_wp_styles; + + parent::tear_down(); + } + + /** + * @ticket 65272 + * + * @covers ::wp_load_classic_theme_block_styles_on_demand + * @covers ::register_core_block_style_handles + */ + public function test_register_core_block_style_handles_without_prior_wp_styles() { + global $wp_styles; + $wp_styles = null; + + remove_all_filters( 'should_load_separate_core_block_assets' ); + remove_all_filters( 'should_load_block_assets_on_demand' ); + remove_all_filters( 'wp_should_output_buffer_template_for_enhancement' ); + + remove_all_actions( 'init' ); + remove_all_actions( 'wp_default_styles' ); + + add_action( 'init', 'wp_load_classic_theme_block_styles_on_demand', 8 ); + add_action( 'init', 'register_core_block_style_handles', 9 ); + add_action( 'wp_default_styles', 'wp_load_classic_theme_block_styles_on_demand', 0 ); + add_action( 'wp_default_styles', 'wp_default_styles' ); + + add_theme_support( 'wp-block-styles' ); + + $this->assertFalse( $wp_styles instanceof WP_Styles, 'Expected WP_Styles to not be constructed yet.' ); + $this->assertFalse( wp_should_load_separate_core_block_assets(), 'Expected separate core block assets to be disabled before init.' ); + + do_action( 'init' ); + + $this->assertTrue( wp_should_load_separate_core_block_assets(), 'Expected separate core block assets to be enabled after init.' ); + $this->assertTrue( wp_style_is( 'wp-block-quote-theme', 'registered' ), 'Expected the Quote block theme stylesheet to be registered.' ); + } + + /** + * @ticket 65272 + * + * @covers ::wp_load_classic_theme_block_styles_on_demand + */ + public function test_wp_load_classic_theme_block_styles_on_demand_does_not_duplicate_hooks() { + switch_theme( 'default' ); + + remove_all_filters( 'should_load_separate_core_block_assets' ); + remove_all_filters( 'should_load_block_assets_on_demand' ); + remove_all_filters( 'wp_should_output_buffer_template_for_enhancement' ); + remove_all_actions( 'wp_template_enhancement_output_buffer_started' ); + + wp_load_classic_theme_block_styles_on_demand(); + wp_load_classic_theme_block_styles_on_demand(); + + global $wp_filter; + + $this->assertSame( 0, has_filter( 'should_load_separate_core_block_assets', '__return_true' ) ); + $this->assertCount( 1, $wp_filter['should_load_separate_core_block_assets']->callbacks[0] ); + $this->assertCount( 1, $wp_filter['should_load_block_assets_on_demand']->callbacks[0] ); + $this->assertCount( 1, $wp_filter['wp_should_output_buffer_template_for_enhancement']->callbacks[0] ); + $this->assertCount( 1, $wp_filter['wp_template_enhancement_output_buffer_started']->callbacks[10] ); + } + + /** + * @ticket 64846 + * @ticket 65272 + * + * @covers ::wp_load_classic_theme_block_styles_on_demand + * @covers ::wp_default_styles + */ + public function test_wp_block_library_uses_common_css_when_wp_styles_constructed_before_init() { + global $wp_styles; + $wp_styles = null; + + remove_all_filters( 'should_load_separate_core_block_assets' ); + remove_all_filters( 'should_load_block_assets_on_demand' ); + remove_all_filters( 'wp_should_output_buffer_template_for_enhancement' ); + + remove_all_actions( 'init' ); + remove_all_actions( 'wp_default_styles' ); + + add_action( 'init', 'wp_load_classic_theme_block_styles_on_demand', 8 ); + add_action( 'init', 'register_core_block_style_handles', 9 ); + add_action( 'wp_default_styles', 'wp_load_classic_theme_block_styles_on_demand', 0 ); + add_action( 'wp_default_styles', 'wp_default_styles' ); + + add_theme_support( 'wp-block-styles' ); + + wp_styles(); + + $this->assertSame( + '/' . WPINC . '/css/dist/block-library/common.css', + wp_styles()->registered['wp-block-library']->src, + 'Expected wp-block-library to use common.css when separate core block assets are enabled.' + ); + + do_action( 'init' ); + + $this->assertTrue( wp_should_load_separate_core_block_assets(), 'Expected separate core block assets to remain enabled after init.' ); + $this->assertTrue( wp_style_is( 'wp-block-quote-theme', 'registered' ), 'Expected the Quote block theme stylesheet to be registered after init.' ); + } +}