WordPress.org

Make WordPress Core


Ignore:
Timestamp:
08/09/2017 09:03:16 PM (11 months ago)
Author:
obenland
Message:

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.

File:
1 edited

Legend:

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

    r40969 r41237  
    10271027    add_action( 'delete_post', '_wp_delete_customize_changeset_dependent_auto_drafts' );
    10281028}
     1029
     1030/**
     1031 * Handle menu config after theme change.
     1032 *
     1033 * @access private
     1034 * @since 4.9.0
     1035 */
     1036function _wp_menus_changed() {
     1037    $old_nav_menu_locations    = get_option( 'theme_switch_menu_locations', array() );
     1038    $new_nav_menu_locations    = get_nav_menu_locations();
     1039    $mapped_nav_menu_locations = wp_map_nav_menu_locations( $new_nav_menu_locations, $old_nav_menu_locations );
     1040
     1041    set_theme_mod( 'nav_menu_locations', $mapped_nav_menu_locations );
     1042    delete_option( 'theme_switch_menu_locations' );
     1043}
     1044
     1045/**
     1046 * Maps nav menu locations according to assignments in previously active theme.
     1047 *
     1048 * @since 4.9.0
     1049 *
     1050 * @param array $new_nav_menu_locations New nav menu locations assignments.
     1051 * @param array $old_nav_menu_locations Old nav menu locations assignments.
     1052 * @return array Nav menus mapped to new nav menu locations.
     1053 */
     1054function wp_map_nav_menu_locations( $new_nav_menu_locations, $old_nav_menu_locations ) {
     1055    $registered_nav_menus = get_registered_nav_menus();
     1056
     1057    // Short-circuit if there are no old nav menu location assignments to map.
     1058    if ( empty( $old_nav_menu_locations ) ) {
     1059        return $new_nav_menu_locations;
     1060    }
     1061
     1062    // If old and new theme have just one location, map it and we're done.
     1063    if ( 1 === count( $old_nav_menu_locations ) && 1 === count( $registered_nav_menus ) ) {
     1064        $new_nav_menu_locations[ key( $registered_nav_menus ) ] = array_pop( $old_nav_menu_locations );
     1065        return $new_nav_menu_locations;
     1066    }
     1067
     1068    $old_locations = array_keys( $old_nav_menu_locations );
     1069
     1070    // Map locations with the same slug.
     1071    foreach ( $registered_nav_menus as $location => $name ) {
     1072        if ( in_array( $location, $old_locations, true ) ) {
     1073            $new_nav_menu_locations[ $location ] = $old_nav_menu_locations[ $location ];
     1074            unset( $old_nav_menu_locations[ $location ] );
     1075        }
     1076    }
     1077
     1078    // If there are no old nav menu locations left, then we're done.
     1079    if ( empty( $old_nav_menu_locations ) ) {
     1080        return $new_nav_menu_locations;
     1081    }
     1082
     1083    /*
     1084     * If old and new theme both have locations that contain phrases
     1085     * from within the same group, make an educated guess and map it.
     1086     */
     1087    $common_slug_groups = array(
     1088        array( 'header', 'main', 'navigation', 'primary', 'top' ),
     1089        array( 'bottom', 'footer', 'secondary', 'subsidiary' ),
     1090    );
     1091
     1092    // Go through each group...
     1093    foreach ( $common_slug_groups as $slug_group ) {
     1094
     1095        // ...and see if any of these slugs...
     1096        foreach ( $slug_group as $slug ) {
     1097
     1098            // ...and any of the new menu locations...
     1099            foreach ( $registered_nav_menus as $new_location => $name ) {
     1100
     1101                // ...actually match!
     1102                if ( false === stripos( $new_location, $slug ) && false === stripos( $slug, $new_location ) ) {
     1103                    continue;
     1104                }
     1105
     1106                // Then see if any of the old locations...
     1107                foreach ( $old_nav_menu_locations as $location => $menu_id ) {
     1108
     1109                    // ...and any slug in the same group...
     1110                    foreach ( $slug_group as $slug ) {
     1111
     1112                        // ... have a match as well.
     1113                        if ( false === stripos( $location, $slug ) && false === stripos( $slug, $location ) ) {
     1114                            continue;
     1115                        }
     1116
     1117                        // Make sure this location wasn't mapped and removed previously.
     1118                        if ( ! empty( $old_nav_menu_locations[ $location ] ) ) {
     1119
     1120                            // We have a match that can be mapped!
     1121                            $new_nav_menu_locations[ $new_location ] = $old_nav_menu_locations[ $location ];
     1122
     1123                            // Remove the mapped location so it can't be mapped again.
     1124                            unset( $old_nav_menu_locations[ $location ] );
     1125
     1126                            // Go back and check the next new menu location.
     1127                            continue 3;
     1128                        }
     1129                    } // endforeach ( $slug_group as $slug )
     1130                } // endforeach ( $old_nav_menu_locations as $location => $menu_id )
     1131            } // endforeach foreach ( $registered_nav_menus as $new_location => $name )
     1132        } // endforeach ( $slug_group as $slug )
     1133    } // endforeach ( $common_slug_groups as $slug_group )
     1134
     1135    return $new_nav_menu_locations;
     1136}
Note: See TracChangeset for help on using the changeset viewer.