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;
|
public $manager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Previewed Menus.
|
* Original nav menu locations before the theme was switched.
|
||||||
*
|
*
|
||||||
* @since 4.3.0
|
* @since 4.9.0
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
public $previewed_menus;
|
protected $original_nav_menu_locations;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
|
@ -42,8 +42,8 @@ final class WP_Customize_Nav_Menus {
|
||||||
* @param object $manager An instance of the WP_Customize_Manager class.
|
* @param object $manager An instance of the WP_Customize_Manager class.
|
||||||
*/
|
*/
|
||||||
public function __construct( $manager ) {
|
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
|
// 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 );
|
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, '…' );
|
$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 ) {
|
foreach ( $locations as $location => $description ) {
|
||||||
$setting_id = "nav_menu_locations[{$location}]";
|
$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(
|
$this->manager->add_control( new WP_Customize_Nav_Menu_Location_Control( $this->manager, $setting_id, array(
|
||||||
'label' => $description,
|
'label' => $description,
|
||||||
'location_id' => $location,
|
'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( 'template_redirect', 'wp_shortlink_header', 11, 0 );
|
||||||
add_action( 'wp_print_footer_scripts', '_wp_footer_scripts' );
|
add_action( 'wp_print_footer_scripts', '_wp_footer_scripts' );
|
||||||
add_action( 'init', 'check_theme_switched', 99 );
|
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( 'after_switch_theme', '_wp_sidebars_changed' );
|
||||||
add_action( 'wp_print_styles', 'print_emoji_styles' );
|
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' );
|
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' );
|
$nav_menu_locations = get_theme_mod( 'nav_menu_locations' );
|
||||||
|
add_option( 'theme_switch_menu_locations', $nav_menu_locations );
|
||||||
|
|
||||||
if ( func_num_args() > 1 ) {
|
if ( func_num_args() > 1 ) {
|
||||||
$stylesheet = func_get_arg( 1 );
|
$stylesheet = func_get_arg( 1 );
|
||||||
|
@ -731,13 +732,6 @@ function switch_theme( $stylesheet ) {
|
||||||
if ( 'wp_ajax_customize_save' === current_action() ) {
|
if ( 'wp_ajax_customize_save' === current_action() ) {
|
||||||
remove_theme_mod( 'sidebars_widgets' );
|
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() );
|
update_option( 'theme_switched', $old_theme->get_stylesheet() );
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
*
|
*
|
||||||
* @global string $wp_version
|
* @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.
|
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
||||||
|
|
Loading…
Reference in New Issue