diff --git a/src/wp-includes/default-filters.php b/src/wp-includes/default-filters.php index 09be9e576b..f10dc6f280 100644 --- a/src/wp-includes/default-filters.php +++ b/src/wp-includes/default-filters.php @@ -626,6 +626,7 @@ add_filter( 'nav_menu_css_class', 'wp_nav_menu_remove_menu_item_has_children_cla add_action( 'after_setup_theme', 'wp_setup_widgets_block_editor', 1 ); add_action( 'init', 'wp_widgets_init', 1 ); add_action( 'change_locale', array( 'WP_Widget_Media', 'reset_default_labels' ) ); +add_action( 'widgets_init', '_wp_block_theme_register_classic_sidebars', 1 ); // Admin Bar. // Don't remove. Wrong way to disable. diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php index 449ad6bb5b..88a10a0a42 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php @@ -339,6 +339,10 @@ class WP_REST_Sidebars_Controller extends WP_REST_Controller { $sidebar['class'] = ''; } + if ( wp_is_block_theme() ) { + $sidebar['status'] = 'inactive'; + } + $fields = $this->get_fields_for_response( $request ); if ( rest_is_field_included( 'widgets', $fields ) ) { $sidebars = wp_get_sidebars_widgets(); diff --git a/src/wp-includes/theme.php b/src/wp-includes/theme.php index c3a4206530..c1623f4058 100644 --- a/src/wp-includes/theme.php +++ b/src/wp-includes/theme.php @@ -733,11 +733,12 @@ function locale_stylesheet() { * @global array $wp_theme_directories * @global WP_Customize_Manager $wp_customize * @global array $sidebars_widgets + * @global array $wp_registered_sidebars * * @param string $stylesheet Stylesheet name. */ function switch_theme( $stylesheet ) { - global $wp_theme_directories, $wp_customize, $sidebars_widgets; + global $wp_theme_directories, $wp_customize, $sidebars_widgets, $wp_registered_sidebars; $requirements = validate_theme_requirements( $stylesheet ); if ( is_wp_error( $requirements ) ) { @@ -814,6 +815,11 @@ function switch_theme( $stylesheet ) { } } + // Stores classic sidebars for later use by block themes. + if ( $new_theme->is_block_theme() ) { + set_theme_mod( 'wp_classic_sidebars', $wp_registered_sidebars ); + } + update_option( 'theme_switched', $old_theme->get_stylesheet() ); /** diff --git a/src/wp-includes/widgets.php b/src/wp-includes/widgets.php index 015cb3c48a..dc643ffe1c 100644 --- a/src/wp-includes/widgets.php +++ b/src/wp-includes/widgets.php @@ -2105,3 +2105,29 @@ function wp_check_widget_editor_deps() { } } } + +/** + * Registers the previous theme's sidebars for the block themes. + * + * @since 6.2.0 + * @access private + * + * @global array $wp_registered_sidebars Registered sidebars. + */ +function _wp_block_theme_register_classic_sidebars() { + global $wp_registered_sidebars; + + if ( ! wp_is_block_theme() ) { + return; + } + + $classic_sidebars = get_theme_mod( 'wp_classic_sidebars' ); + if ( empty( $classic_sidebars ) ) { + return; + } + + // Don't use `register_sidebar` since it will enable the `widgets` support for a theme. + foreach ( $classic_sidebars as $sidebar ) { + $wp_registered_sidebars[ $sidebar['id'] ] = $sidebar; + } +} diff --git a/tests/phpunit/tests/rest-api/rest-sidebars-controller.php b/tests/phpunit/tests/rest-api/rest-sidebars-controller.php index e2745f519f..21bbc092d1 100644 --- a/tests/phpunit/tests/rest-api/rest-sidebars-controller.php +++ b/tests/phpunit/tests/rest-api/rest-sidebars-controller.php @@ -860,6 +860,73 @@ class WP_Test_REST_Sidebars_Controller extends WP_Test_REST_Controller_Testcase ); } + /** + * @ticket 57531 + * @covers WP_Test_REST_Sidebars_Controller::prepare_item_for_response + */ + public function test_prepare_item_for_response_to_set_inactive_on_theme_switch() { + $request = new WP_REST_Request( 'GET', '/wp/v2/sidebars/sidebar-1' ); + + // Set up the test. + wp_widgets_init(); + $this->setup_widget( + 'widget_rss', + 1, + array( + 'title' => 'RSS test', + ) + ); + $this->setup_widget( + 'widget_text', + 1, + array( + 'text' => 'Custom text test', + ) + ); + $this->setup_sidebar( + 'sidebar-1', + array( + 'name' => 'Sidebar 1', + ), + array( 'text-1', 'rss-1' ) + ); + + // Validate the state before a theme switch. + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + $data = $this->remove_links( $data ); + + $this->assertSame( 'active', $data['status'] ); + $this->assertFalse( + get_theme_mod( 'wp_classic_sidebars' ), + 'wp_classic_sidebars theme mod should not exist before switching to block theme' + ); + + switch_theme( 'block-theme' ); + wp_widgets_init(); + + // Validate the state after a theme switch. + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + $data = $this->remove_links( $data ); + + $this->assertSame( + 'inactive', + $data['status'], + 'Sidebar status should have changed to inactive' + ); + $this->assertSame( + array( 'text-1', 'rss-1' ), + $data['widgets'], + 'The text and rss widgets should still in sidebar-1' + ); + $this->assertArrayHasKey( + 'sidebar-1', + get_theme_mod( 'wp_classic_sidebars' ), + 'sidebar-1 should be in "wp_classic_sidebars" theme mod' + ); + } + /** * @ticket 41683 */ diff --git a/tests/phpunit/tests/widgets/wpBlockThemeRegisterClassicSidebar.php b/tests/phpunit/tests/widgets/wpBlockThemeRegisterClassicSidebar.php new file mode 100644 index 0000000000..f8f8c519ae --- /dev/null +++ b/tests/phpunit/tests/widgets/wpBlockThemeRegisterClassicSidebar.php @@ -0,0 +1,89 @@ +assertNotEmpty( $sidebar_id ); + } + + /** + * @ticket 57531 + */ + public function test_should_reregister_previous_theme_sidebar() { + global $wp_registered_sidebars; + + $sidebar_id = array_key_first( $wp_registered_sidebars ); + + switch_theme( 'block-theme' ); + unregister_sidebar( $sidebar_id ); + + // Test before. + $this->assertArrayNotHasKey( + $sidebar_id, + $wp_registered_sidebars, + 'Sidebar should not be in registered sidebars after unregister' + ); + + _wp_block_theme_register_classic_sidebars(); + + // Test after. + $this->assertArrayHasKey( + $sidebar_id, + $wp_registered_sidebars, + 'Sidebar should be in registered sidebars after invoking _wp_block_theme_register_classic_sidebars()' + ); + } + + /** + * @ticket 57531 + */ + public function test_should_bail_out_when_theme_mod_is_empty() { + global $wp_registered_sidebars; + + // Test state before invoking. + $this->assertFalse( + get_theme_mod( 'wp_classic_sidebars' ), + 'Theme mod should not be set before invoking _wp_block_theme_register_classic_sidebars()' + ); + + $before = $wp_registered_sidebars; + _wp_block_theme_register_classic_sidebars(); + + // Test state after invoking. + $this->assertSameSetsWithIndex( + $before, + $wp_registered_sidebars, + 'No change should happen after invoking _wp_block_theme_register_classic_sidebars()' + ); + } +}