Make WordPress Core


Ignore:
Timestamp:
09/21/2017 06:45:03 PM (7 years ago)
Author:
obenland
Message:

Widgets: Improved sidebar mapping on theme switch

Builds on efforts brought forward in #17979.

This will send sidebars through three levels of mapping:

  1. If both themes have only one sidebar, that gets mapped.
  2. If both themes have sidebars with the same slug, they get mapped.
  3. Sidebars that (even partially) match slugs from a similar kind of sidebar will get mapped.

Finally, if the theme has previously been active and we have a record of its
sidebar configuration then, any unmapped sidebar will be restored to its
previous state.

Props westonruter, obenland, alexvorn2, timmydcrawford.
See #39693.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/widgets.php

    r41327 r41555  
    710710
    711711        wp_widgets_init();
    712         $this->register_sidebars( array( 'sidebar-1', 'sidebar-2','sidebar-3', 'wp_inactive_widgets' ) );
    713 
     712        $this->register_sidebars( array( 'sidebar-1', 'sidebar-2', 'sidebar-3', 'wp_inactive_widgets' ) );
     713
     714        // Test restoring sidebars widgets when previously activated.
    714715        set_theme_mod( 'sidebars_widgets', array(
    715             'time' => time(),
    716             'data' => array(
    717                 'sidebar-1' => array( 'tag_cloud-1' ),
    718                 'sidebar-2' => array( 'text-1' ),
    719                 'sidebar-3' => array( 'unregistered_widget-1' ),
    720                 'fantasy'   => array( 'archives-2' ),
    721                 'wp_inactive_widgets' => array(),
    722             ),
     716            'sidebar-1' => array( 'tag_cloud-1' ),
     717            'sidebar-2' => array(),
     718            'sidebar-3' => array( 'unregistered_widget-1', 'text-1', 'media_image-1' ),
     719            'orphaned_widgets_1' => array( 'media_video-2' ),
    723720        ) );
    724721
     722        $sidebars_widgets = array(
     723            'sidebar-1' => array( 'tag_cloud-1' ),
     724            'sidebar-2' => array( 'text-1' ),
     725            'fantasy'   => array( 'archives-2' ),
     726            'wp_inactive_widgets' => array(),
     727        );
     728
    725729        $result = retrieve_widgets( true );
    726730
    727         $_wp_sidebars_widgets = array();
    728731        $this->assertInternalType( 'array', $result );
    729         $this->assertNotEmpty( $result );
     732        $this->assertEquals( $result, $sidebars_widgets );
    730733
    731734        foreach ( $sidebars_widgets as $widgets ) {
     
    735738        $this->assertContains( 'tag_cloud-1', $sidebars_widgets['sidebar-1'] );
    736739        $this->assertContains( 'text-1', $sidebars_widgets['sidebar-2'] );
    737         $this->assertContains( 'archives-2', $sidebars_widgets['orphaned_widgets_1'] );
     740        $this->assertContains( 'media_image-1', $sidebars_widgets['sidebar-3'] );
     741        $this->assertArrayNotHasKey( 'orphaned_widgets_1', $sidebars_widgets );
    738742
    739743        // Unregistered widget should be filtered out.
    740         $this->assertEmpty( $sidebars_widgets['sidebar-3'] );
    741 
    742         // 6 default widgets - 1 active text widget = 5.
    743         $this->assertCount( 5, $sidebars_widgets['wp_inactive_widgets'] );
     744        $this->assertNotContains( 'unregistered_widget-1', $sidebars_widgets['sidebar-3'] );
     745
     746        // 6 default widgets - 1 active text widget + 1 orphaned widget = 6.
     747        $this->assertCount( 6, $sidebars_widgets['wp_inactive_widgets'] );
     748
    744749        $this->assertContains( 'meta-2',            $sidebars_widgets['wp_inactive_widgets'] );
    745750        $this->assertContains( 'search-2',          $sidebars_widgets['wp_inactive_widgets'] );
     751        $this->assertContains( 'archives-2',        $sidebars_widgets['wp_inactive_widgets'] );
    746752        $this->assertContains( 'categories-2',      $sidebars_widgets['wp_inactive_widgets'] );
    747753        $this->assertContains( 'recent-posts-2',    $sidebars_widgets['wp_inactive_widgets'] );
    748754        $this->assertContains( 'recent-comments-2', $sidebars_widgets['wp_inactive_widgets'] );
    749 
    750         // Theme mode with previous widgets was removed.
    751         $this->assertFalse( get_theme_mod( 'sidebars_widgets' ) );
    752755
    753756        // Sidebar_widgets option was updated.
     
    776779
    777780        // $sidebars_widgets matches registered sidebars.
    778         $this->assertNull( $result );
     781        $this->assertInternalType( 'array', $result );
     782        $this->assertEquals( $result, $sidebars_widgets );
    779783
    780784        foreach ( $sidebars_widgets as $widgets ) {
     
    785789        $this->assertContains( 'text-1', $sidebars_widgets['sidebar-2'] );
    786790
    787         // No widget validity check when $sidebars_widgets matches registered sidebars.
    788         $this->assertContains( 'custom_widget-1', $sidebars_widgets['sidebar-3'] );
     791        // Invalid widget removed, even when $sidebars_widgets matches registered sidebars.
     792        $this->assertEmpty( $sidebars_widgets['sidebar-3'] );
    789793
    790794        // No lost widgets when $sidebars_widgets matches registered sidebars.
     
    815819        $_wp_sidebars_widgets = array();
    816820        $this->assertInternalType( 'array', $result );
    817         $this->assertNotEmpty( $result );
     821        $this->assertEquals( $result, $sidebars_widgets );
    818822
    819823        foreach ( $sidebars_widgets as $widgets ) {
     
    858862        $_wp_sidebars_widgets = array();
    859863        $this->assertInternalType( 'array', $result );
    860         $this->assertNotEmpty( $result );
     864        $this->assertEquals( $result, $sidebars_widgets );
    861865
    862866        foreach ( $sidebars_widgets as $widgets ) {
     
    864868        }
    865869
    866         /*
    867          * Only returns intersection of registered sidebars and saved sidebars,
    868          * so neither fantasy-sidebar nor sidebar-3 will make the cut.
    869          */
     870        // This sidebar is not registered anymore.
    870871        $this->assertArrayNotHasKey( 'fantasy', $sidebars_widgets );
    871         $this->assertArrayNotHasKey( 'sidebar-3', $sidebars_widgets );
    872 
    873         // archives-2 ends up as an orphan because of the above behavior.
    874         $this->assertContains( 'archives-2', $sidebars_widgets['orphaned_widgets_1'] );
     872        $this->assertArrayHasKey( 'sidebar-3', $sidebars_widgets );
     873
    875874        $this->assertContains( 'tag_cloud-1', $sidebars_widgets['sidebar-1'] );
    876875        $this->assertContains( 'text-1', $sidebars_widgets['sidebar-2'] );
    877876
    878877        // 6 default widgets - 1 active text widget = 5.
    879         $this->assertCount( 5, $sidebars_widgets['wp_inactive_widgets'] );
     878        $this->assertCount( 6, $sidebars_widgets['wp_inactive_widgets'] );
    880879
    881880        $this->assertContains( 'meta-2',            $sidebars_widgets['wp_inactive_widgets'] );
    882881        $this->assertContains( 'search-2',          $sidebars_widgets['wp_inactive_widgets'] );
     882        // archives-2 ends up as inactive because fantasy sidebar doesn't exist.
     883        $this->assertContains( 'archives-2',        $sidebars_widgets['wp_inactive_widgets'] );
    883884        $this->assertContains( 'categories-2',      $sidebars_widgets['wp_inactive_widgets'] );
    884885        $this->assertContains( 'recent-posts-2',    $sidebars_widgets['wp_inactive_widgets'] );
     
    901902
    902903        $old_sidebars_widgets = array(
    903             'time' => time(),
    904             'data' => array(
    905                 'sidebar-1' => array( 'tag_cloud-1' ),
    906                 'sidebar-2' => array( 'text-1' ),
    907                 'sidebar-3' => array( 'unregistered_widget-1' ),
    908                 'fantasy'   => array( 'archives-2' ),
    909                 'wp_inactive_widgets' => array(),
    910             ),
     904            'sidebar-1' => array( 'tag_cloud-1' ),
     905            'sidebar-2' => array( 'text-1' ),
     906            'sidebar-3' => array( 'unregistered_widget-1' ),
     907            'fantasy'   => array( 'archives-2' ),
     908            'wp_inactive_widgets' => array(),
    911909        );
    912910        set_theme_mod( 'sidebars_widgets', $old_sidebars_widgets );
     
    916914        $_wp_sidebars_widgets = array();
    917915        $this->assertInternalType( 'array', $result );
    918         $this->assertNotEmpty( $result );
     916        $this->assertEquals( $result, $sidebars_widgets );
    919917
    920918        foreach ( $sidebars_widgets as $widgets ) {
     
    924922        $this->assertContains( 'tag_cloud-1', $sidebars_widgets['sidebar-1'] );
    925923        $this->assertContains( 'text-1', $sidebars_widgets['sidebar-2'] );
    926         $this->assertContains( 'archives-2', $sidebars_widgets['orphaned_widgets_1'] );
    927924        $this->assertArrayHasKey( 'sidebar-3', $sidebars_widgets );
    928925        $this->assertEmpty( $sidebars_widgets['sidebar-3'] );
    929         $this->assertCount( 5, $sidebars_widgets['wp_inactive_widgets'] );
     926        $this->assertCount( 6, $sidebars_widgets['wp_inactive_widgets'] );
    930927
    931928        $this->assertContains( 'meta-2',            $sidebars_widgets['wp_inactive_widgets'] );
    932929        $this->assertContains( 'search-2',          $sidebars_widgets['wp_inactive_widgets'] );
     930        $this->assertContains( 'archives-2',        $sidebars_widgets['wp_inactive_widgets'] );
    933931        $this->assertContains( 'categories-2',      $sidebars_widgets['wp_inactive_widgets'] );
    934932        $this->assertContains( 'recent-posts-2',    $sidebars_widgets['wp_inactive_widgets'] );
     
    941939        $this->assertNotEquals( $sidebars_widgets, wp_get_sidebars_widgets() );
    942940    }
     941
     942    function test_retreive_widgets_with_single_widget() {
     943        global $sidebars_widgets;
     944
     945        wp_widgets_init();
     946
     947        // Register single-dimension widget.
     948        wp_register_sidebar_widget( 'single', 'Single', '__return_false', array(), array() );
     949        wp_register_widget_control( 'single', 'Single', '__return_false', array(), array() );
     950
     951        $this->register_sidebars( array( 'sidebar-1', 'sidebar-2', 'wp_inactive_widgets' ) );
     952
     953        $sidebars_widgets = array(
     954            'sidebar-1' => array( 'tag_cloud-1' ),
     955            'wp_inactive_widgets' => array(),
     956        );
     957
     958        // Theme changed.
     959        $result = retrieve_widgets( true );
     960
     961        $this->assertContains( 'single', $result['wp_inactive_widgets'] );
     962    }
     963
     964    /**
     965     * Test _wp_remove_unregistered_widgets.
     966     *
     967     * @covers _wp_remove_unregistered_widgets()
     968     */
     969    public function test__wp_remove_unregistered_widgets() {
     970        $widgets = array(
     971            'sidebar-1' => array( 'tag_cloud-1' ),
     972            'sidebar-2' => array( 'text-1' ),
     973            'fantasy'   => array( 'archives-2' ),
     974            'wp_inactive_widgets' => array(),
     975            'array_version' => 3,
     976        );
     977
     978        $whitelist = array( 'tag_cloud-1', 'text-1' );
     979
     980        $filtered_widgets = _wp_remove_unregistered_widgets( $widgets, $whitelist );
     981
     982        $this->assertInternalType( 'array', $filtered_widgets );
     983        $this->assertArrayHasKey( 'fantasy', $filtered_widgets );
     984        $this->assertEmpty( $filtered_widgets['fantasy'] );
     985        $this->assertArrayHasKey( 'array_version', $filtered_widgets );
     986        $this->assertEquals( 3, $filtered_widgets['array_version'] );
     987        $this->assertInternalType( 'integer', $filtered_widgets['array_version'] );
     988    }
     989
     990    /**
     991     * wp_map_sidebars_widgets Tests.
     992     */
     993
     994    /**
     995     * Two themes with one sidebar each should just map, switching to a theme not previously-active.
     996     *
     997     * @covers wp_map_sidebars_widgets()
     998     */
     999    public function test_one_sidebar_each() {
     1000        $this->register_sidebars( array( 'primary' ) );
     1001        $prev_theme_sidebars = array(
     1002            'unique-slug' => 1,
     1003        );
     1004
     1005        $new_next_theme_sidebars = wp_map_sidebars_widgets( $prev_theme_sidebars );
     1006
     1007        $expected_sidebars = array(
     1008            'primary' => 1,
     1009            'wp_inactive_widgets' => array(),
     1010        );
     1011        $this->assertEquals( $expected_sidebars, $new_next_theme_sidebars );
     1012    }
     1013
     1014    /**
     1015     * Sidebars with the same name should map, switching to a theme not previously-active.
     1016     *
     1017     * @covers wp_map_sidebars_widgets()
     1018     */
     1019    public function test_sidebars_with_same_slug() {
     1020        $this->register_sidebars( array( 'primary', 'secondary' ) );
     1021        $prev_theme_sidebars = array(
     1022            'primary' => 1,
     1023            'secondary' => 2,
     1024            'wp_inactive_widgets' => array(),
     1025        );
     1026
     1027        $new_next_theme_sidebars = wp_map_sidebars_widgets( $prev_theme_sidebars );
     1028
     1029        $this->assertEquals( $prev_theme_sidebars, $new_next_theme_sidebars );
     1030    }
     1031
     1032    /**
     1033     * Make educated guesses on theme sidebars.
     1034     *
     1035     * @covers wp_map_sidebars_widgets()
     1036     */
     1037    public function test_sidebar_guessing() {
     1038        $this->register_sidebars( array( 'primary', 'secondary' ) );
     1039
     1040        $prev_theme_sidebars = array(
     1041            'header' => array(),
     1042            'footer' => array(),
     1043        );
     1044
     1045        $new_next_theme_sidebars = wp_map_sidebars_widgets( $prev_theme_sidebars );
     1046
     1047        $expected_sidebars = array(
     1048            'primary' => array(),
     1049            'secondary' => array(),
     1050            'wp_inactive_widgets' => array(),
     1051        );
     1052        $this->assertEquals( $expected_sidebars, $new_next_theme_sidebars );
     1053    }
     1054
     1055    /**
     1056     * Make sure two sidebars that fall in the same group don't get the same menu assigned.
     1057     *
     1058     * @covers wp_map_sidebars_widgets()
     1059     */
     1060    public function test_sidebar_guessing_one_menu_per_group() {
     1061        $this->register_sidebars( array( 'primary' ) );
     1062        $prev_theme_sidebars = array(
     1063            'top-menu' => array(),
     1064            'secondary' => array(),
     1065        );
     1066
     1067        $new_next_theme_sidebars = wp_map_sidebars_widgets( $prev_theme_sidebars );
     1068
     1069        $expected_sidebars = array(
     1070            'main' => array(),
     1071            'wp_inactive_widgets' => array(),
     1072        );
     1073        $this->assertEqualSets( $expected_sidebars, $new_next_theme_sidebars );
     1074    }
     1075
     1076    /**
     1077     * Make sure two sidebars that fall in the same group get menus assigned from the same group.
     1078     *
     1079     * @covers wp_map_sidebars_widgets()
     1080     */
     1081    public function test_sidebar_guessing_one_menu_per_sidebar() {
     1082        $this->register_sidebars( array( 'primary', 'main' ) );
     1083
     1084        $prev_theme_sidebars = array(
     1085            'navigation-menu' => array(),
     1086            'top-menu' => array(),
     1087        );
     1088
     1089        $new_next_theme_sidebars = wp_map_sidebars_widgets( $prev_theme_sidebars );
     1090
     1091        $expected_sidebars = array(
     1092            'main' => array(),
     1093            'primary' => array(),
     1094            'wp_inactive_widgets' => array(),
     1095        );
     1096        $this->assertEquals( $expected_sidebars, $new_next_theme_sidebars );
     1097    }
    9431098}
Note: See TracChangeset for help on using the changeset viewer.