Widgets: Preserve classic sidebars when switching to a block theme.

When switching to a block theme, classic sidebars were orphaned and their widgets remapping to the `'wp_inactive_widgets'` sidebar . This changeset preserves the sidebars and their widgets, providing a migration path to a block theme without losing the widgets.

Classic sidebars are now:

* Stored in a new theme mod called `'wp_classic_sidebars'`;
* Restored to the `$wp_registered_sidebars` global variable when the `'widgets_init'` action fires (via a new internal function called `_wp_block_theme_register_classic_sidebars()`);
* And marked as `'inactive'` when interacting with sidebars REST API endpoint.

References:
* [https://github.com/WordPress/gutenberg/pull/45509 Gutenberg PR 45509] which adds an option for importing widgets from sidebars into template parts.

Follow-up to [50995], [6334].

Props mamaduka, audrasjb, hellofromTonya, ironprogrammer, jameskoster, joen, matveb, mukesh27, noisysocks, poena, youknowriad.
Fixes #57531.

git-svn-id: https://develop.svn.wordpress.org/trunk@55200 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Tonya Mork
2023-02-03 00:13:52 +00:00
parent a501f4f40d
commit 8ff5899348
6 changed files with 194 additions and 1 deletions
@@ -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
*/
@@ -0,0 +1,89 @@
<?php
/**
* Tests for _wp_block_theme_register_classic_sidebars().
*
* @group widgets
* @covers ::_wp_block_theme_register_classic_sidebars
*/
class Tests_Widgets_WpBlockThemeRegisterClassicSidebars extends WP_UnitTestCase {
/**
* Original global $wp_registered_sidebars.
*
* @var array
*/
private static $wp_registered_sidebars;
public static function set_up_before_class() {
global $wp_registered_sidebars;
parent::set_up_before_class();
// Store the original global before running tests.
static::$wp_registered_sidebars = $wp_registered_sidebars;
}
public function tear_down() {
// Restore the global after each test.
global $wp_registered_sidebars;
$wp_registered_sidebars = static::$wp_registered_sidebars;
parent::tear_down();
}
public function test_a_sidebar_should_be_registered() {
global $wp_registered_sidebars;
$sidebar_id = array_key_first( $wp_registered_sidebars );
$this->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()'
);
}
}