WordPress.org

Make WordPress Core

Changeset 41555


Ignore:
Timestamp:
09/21/17 18:45:03 (2 months 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.

Location:
trunk
Files:
3 edited

Legend:

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

    r41353 r41555  
    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; 
     
    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 
  • trunk/src/wp-includes/widgets.php

    r41340 r41555  
    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} 
     
    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']; 
    1128  
    1129         if ( 'customize' !== $theme_changed ) { 
    1130             remove_theme_mod( 'sidebars_widgets' ); 
    1131         } 
    1132  
    1133         foreach ( $_sidebars_widgets as $sidebar => $widgets ) { 
    1134             if ( 'wp_inactive_widgets' === $sidebar || 'orphaned_widgets' === substr( $sidebar, 0, 16 ) ) { 
    1135                 continue; 
    1136             } 
    1137  
    1138             if ( !in_array( $sidebar, $registered_sidebar_keys ) ) { 
    1139                 $_sidebars_widgets['orphaned_widgets_' . ++$orphaned] = $widgets; 
    1140                 unset( $_sidebars_widgets[$sidebar] ); 
    1141             } 
    1142         } 
    1143     } else { 
    1144         if ( empty( $sidebars_widgets ) ) 
    1145             return; 
     1129    $registered_sidebars_keys = array_keys( $wp_registered_sidebars ); 
     1130    $registered_widgets_ids   = array_keys( $wp_registered_widgets ); 
     1131 
     1132    if ( ! is_array( get_theme_mod( 'sidebars_widgets' ) ) )  { 
     1133        if ( empty( $sidebars_widgets ) ) { 
     1134            return array(); 
     1135        } 
    11461136 
    11471137        unset( $sidebars_widgets['array_version'] ); 
    11481138 
    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             } 
    1172         } 
    1173  
    1174         foreach ( $sidebars_widgets as $val ) { 
    1175             if ( is_array($val) && ! empty( $val ) ) 
    1176                 $_sidebars_widgets['orphaned_widgets_' . ++$orphaned] = $val; 
    1177         } 
    1178     } 
    1179  
    1180     // discard invalid, theme-specific widgets from sidebars 
    1181     $shown_widgets = array(); 
    1182  
    1183     foreach ( $_sidebars_widgets as $sidebar => $widgets ) { 
    1184         if ( !is_array($widgets) ) 
    1185             continue; 
    1186  
    1187         $_widgets = array(); 
    1188         foreach ( $widgets as $widget ) { 
    1189             if ( isset($wp_registered_widgets[$widget]) ) 
    1190                 $_widgets[] = $widget; 
    1191         } 
    1192  
    1193         $_sidebars_widgets[$sidebar] = $_widgets; 
    1194         $shown_widgets = array_merge($shown_widgets, $_widgets); 
    1195     } 
    1196  
    1197     $sidebars_widgets = $_sidebars_widgets; 
    1198     unset($_sidebars_widgets, $_widgets); 
    1199  
    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; 
    1205  
    1206         $number = preg_replace('/.+?-([0-9]+)$/', '$1', $key); 
    1207  
    1208         if ( 2 > (int) $number ) 
    1209             continue; 
    1210  
    1211         $lost_widgets[] = $key; 
    1212     } 
    1213  
    1214     $sidebars_widgets['wp_inactive_widgets'] = array_merge($lost_widgets, (array) $sidebars_widgets['wp_inactive_widgets']); 
     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; 
     1147        } 
     1148    } 
     1149 
     1150 
     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 ] ); 
     1165        } 
     1166    } 
     1167    $sidebars_widgets['wp_inactive_widgets'] = array_merge( $lost_widgets, (array) $sidebars_widgets['wp_inactive_widgets'] ); 
     1168 
    12151169    if ( 'customize' !== $theme_changed ) { 
    12161170        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 ] ); 
     1200        } 
     1201    } 
     1202 
     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 ); 
     1206 
     1207        return $new_sidebars_widgets; 
     1208    } 
     1209 
     1210    // Map locations with the same slug. 
     1211    $existing_sidebars = array_keys( $existing_sidebars_widgets ); 
     1212 
     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(); 
     1219        } 
     1220    } 
     1221 
     1222    // If there are no old sidebars left, then we're done. 
     1223    if ( empty( $existing_sidebars_widgets ) ) { 
     1224        return $new_sidebars_widgets; 
     1225    } 
     1226 
     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                } 
     1251 
     1252                // Then see if any of the existing sidebars... 
     1253                foreach ( $existing_sidebars_widgets as $sidebar => $widgets ) { 
     1254 
     1255                    // ...and any slug in the same group... 
     1256                    foreach ( $slug_group as $slug ) { 
     1257 
     1258                        // ... have a match as well. 
     1259                        if ( false === stripos( $sidebar, $slug ) && false === stripos( $slug, $sidebar ) ) { 
     1260                            continue; 
     1261                        } 
     1262 
     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        } 
     1286    } 
     1287 
     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 
  • 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.