Make WordPress Core

Changeset 55200


Ignore:
Timestamp:
02/03/2023 12:13:52 AM (18 months ago)
Author:
hellofromTonya
Message:

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:

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

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

Location:
trunk
Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/default-filters.php

    r55192 r55200  
    627627add_action( 'init', 'wp_widgets_init', 1 );
    628628add_action( 'change_locale', array( 'WP_Widget_Media', 'reset_default_labels' ) );
     629add_action( 'widgets_init', '_wp_block_theme_register_classic_sidebars', 1 );
    629630
    630631// Admin Bar.
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php

    r53760 r55200  
    340340        }
    341341
     342        if ( wp_is_block_theme() ) {
     343            $sidebar['status'] = 'inactive';
     344        }
     345
    342346        $fields = $this->get_fields_for_response( $request );
    343347        if ( rest_is_field_included( 'widgets', $fields ) ) {
  • trunk/src/wp-includes/theme.php

    r55014 r55200  
    734734 * @global WP_Customize_Manager $wp_customize
    735735 * @global array                $sidebars_widgets
     736 * @global array                $wp_registered_sidebars
    736737 *
    737738 * @param string $stylesheet Stylesheet name.
    738739 */
    739740function switch_theme( $stylesheet ) {
    740     global $wp_theme_directories, $wp_customize, $sidebars_widgets;
     741    global $wp_theme_directories, $wp_customize, $sidebars_widgets, $wp_registered_sidebars;
    741742
    742743    $requirements = validate_theme_requirements( $stylesheet );
     
    813814            remove_theme_mod( 'sidebars_widgets' );
    814815        }
     816    }
     817
     818    // Stores classic sidebars for later use by block themes.
     819    if ( $new_theme->is_block_theme() ) {
     820        set_theme_mod( 'wp_classic_sidebars', $wp_registered_sidebars );
    815821    }
    816822
  • trunk/src/wp-includes/widgets.php

    r54541 r55200  
    21062106    }
    21072107}
     2108
     2109/**
     2110 * Registers the previous theme's sidebars for the block themes.
     2111 *
     2112 * @since 6.2.0
     2113 * @access private
     2114 *
     2115 * @global array $wp_registered_sidebars Registered sidebars.
     2116 */
     2117function _wp_block_theme_register_classic_sidebars() {
     2118    global $wp_registered_sidebars;
     2119
     2120    if ( ! wp_is_block_theme() ) {
     2121        return;
     2122    }
     2123
     2124    $classic_sidebars = get_theme_mod( 'wp_classic_sidebars' );
     2125    if ( empty( $classic_sidebars ) ) {
     2126        return;
     2127    }
     2128
     2129    // Don't use `register_sidebar` since it will enable the `widgets` support for a theme.
     2130    foreach ( $classic_sidebars as $sidebar ) {
     2131        $wp_registered_sidebars[ $sidebar['id'] ] = $sidebar;
     2132    }
     2133}
  • trunk/tests/phpunit/tests/rest-api/rest-sidebars-controller.php

    r54896 r55200  
    862862
    863863    /**
     864     * @ticket 57531
     865     * @covers WP_Test_REST_Sidebars_Controller::prepare_item_for_response
     866     */
     867    public function test_prepare_item_for_response_to_set_inactive_on_theme_switch() {
     868        $request = new WP_REST_Request( 'GET', '/wp/v2/sidebars/sidebar-1' );
     869
     870        // Set up the test.
     871        wp_widgets_init();
     872        $this->setup_widget(
     873            'widget_rss',
     874            1,
     875            array(
     876                'title' => 'RSS test',
     877            )
     878        );
     879        $this->setup_widget(
     880            'widget_text',
     881            1,
     882            array(
     883                'text' => 'Custom text test',
     884            )
     885        );
     886        $this->setup_sidebar(
     887            'sidebar-1',
     888            array(
     889                'name' => 'Sidebar 1',
     890            ),
     891            array( 'text-1', 'rss-1' )
     892        );
     893
     894        // Validate the state before a theme switch.
     895        $response = rest_get_server()->dispatch( $request );
     896        $data     = $response->get_data();
     897        $data     = $this->remove_links( $data );
     898
     899        $this->assertSame( 'active', $data['status'] );
     900        $this->assertFalse(
     901            get_theme_mod( 'wp_classic_sidebars' ),
     902            'wp_classic_sidebars theme mod should not exist before switching to block theme'
     903        );
     904
     905        switch_theme( 'block-theme' );
     906        wp_widgets_init();
     907
     908        // Validate the state after a theme switch.
     909        $response = rest_get_server()->dispatch( $request );
     910        $data     = $response->get_data();
     911        $data     = $this->remove_links( $data );
     912
     913        $this->assertSame(
     914            'inactive',
     915            $data['status'],
     916            'Sidebar status should have changed to inactive'
     917        );
     918        $this->assertSame(
     919            array( 'text-1', 'rss-1' ),
     920            $data['widgets'],
     921            'The text and rss widgets should still in sidebar-1'
     922        );
     923        $this->assertArrayHasKey(
     924            'sidebar-1',
     925            get_theme_mod( 'wp_classic_sidebars' ),
     926            'sidebar-1 should be in "wp_classic_sidebars" theme mod'
     927        );
     928    }
     929
     930    /**
    864931     * @ticket 41683
    865932     */
Note: See TracChangeset for help on using the changeset viewer.