WordPress.org

Make WordPress Core

Ticket #39693: 39693.10.diff

File 39693.10.diff, 26.5 KB (added by obenland, 4 months ago)
  • src/wp-includes/theme.php

     
    681681 
    682682        $_sidebars_widgets = null; 
    683683        if ( 'wp_ajax_customize_save' === current_action() ) { 
    684                 $_sidebars_widgets = $wp_customize->post_value( $wp_customize->get_setting( 'old_sidebars_widgets_data' ) ); 
     684                $old_sidebars_widgets_data_setting = $wp_customize->get_setting( 'old_sidebars_widgets_data' ); 
     685                if ( $old_sidebars_widgets_data_setting ) { 
     686                        $_sidebars_widgets = $wp_customize->post_value( $old_sidebars_widgets_data_setting ); 
     687                } 
    685688        } elseif ( is_array( $sidebars_widgets ) ) { 
    686689                $_sidebars_widgets = $sidebars_widgets; 
    687690        } 
    688691 
    689692        if ( is_array( $_sidebars_widgets ) ) { 
    690                 set_theme_mod( 'sidebars_widgets', array( 'time' => time(), 'data' => $_sidebars_widgets ) ); 
     693                set_theme_mod( 'sidebars_widgets', $_sidebars_widgets ); 
    691694        } 
    692695 
    693696        $nav_menu_locations = get_theme_mod( 'nav_menu_locations' ); 
  • src/wp-includes/widgets.php

     
    919919 * @since 2.2.0 
    920920 * @access private 
    921921 * 
     922 * @global array $_wp_sidebars_widgets 
    922923 * @param array $sidebars_widgets Sidebar widgets and their settings. 
    923924 */ 
    924925function wp_set_sidebars_widgets( $sidebars_widgets ) { 
    925         if ( !isset( $sidebars_widgets['array_version'] ) ) 
     926        global $_wp_sidebars_widgets; 
     927 
     928        // Clear cached value used in wp_get_sidebars_widgets(). 
     929        $_wp_sidebars_widgets = null; 
     930 
     931        if ( ! isset( $sidebars_widgets['array_version'] ) ) { 
    926932                $sidebars_widgets['array_version'] = 3; 
     933        } 
     934 
    927935        update_option( 'sidebars_widgets', $sidebars_widgets ); 
    928936} 
    929937 
     
    11131121 * 
    11141122 * @param string|bool $theme_changed Whether the theme was changed as a boolean. A value 
    11151123 *                                   of 'customize' defers updates for the Customizer. 
    1116  * @return array|void 
     1124 * @return array Updated sidebars widgets. 
    11171125 */ 
    11181126function retrieve_widgets( $theme_changed = false ) { 
    11191127        global $wp_registered_sidebars, $sidebars_widgets, $wp_registered_widgets; 
    11201128 
    1121         $registered_sidebar_keys = array_keys( $wp_registered_sidebars ); 
    1122         $orphaned = 0; 
    1123  
    1124         $old_sidebars_widgets = get_theme_mod( 'sidebars_widgets' ); 
    1125         if ( is_array( $old_sidebars_widgets ) ) { 
    1126                 // time() that sidebars were stored is in $old_sidebars_widgets['time'] 
    1127                 $_sidebars_widgets = $old_sidebars_widgets['data']; 
     1129        $registered_sidebars_keys = array_keys( $wp_registered_sidebars ); 
     1130        $registered_widgets_ids   = array_keys( $wp_registered_widgets ); 
    11281131 
    1129                 if ( 'customize' !== $theme_changed ) { 
    1130                         remove_theme_mod( 'sidebars_widgets' ); 
     1132        if ( ! is_array( get_theme_mod( 'sidebars_widgets' ) ) )  { 
     1133                if ( empty( $sidebars_widgets ) ) { 
     1134                        return array(); 
    11311135                } 
    11321136 
    1133                 foreach ( $_sidebars_widgets as $sidebar => $widgets ) { 
    1134                         if ( 'wp_inactive_widgets' === $sidebar || 'orphaned_widgets' === substr( $sidebar, 0, 16 ) ) { 
    1135                                 continue; 
    1136                         } 
     1137                unset( $sidebars_widgets['array_version'] ); 
    11371138 
    1138                         if ( !in_array( $sidebar, $registered_sidebar_keys ) ) { 
    1139                                 $_sidebars_widgets['orphaned_widgets_' . ++$orphaned] = $widgets; 
    1140                                 unset( $_sidebars_widgets[$sidebar] ); 
    1141                         } 
     1139                $sidebars_widgets_keys = array_keys( $sidebars_widgets ); 
     1140                sort( $sidebars_widgets_keys ); 
     1141                sort( $registered_sidebars_keys ); 
     1142 
     1143                if ( $sidebars_widgets_keys === $registered_sidebars_keys ) { 
     1144                        $sidebars_widgets = _wp_remove_unregistered_widgets( $sidebars_widgets, $registered_widgets_ids ); 
     1145 
     1146                        return $sidebars_widgets; 
    11421147                } 
    1143         } else { 
    1144                 if ( empty( $sidebars_widgets ) ) 
    1145                         return; 
     1148        } 
    11461149 
    1147                 unset( $sidebars_widgets['array_version'] ); 
    11481150 
    1149                 $old = array_keys($sidebars_widgets); 
    1150                 sort($old); 
    1151                 sort($registered_sidebar_keys); 
    1152  
    1153                 if ( $old == $registered_sidebar_keys ) 
    1154                         return; 
    1155  
    1156                 $_sidebars_widgets = array( 
    1157                         'wp_inactive_widgets' => !empty( $sidebars_widgets['wp_inactive_widgets'] ) ? $sidebars_widgets['wp_inactive_widgets'] : array() 
    1158                 ); 
    1159  
    1160                 unset( $sidebars_widgets['wp_inactive_widgets'] ); 
    1161  
    1162                 foreach ( $wp_registered_sidebars as $id => $settings ) { 
    1163                         if ( $theme_changed ) { 
    1164                                 $_sidebars_widgets[$id] = array_shift( $sidebars_widgets ); 
    1165                         } else { 
    1166                                 // no theme change, grab only sidebars that are currently registered 
    1167                                 if ( isset( $sidebars_widgets[$id] ) ) { 
    1168                                         $_sidebars_widgets[$id] = $sidebars_widgets[$id]; 
    1169                                         unset( $sidebars_widgets[$id] ); 
    1170                                 } 
    1171                         } 
     1151        // Discard invalid, theme-specific widgets from sidebars. 
     1152        $sidebars_widgets = _wp_remove_unregistered_widgets( $sidebars_widgets, $registered_widgets_ids ); 
     1153        $sidebars_widgets = wp_map_sidebars_widgets( $sidebars_widgets ); 
     1154 
     1155        // Find hidden/lost multi-widget instances. 
     1156        $shown_widgets = call_user_func_array( 'array_merge', $sidebars_widgets ); 
     1157        $lost_widgets  = array_diff( $registered_widgets_ids, $shown_widgets ); 
     1158 
     1159        foreach ( $lost_widgets as $key => $widget_id ) { 
     1160                $number = preg_replace( '/.+?-([0-9]+)$/', '$1', $widget_id ); 
     1161 
     1162                // Only keep active and default widgets. 
     1163                if ( is_numeric( $number ) && (int) $number < 2 ) { 
     1164                        unset( $lost_widgets[ $key ] ); 
    11721165                } 
     1166        } 
     1167        $sidebars_widgets['wp_inactive_widgets'] = array_merge( $lost_widgets, (array) $sidebars_widgets['wp_inactive_widgets'] ); 
    11731168 
    1174                 foreach ( $sidebars_widgets as $val ) { 
    1175                         if ( is_array($val) && ! empty( $val ) ) 
    1176                                 $_sidebars_widgets['orphaned_widgets_' . ++$orphaned] = $val; 
     1169        if ( 'customize' !== $theme_changed ) { 
     1170                wp_set_sidebars_widgets( $sidebars_widgets ); 
     1171        } 
     1172 
     1173        return $sidebars_widgets; 
     1174} 
     1175 
     1176/** 
     1177 * Compares a list of sidebars with their widgets against a whitelist. 
     1178 * 
     1179 * @since 4.9.0 
     1180 * 
     1181 * @param array $existing_sidebars_widgets List of sidebars and their widget instance IDs. 
     1182 * @return array Mapped sidebars widgets. 
     1183 */ 
     1184function wp_map_sidebars_widgets( $existing_sidebars_widgets ) { 
     1185        global $wp_registered_sidebars; 
     1186 
     1187        $new_sidebars_widgets = array( 
     1188                'wp_inactive_widgets' => array(), 
     1189        ); 
     1190 
     1191        // Short-circuit if there are no sidebars to map. 
     1192        if ( ! is_array( $existing_sidebars_widgets ) || empty( $existing_sidebars_widgets ) ) { 
     1193                return $new_sidebars_widgets; 
     1194        } 
     1195 
     1196        foreach ( $existing_sidebars_widgets as $sidebar => $widgets ) { 
     1197                if ( 'wp_inactive_widgets' === $sidebar || 'orphaned_widgets' === substr( $sidebar, 0, 16 ) ) { 
     1198                        $new_sidebars_widgets['wp_inactive_widgets'] = array_merge( $new_sidebars_widgets['wp_inactive_widgets'], (array) $widgets ); 
     1199                        unset( $existing_sidebars_widgets[ $sidebar ] ); 
    11771200                } 
    11781201        } 
    11791202 
    1180         // discard invalid, theme-specific widgets from sidebars 
    1181         $shown_widgets = array(); 
     1203        // If old and new theme have just one sidebar, map it and we're done. 
     1204        if ( 1 === count( $existing_sidebars_widgets ) && 1 === count( $wp_registered_sidebars ) ) { 
     1205                $new_sidebars_widgets[ key( $wp_registered_sidebars ) ] = array_pop( $existing_sidebars_widgets ); 
    11821206 
    1183         foreach ( $_sidebars_widgets as $sidebar => $widgets ) { 
    1184                 if ( !is_array($widgets) ) 
    1185                         continue; 
     1207                return $new_sidebars_widgets; 
     1208        } 
     1209 
     1210        // Map locations with the same slug. 
     1211        $existing_sidebars = array_keys( $existing_sidebars_widgets ); 
    11861212 
    1187                 $_widgets = array(); 
    1188                 foreach ( $widgets as $widget ) { 
    1189                         if ( isset($wp_registered_widgets[$widget]) ) 
    1190                                 $_widgets[] = $widget; 
     1213        foreach ( $wp_registered_sidebars as $sidebar => $name ) { 
     1214                if ( in_array( $sidebar, $existing_sidebars, true ) ) { 
     1215                        $new_sidebars_widgets[ $sidebar ] = $existing_sidebars_widgets[ $sidebar ]; 
     1216                        unset( $existing_sidebars_widgets[ $sidebar ] ); 
     1217                } else { 
     1218                        $new_sidebars_widgets[ $sidebar ] = array(); 
    11911219                } 
     1220        } 
    11921221 
    1193                 $_sidebars_widgets[$sidebar] = $_widgets; 
    1194                 $shown_widgets = array_merge($shown_widgets, $_widgets); 
     1222        // If there are no old sidebars left, then we're done. 
     1223        if ( empty( $existing_sidebars_widgets ) ) { 
     1224                return $new_sidebars_widgets; 
    11951225        } 
    11961226 
    1197         $sidebars_widgets = $_sidebars_widgets; 
    1198         unset($_sidebars_widgets, $_widgets); 
     1227        /* 
     1228         * If old and new theme both have sidebars that contain phrases 
     1229         * from within the same group, make an educated guess and map it. 
     1230         */ 
     1231        $common_slug_groups = array( 
     1232                array( 'sidebar', 'primary', 'main', 'right' ), 
     1233                array( 'second', 'left' ), 
     1234                array( 'sidebar-2', 'footer', 'bottom' ), 
     1235                array( 'header', 'top' ), 
     1236        ); 
     1237 
     1238        // Go through each group... 
     1239        foreach ( $common_slug_groups as $slug_group ) { 
     1240 
     1241                // ...and see if any of these slugs... 
     1242                foreach ( $slug_group as $slug ) { 
     1243 
     1244                        // ...and any of the new sidebars... 
     1245                        foreach ( $wp_registered_sidebars as $new_sidebar => $args ) { 
     1246 
     1247                                // ...actually match! 
     1248                                if ( false === stripos( $new_sidebar, $slug ) && false === stripos( $slug, $new_sidebar ) ) { 
     1249                                        continue; 
     1250                                } 
    11991251 
    1200         // find hidden/lost multi-widget instances 
    1201         $lost_widgets = array(); 
    1202         foreach ( $wp_registered_widgets as $key => $val ) { 
    1203                 if ( in_array($key, $shown_widgets, true) ) 
    1204                         continue; 
     1252                                // Then see if any of the existing sidebars... 
     1253                                foreach ( $existing_sidebars_widgets as $sidebar => $widgets ) { 
    12051254 
    1206                 $number = preg_replace('/.+?-([0-9]+)$/', '$1', $key); 
     1255                                        // ...and any slug in the same group... 
     1256                                        foreach ( $slug_group as $slug ) { 
    12071257 
    1208                 if ( 2 > (int) $number ) 
    1209                         continue; 
     1258                                                // ... have a match as well. 
     1259                                                if ( false === stripos( $sidebar, $slug ) && false === stripos( $slug, $sidebar ) ) { 
     1260                                                        continue; 
     1261                                                } 
    12101262 
    1211                 $lost_widgets[] = $key; 
     1263                                                // Make sure this sidebar wasn't mapped and removed previously. 
     1264                                                if ( ! empty( $existing_sidebars_widgets[ $sidebar ] ) ) { 
     1265 
     1266                                                        // We have a match that can be mapped! 
     1267                                                        $new_sidebars_widgets[ $new_sidebar ] = array_merge( $new_sidebars_widgets[ $new_sidebar ], $existing_sidebars_widgets[ $sidebar ] ); 
     1268 
     1269                                                        // Remove the mapped sidebar so it can't be mapped again. 
     1270                                                        unset( $existing_sidebars_widgets[ $sidebar ] ); 
     1271 
     1272                                                        // Go back and check the next new sidebar. 
     1273                                                        continue 3; 
     1274                                                } 
     1275                                        } // endforeach ( $slug_group as $slug ) 
     1276                                } // endforeach ( $existing_sidebars_widgets as $sidebar => $widgets ) 
     1277                        } // endforeach foreach ( $wp_registered_sidebars as $new_sidebar => $args ) 
     1278                } // endforeach ( $slug_group as $slug ) 
     1279        } // endforeach ( $common_slug_groups as $slug_group ) 
     1280 
     1281        // Move any left over widgets to inactive sidebar. 
     1282        foreach ( $existing_sidebars_widgets as $widgets ) { 
     1283                if ( is_array( $widgets ) && ! empty( $widgets ) ) { 
     1284                        $new_sidebars_widgets['wp_inactive_widgets'] = array_merge( $new_sidebars_widgets['wp_inactive_widgets'], $widgets ); 
     1285                } 
    12121286        } 
    12131287 
    1214         $sidebars_widgets['wp_inactive_widgets'] = array_merge($lost_widgets, (array) $sidebars_widgets['wp_inactive_widgets']); 
    1215         if ( 'customize' !== $theme_changed ) { 
    1216                 wp_set_sidebars_widgets( $sidebars_widgets ); 
     1288        // Sidebars_widgets settings from when this theme was previously active. 
     1289        $old_sidebars_widgets = get_theme_mod( 'sidebars_widgets' ); 
     1290 
     1291        if ( is_array( $old_sidebars_widgets ) ) { 
     1292 
     1293                // Only check sidebars that are empty or have not been mapped to yet. 
     1294                foreach ( $new_sidebars_widgets as $new_sidebar => $new_widgets ) { 
     1295                        if ( array_key_exists( $new_sidebar, $old_sidebars_widgets ) && ! empty( $new_widgets ) ) { 
     1296                                unset( $old_sidebars_widgets[ $new_sidebar ] ); 
     1297                        } 
     1298                } 
     1299 
     1300                // Remove orphaned widgets, we're only interested in previously active sidebars. 
     1301                foreach ( $old_sidebars_widgets as $sidebar => $widgets ) { 
     1302                        if ( 'orphaned_widgets' === substr( $sidebar, 0, 16 ) ) { 
     1303                                unset( $old_sidebars_widgets[ $sidebar ] ); 
     1304                        } 
     1305                } 
     1306 
     1307                $old_sidebars_widgets = _wp_remove_unregistered_widgets( $old_sidebars_widgets ); 
     1308 
     1309                if ( ! empty( $old_sidebars_widgets ) ) { 
     1310 
     1311                        // Go through each remaining sidebar... 
     1312                        foreach ( $old_sidebars_widgets as $old_sidebar => $old_widgets ) { 
     1313 
     1314                                // ...and check every new sidebar... 
     1315                                foreach ( $new_sidebars_widgets as $new_sidebar => $new_widgets ) { 
     1316 
     1317                                        // ...for every widget we're trying to revive. 
     1318                                        foreach ( $old_widgets as $key => $widget_id ) { 
     1319                                                $active_key = array_search( $widget_id, $new_widgets, true ); 
     1320 
     1321                                                // If the widget is used elsewhere... 
     1322                                                if ( false !== $active_key ) { 
     1323 
     1324                                                        // ...and that elsewhere is inactive widgets... 
     1325                                                        if ( 'wp_inactive_widgets' === $new_sidebar ) { 
     1326 
     1327                                                                // ...remove it from there and keep the active version... 
     1328                                                                unset( $new_sidebars_widgets['wp_inactive_widgets'][ $active_key ] ); 
     1329                                                        } else { 
     1330 
     1331                                                                // ...otherwise remove it from the old sidebar and keep it in the new one. 
     1332                                                                unset( $old_sidebars_widgets[ $old_sidebar ][ $key ] ); 
     1333                                                        } 
     1334                                                } // endif ( $active_key ) 
     1335                                        } // endforeach ( $old_widgets as $key => $widget_id ) 
     1336                                } // endforeach ( $new_sidebars_widgets as $new_sidebar => $new_widgets ) 
     1337                        } // endforeach ( $old_sidebars_widgets as $old_sidebar => $old_widgets ) 
     1338                } // endif ( ! empty( $old_sidebars_widgets ) ) 
     1339 
     1340 
     1341                // Restore widget settings from when theme was previously active. 
     1342                $new_sidebars_widgets = array_merge( $new_sidebars_widgets, $old_sidebars_widgets ); 
     1343        } 
     1344 
     1345        return $new_sidebars_widgets; 
     1346} 
     1347 
     1348/** 
     1349 * Compares a list of sidebars with their widgets against a whitelist. 
     1350 * 
     1351 * @since 4.9.0 
     1352 * 
     1353 * @param array $sidebars_widgets List of sidebars and their widget instance IDs. 
     1354 * @param array $whitelist        Optional. List of widget IDs to compare against. Default: Registered widgets. 
     1355 * @return array Sidebars with whitelisted widgets. 
     1356 */ 
     1357function _wp_remove_unregistered_widgets( $sidebars_widgets, $whitelist = array() ) { 
     1358        if ( empty( $whitelist ) ) { 
     1359                $whitelist = array_keys( $GLOBALS['wp_registered_widgets'] ); 
     1360        } 
     1361 
     1362        foreach ( $sidebars_widgets as $sidebar => $widgets ) { 
     1363                if ( is_array( $widgets ) ) { 
     1364                        $sidebars_widgets[ $sidebar ] = array_intersect( $widgets, $whitelist ); 
     1365                } 
    12171366        } 
    12181367 
    12191368        return $sidebars_widgets; 
  • tests/phpunit/tests/widgets.php

     
    709709                global $sidebars_widgets, $_wp_sidebars_widgets; 
    710710 
    711711                wp_widgets_init(); 
    712                 $this->register_sidebars( array( 'sidebar-1', 'sidebar-2','sidebar-3', 'wp_inactive_widgets' ) ); 
     712                $this->register_sidebars( array( 'sidebar-1', 'sidebar-2', 'sidebar-3', 'wp_inactive_widgets' ) ); 
    713713 
     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 ) { 
    732735                        $this->assertInternalType( 'array', $widgets ); 
     
    734737 
    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'] ); 
     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'] ); 
    741748 
    742                 // 6 default widgets - 1 active text widget = 5. 
    743                 $this->assertCount( 5, $sidebars_widgets['wp_inactive_widgets'] ); 
    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'] ); 
    749755 
    750                 // Theme mode with previous widgets was removed. 
    751                 $this->assertFalse( get_theme_mod( 'sidebars_widgets' ) ); 
    752  
    753756                // Sidebar_widgets option was updated. 
    754757                $this->assertEquals( $sidebars_widgets, wp_get_sidebars_widgets() ); 
    755758        } 
     
    775778                $result = retrieve_widgets( true ); 
    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 ) { 
    781785                        $this->assertInternalType( 'array', $widgets ); 
     
    784788                $this->assertContains( 'tag_cloud-1', $sidebars_widgets['sidebar-1'] ); 
    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. 
    791795                $this->assertEmpty( $sidebars_widgets['wp_inactive_widgets'] ); 
     
    814818 
    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 ) { 
    820824                        $this->assertInternalType( 'array', $widgets ); 
     
    857861 
    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 ) { 
    863867                        $this->assertInternalType( 'array', $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                $this->assertArrayHasKey( 'sidebar-3', $sidebars_widgets ); 
    872873 
    873                 // archives-2 ends up as an orphan because of the above behavior. 
    874                 $this->assertContains( 'archives-2', $sidebars_widgets['orphaned_widgets_1'] ); 
    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'] ); 
    885886                $this->assertContains( 'recent-comments-2', $sidebars_widgets['wp_inactive_widgets'] ); 
     
    900901                $this->register_sidebars( array( 'sidebar-1', 'sidebar-2','sidebar-3', '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 ); 
    913911 
     
    915913 
    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 ) { 
    921919                        $this->assertInternalType( 'array', $widgets ); 
     
    923921 
    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'] ); 
    935933                $this->assertContains( 'recent-comments-2', $sidebars_widgets['wp_inactive_widgets'] ); 
     
    940938                // Sidebar_widgets option was not updated. 
    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}