Map nav menu locations on theme switch
This will send nav menu locations through three levels of mapping: 1. If both themes have only one location, that gets mapped. 2. If both themes have locations with the same slug, they get mapped. 3. Locations that (even partially) match slugs from a similar kind of menu location will get mapped. Menu locations are mapped for Live Previews in the Customizer and during theme switches. Props westonruter, obenland, welcher, melchoyce. Fixes #39692. Built from https://develop.svn.wordpress.org/trunk@41237 git-svn-id: http://core.svn.wordpress.org/trunk@41077 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
5fe8d31118
commit
e183d59acb
|
@ -27,12 +27,12 @@ final class WP_Customize_Nav_Menus {
|
|||
public $manager;
|
||||
|
||||
/**
|
||||
* Previewed Menus.
|
||||
* Original nav menu locations before the theme was switched.
|
||||
*
|
||||
* @since 4.3.0
|
||||
* @since 4.9.0
|
||||
* @var array
|
||||
*/
|
||||
public $previewed_menus;
|
||||
protected $original_nav_menu_locations;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
@ -42,8 +42,8 @@ final class WP_Customize_Nav_Menus {
|
|||
* @param object $manager An instance of the WP_Customize_Manager class.
|
||||
*/
|
||||
public function __construct( $manager ) {
|
||||
$this->previewed_menus = array();
|
||||
$this->manager = $manager;
|
||||
$this->manager = $manager;
|
||||
$this->original_nav_menu_locations = get_nav_menu_locations();
|
||||
|
||||
// See https://github.com/xwp/wp-customize-snapshots/blob/962586659688a5b1fd9ae93618b7ce2d4e7a421c/php/class-customize-snapshot-manager.php#L469-L499
|
||||
add_action( 'customize_register', array( $this, 'customize_register' ), 11 );
|
||||
|
@ -582,6 +582,12 @@ final class WP_Customize_Nav_Menus {
|
|||
$choices[ $menu->term_id ] = wp_html_excerpt( $menu->name, 40, '…' );
|
||||
}
|
||||
|
||||
// Attempt to re-map the nav menu location assignments when previewing a theme switch.
|
||||
$mapped_nav_menu_locations = array();
|
||||
if ( ! $this->manager->is_theme_active() ) {
|
||||
$mapped_nav_menu_locations = wp_map_nav_menu_locations( get_nav_menu_locations(), $this->original_nav_menu_locations );
|
||||
}
|
||||
|
||||
foreach ( $locations as $location => $description ) {
|
||||
$setting_id = "nav_menu_locations[{$location}]";
|
||||
|
||||
|
@ -600,6 +606,11 @@ final class WP_Customize_Nav_Menus {
|
|||
) );
|
||||
}
|
||||
|
||||
// Override the assigned nav menu location if mapped during previewed theme switch.
|
||||
if ( isset( $mapped_nav_menu_locations[ $location ] ) ) {
|
||||
$this->manager->set_post_value( $setting_id, $mapped_nav_menu_locations[ $location ] );
|
||||
}
|
||||
|
||||
$this->manager->add_control( new WP_Customize_Nav_Menu_Location_Control( $this->manager, $setting_id, array(
|
||||
'label' => $description,
|
||||
'location_id' => $location,
|
||||
|
|
|
@ -262,6 +262,7 @@ add_action( 'wp_footer', 'wp_print_footer_scripts', 20 );
|
|||
add_action( 'template_redirect', 'wp_shortlink_header', 11, 0 );
|
||||
add_action( 'wp_print_footer_scripts', '_wp_footer_scripts' );
|
||||
add_action( 'init', 'check_theme_switched', 99 );
|
||||
add_action( 'after_switch_theme', '_wp_menus_changed' );
|
||||
add_action( 'after_switch_theme', '_wp_sidebars_changed' );
|
||||
add_action( 'wp_print_styles', 'print_emoji_styles' );
|
||||
|
||||
|
|
|
@ -1026,3 +1026,111 @@ function _wp_delete_customize_changeset_dependent_auto_drafts( $post_id ) {
|
|||
}
|
||||
add_action( 'delete_post', '_wp_delete_customize_changeset_dependent_auto_drafts' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle menu config after theme change.
|
||||
*
|
||||
* @access private
|
||||
* @since 4.9.0
|
||||
*/
|
||||
function _wp_menus_changed() {
|
||||
$old_nav_menu_locations = get_option( 'theme_switch_menu_locations', array() );
|
||||
$new_nav_menu_locations = get_nav_menu_locations();
|
||||
$mapped_nav_menu_locations = wp_map_nav_menu_locations( $new_nav_menu_locations, $old_nav_menu_locations );
|
||||
|
||||
set_theme_mod( 'nav_menu_locations', $mapped_nav_menu_locations );
|
||||
delete_option( 'theme_switch_menu_locations' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps nav menu locations according to assignments in previously active theme.
|
||||
*
|
||||
* @since 4.9.0
|
||||
*
|
||||
* @param array $new_nav_menu_locations New nav menu locations assignments.
|
||||
* @param array $old_nav_menu_locations Old nav menu locations assignments.
|
||||
* @return array Nav menus mapped to new nav menu locations.
|
||||
*/
|
||||
function wp_map_nav_menu_locations( $new_nav_menu_locations, $old_nav_menu_locations ) {
|
||||
$registered_nav_menus = get_registered_nav_menus();
|
||||
|
||||
// Short-circuit if there are no old nav menu location assignments to map.
|
||||
if ( empty( $old_nav_menu_locations ) ) {
|
||||
return $new_nav_menu_locations;
|
||||
}
|
||||
|
||||
// If old and new theme have just one location, map it and we're done.
|
||||
if ( 1 === count( $old_nav_menu_locations ) && 1 === count( $registered_nav_menus ) ) {
|
||||
$new_nav_menu_locations[ key( $registered_nav_menus ) ] = array_pop( $old_nav_menu_locations );
|
||||
return $new_nav_menu_locations;
|
||||
}
|
||||
|
||||
$old_locations = array_keys( $old_nav_menu_locations );
|
||||
|
||||
// Map locations with the same slug.
|
||||
foreach ( $registered_nav_menus as $location => $name ) {
|
||||
if ( in_array( $location, $old_locations, true ) ) {
|
||||
$new_nav_menu_locations[ $location ] = $old_nav_menu_locations[ $location ];
|
||||
unset( $old_nav_menu_locations[ $location ] );
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no old nav menu locations left, then we're done.
|
||||
if ( empty( $old_nav_menu_locations ) ) {
|
||||
return $new_nav_menu_locations;
|
||||
}
|
||||
|
||||
/*
|
||||
* If old and new theme both have locations that contain phrases
|
||||
* from within the same group, make an educated guess and map it.
|
||||
*/
|
||||
$common_slug_groups = array(
|
||||
array( 'header', 'main', 'navigation', 'primary', 'top' ),
|
||||
array( 'bottom', 'footer', 'secondary', 'subsidiary' ),
|
||||
);
|
||||
|
||||
// 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 menu locations...
|
||||
foreach ( $registered_nav_menus as $new_location => $name ) {
|
||||
|
||||
// ...actually match!
|
||||
if ( false === stripos( $new_location, $slug ) && false === stripos( $slug, $new_location ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Then see if any of the old locations...
|
||||
foreach ( $old_nav_menu_locations as $location => $menu_id ) {
|
||||
|
||||
// ...and any slug in the same group...
|
||||
foreach ( $slug_group as $slug ) {
|
||||
|
||||
// ... have a match as well.
|
||||
if ( false === stripos( $location, $slug ) && false === stripos( $slug, $location ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Make sure this location wasn't mapped and removed previously.
|
||||
if ( ! empty( $old_nav_menu_locations[ $location ] ) ) {
|
||||
|
||||
// We have a match that can be mapped!
|
||||
$new_nav_menu_locations[ $new_location ] = $old_nav_menu_locations[ $location ];
|
||||
|
||||
// Remove the mapped location so it can't be mapped again.
|
||||
unset( $old_nav_menu_locations[ $location ] );
|
||||
|
||||
// Go back and check the next new menu location.
|
||||
continue 3;
|
||||
}
|
||||
} // endforeach ( $slug_group as $slug )
|
||||
} // endforeach ( $old_nav_menu_locations as $location => $menu_id )
|
||||
} // endforeach foreach ( $registered_nav_menus as $new_location => $name )
|
||||
} // endforeach ( $slug_group as $slug )
|
||||
} // endforeach ( $common_slug_groups as $slug_group )
|
||||
|
||||
return $new_nav_menu_locations;
|
||||
}
|
||||
|
|
|
@ -691,6 +691,7 @@ function switch_theme( $stylesheet ) {
|
|||
}
|
||||
|
||||
$nav_menu_locations = get_theme_mod( 'nav_menu_locations' );
|
||||
add_option( 'theme_switch_menu_locations', $nav_menu_locations );
|
||||
|
||||
if ( func_num_args() > 1 ) {
|
||||
$stylesheet = func_get_arg( 1 );
|
||||
|
@ -731,13 +732,6 @@ function switch_theme( $stylesheet ) {
|
|||
if ( 'wp_ajax_customize_save' === current_action() ) {
|
||||
remove_theme_mod( 'sidebars_widgets' );
|
||||
}
|
||||
|
||||
if ( ! empty( $nav_menu_locations ) ) {
|
||||
$nav_mods = get_theme_mod( 'nav_menu_locations' );
|
||||
if ( empty( $nav_mods ) ) {
|
||||
set_theme_mod( 'nav_menu_locations', $nav_menu_locations );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update_option( 'theme_switched', $old_theme->get_stylesheet() );
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* @global string $wp_version
|
||||
*/
|
||||
$wp_version = '4.9-alpha-41236';
|
||||
$wp_version = '4.9-alpha-41237';
|
||||
|
||||
/**
|
||||
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
||||
|
|
Loading…
Reference in New Issue