WordPress Version: 5.5
/**
* Compares a list of sidebars with their widgets against an allowed list.
*
* @since 4.9.0
* @since 4.9.2 Always tries to restore widget assignments from previous data, not just if sidebars needed mapping.
*
* @param array $existing_sidebars_widgets List of sidebars and their widget instance IDs.
* @return array Mapped sidebars widgets.
*/
function wp_map_sidebars_widgets($existing_sidebars_widgets)
{
global $wp_registered_sidebars;
$new_sidebars_widgets = array('wp_inactive_widgets' => array());
// Short-circuit if there are no sidebars to map.
if (!is_array($existing_sidebars_widgets) || empty($existing_sidebars_widgets)) {
return $new_sidebars_widgets;
}
foreach ($existing_sidebars_widgets as $sidebar => $widgets) {
if ('wp_inactive_widgets' === $sidebar || 'orphaned_widgets' === substr($sidebar, 0, 16)) {
$new_sidebars_widgets['wp_inactive_widgets'] = array_merge($new_sidebars_widgets['wp_inactive_widgets'], (array) $widgets);
unset($existing_sidebars_widgets[$sidebar]);
}
}
// If old and new theme have just one sidebar, map it and we're done.
if (1 === count($existing_sidebars_widgets) && 1 === count($wp_registered_sidebars)) {
$new_sidebars_widgets[key($wp_registered_sidebars)] = array_pop($existing_sidebars_widgets);
return $new_sidebars_widgets;
}
// Map locations with the same slug.
$existing_sidebars = array_keys($existing_sidebars_widgets);
foreach ($wp_registered_sidebars as $sidebar => $name) {
if (in_array($sidebar, $existing_sidebars, true)) {
$new_sidebars_widgets[$sidebar] = $existing_sidebars_widgets[$sidebar];
unset($existing_sidebars_widgets[$sidebar]);
} elseif (!array_key_exists($sidebar, $new_sidebars_widgets)) {
$new_sidebars_widgets[$sidebar] = array();
}
}
// If there are more sidebars, try to map them.
if (!empty($existing_sidebars_widgets)) {
/*
* If old and new theme both have sidebars that contain phrases
* from within the same group, make an educated guess and map it.
*/
$common_slug_groups = array(array('sidebar', 'primary', 'main', 'right'), array('second', 'left'), array('sidebar-2', 'footer', 'bottom'), array('header', 'top'));
// Go through each group...
foreach ($common_slug_groups as $slug_group) {
// ...and see if any of these slugs...
foreach ($slug_group as $slug) {
// ...and any of the new sidebars...
foreach ($wp_registered_sidebars as $new_sidebar => $args) {
// ...actually match!
if (false === stripos($new_sidebar, $slug) && false === stripos($slug, $new_sidebar)) {
continue;
}
// Then see if any of the existing sidebars...
foreach ($existing_sidebars_widgets as $sidebar => $widgets) {
// ...and any slug in the same group...
foreach ($slug_group as $slug) {
// ... have a match as well.
if (false === stripos($sidebar, $slug) && false === stripos($slug, $sidebar)) {
continue;
}
// Make sure this sidebar wasn't mapped and removed previously.
if (!empty($existing_sidebars_widgets[$sidebar])) {
// We have a match that can be mapped!
$new_sidebars_widgets[$new_sidebar] = array_merge($new_sidebars_widgets[$new_sidebar], $existing_sidebars_widgets[$sidebar]);
// Remove the mapped sidebar so it can't be mapped again.
unset($existing_sidebars_widgets[$sidebar]);
// Go back and check the next new sidebar.
continue 3;
}
}
// End foreach ( $slug_group as $slug ).
}
// End foreach ( $existing_sidebars_widgets as $sidebar => $widgets ).
}
// End foreach ( $wp_registered_sidebars as $new_sidebar => $args ).
}
// End foreach ( $slug_group as $slug ).
}
// End foreach ( $common_slug_groups as $slug_group ).
}
// Move any left over widgets to inactive sidebar.
foreach ($existing_sidebars_widgets as $widgets) {
if (is_array($widgets) && !empty($widgets)) {
$new_sidebars_widgets['wp_inactive_widgets'] = array_merge($new_sidebars_widgets['wp_inactive_widgets'], $widgets);
}
}
// Sidebars_widgets settings from when this theme was previously active.
$old_sidebars_widgets = get_theme_mod('sidebars_widgets');
$old_sidebars_widgets = isset($old_sidebars_widgets['data']) ? $old_sidebars_widgets['data'] : false;
if (is_array($old_sidebars_widgets)) {
// Remove empty sidebars, no need to map those.
$old_sidebars_widgets = array_filter($old_sidebars_widgets);
// Only check sidebars that are empty or have not been mapped to yet.
foreach ($new_sidebars_widgets as $new_sidebar => $new_widgets) {
if (array_key_exists($new_sidebar, $old_sidebars_widgets) && !empty($new_widgets)) {
unset($old_sidebars_widgets[$new_sidebar]);
}
}
// Remove orphaned widgets, we're only interested in previously active sidebars.
foreach ($old_sidebars_widgets as $sidebar => $widgets) {
if ('orphaned_widgets' === substr($sidebar, 0, 16)) {
unset($old_sidebars_widgets[$sidebar]);
}
}
$old_sidebars_widgets = _wp_remove_unregistered_widgets($old_sidebars_widgets);
if (!empty($old_sidebars_widgets)) {
// Go through each remaining sidebar...
foreach ($old_sidebars_widgets as $old_sidebar => $old_widgets) {
// ...and check every new sidebar...
foreach ($new_sidebars_widgets as $new_sidebar => $new_widgets) {
// ...for every widget we're trying to revive.
foreach ($old_widgets as $key => $widget_id) {
$active_key = array_search($widget_id, $new_widgets, true);
// If the widget is used elsewhere...
if (false !== $active_key) {
// ...and that elsewhere is inactive widgets...
if ('wp_inactive_widgets' === $new_sidebar) {
// ...remove it from there and keep the active version...
unset($new_sidebars_widgets['wp_inactive_widgets'][$active_key]);
} else {
// ...otherwise remove it from the old sidebar and keep it in the new one.
unset($old_sidebars_widgets[$old_sidebar][$key]);
}
}
// End if ( $active_key ).
}
// End foreach ( $old_widgets as $key => $widget_id ).
}
// End foreach ( $new_sidebars_widgets as $new_sidebar => $new_widgets ).
}
// End foreach ( $old_sidebars_widgets as $old_sidebar => $old_widgets ).
}
// End if ( ! empty( $old_sidebars_widgets ) ).
// Restore widget settings from when theme was previously active.
$new_sidebars_widgets = array_merge($new_sidebars_widgets, $old_sidebars_widgets);
}
return $new_sidebars_widgets;
}