Ticket #39692: 39692.6.diff
File 39692.6.diff, 12.3 KB (added by , 7 years ago) |
---|
-
src/wp-includes/class-wp-customize-nav-menus.php
diff --git src/wp-includes/class-wp-customize-nav-menus.php src/wp-includes/class-wp-customize-nav-menus.php index 3d7b1f0deb..73b40bcd21 100644
final class WP_Customize_Nav_Menus { 29 29 /** 30 30 * Previewed Menus. 31 31 * 32 * @todo This is unused and can be removed. 33 * 32 34 * @since 4.3.0 33 35 * @var array 34 36 */ 35 37 public $previewed_menus; 36 38 37 39 /** 40 * Original nav menu locations before the theme was switched. 41 * 42 * @since 4.9.0 43 * @var array 44 */ 45 protected $original_nav_menu_locations; 46 47 /** 38 48 * Constructor. 39 49 * 40 50 * @since 4.3.0 … … final class WP_Customize_Nav_Menus { 42 52 * @param object $manager An instance of the WP_Customize_Manager class. 43 53 */ 44 54 public function __construct( $manager ) { 45 $this->previewed_menus = array(); 46 $this->manager = $manager; 55 $this->previewed_menus = array(); // @todo This is unused and can be removed. 56 $this->manager = $manager; 57 $this->original_nav_menu_locations = get_nav_menu_locations(); 47 58 48 59 // See https://github.com/xwp/wp-customize-snapshots/blob/962586659688a5b1fd9ae93618b7ce2d4e7a421c/php/class-customize-snapshot-manager.php#L469-L499 49 60 add_action( 'customize_register', array( $this, 'customize_register' ), 11 ); … … final class WP_Customize_Nav_Menus { 582 593 $choices[ $menu->term_id ] = wp_html_excerpt( $menu->name, 40, '…' ); 583 594 } 584 595 596 // Attempt to re-map the nav menu location assignments when previewing a theme switch. 597 $remapped_nav_menu_locations = array(); 598 if ( ! $this->manager->is_theme_active() ) { 599 $remapped_nav_menu_locations = wp_get_remapped_nav_menu_locations( get_nav_menu_locations(), $this->original_nav_menu_locations ); 600 } 601 585 602 foreach ( $locations as $location => $description ) { 586 603 $setting_id = "nav_menu_locations[{$location}]"; 587 604 … … final class WP_Customize_Nav_Menus { 600 617 ) ); 601 618 } 602 619 620 // Override the assigned nav menu location if remapped during previewed theme switch. 621 if ( isset( $remapped_nav_menu_locations[ $location ] ) ) { 622 $this->manager->set_post_value( $setting_id, $remapped_nav_menu_locations[ $location ] ); 623 } 624 603 625 $this->manager->add_control( new WP_Customize_Nav_Menu_Location_Control( $this->manager, $setting_id, array( 604 626 'label' => $description, 605 627 'location_id' => $location, -
src/wp-includes/default-filters.php
diff --git src/wp-includes/default-filters.php src/wp-includes/default-filters.php index 9212e42865..8a8b6a9072 100644
add_action( 'wp_footer', 'wp_print_footer_scripts', 20 ); 262 262 add_action( 'template_redirect', 'wp_shortlink_header', 11, 0 ); 263 263 add_action( 'wp_print_footer_scripts', '_wp_footer_scripts' ); 264 264 add_action( 'init', 'check_theme_switched', 99 ); 265 add_action( 'after_switch_theme', '_wp_menus_changed' ); 265 266 add_action( 'after_switch_theme', '_wp_sidebars_changed' ); 266 267 add_action( 'wp_print_styles', 'print_emoji_styles' ); 267 268 -
src/wp-includes/nav-menu.php
diff --git src/wp-includes/nav-menu.php src/wp-includes/nav-menu.php index 1585c62f3d..aaeca74d33 100644
function _wp_delete_customize_changeset_dependent_auto_drafts( $post_id ) { 1026 1026 } 1027 1027 add_action( 'delete_post', '_wp_delete_customize_changeset_dependent_auto_drafts' ); 1028 1028 } 1029 1030 /** 1031 * Handle menu config after theme change. 1032 * 1033 * @access private 1034 * @since 4.9.0 1035 */ 1036 function _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 $remapped_nav_menu_locations = wp_get_remapped_nav_menu_locations( $new_nav_menu_locations, $old_nav_menu_locations ); 1040 set_theme_mod( 'nav_menu_locations', $remapped_nav_menu_locations ); 1041 delete_option( 'theme_switch_menu_locations' ); 1042 } 1043 1044 /** 1045 * Re-maps nav menu location assignments according to previous location assignments (in a different theme). 1046 * 1047 * @since 4.9.0 1048 * 1049 * @param array $new_nav_menu_locations New nav menu locations assignments. 1050 * @param array $old_nav_menu_locations Old nav menu locations assignments. 1051 * @return array Nav menus remapped to new nav menu locations. 1052 */ 1053 function wp_get_remapped_nav_menu_locations( $new_nav_menu_locations, $old_nav_menu_locations ) { 1054 $registered_nav_menus = get_registered_nav_menus(); 1055 1056 // Short-circuit if there are no old nav menu location assignments to map. 1057 if ( empty( $old_nav_menu_locations ) ) { 1058 return $new_nav_menu_locations; 1059 } 1060 1061 // If old and new theme have just one location, map it and we're done. 1062 if ( 1 === count( $old_nav_menu_locations ) && 1 === count( $registered_nav_menus ) ) { 1063 $new_nav_menu_locations[ key( $registered_nav_menus ) ] = array_pop( $old_nav_menu_locations ); 1064 return $new_nav_menu_locations; 1065 } 1066 1067 $old_locations = array_keys( $old_nav_menu_locations ); 1068 1069 // Map locations with the same slug. 1070 foreach ( $registered_nav_menus as $location => $name ) { 1071 if ( in_array( $location, $old_locations, true ) ) { 1072 $new_nav_menu_locations[ $location ] = $old_nav_menu_locations[ $location ]; 1073 unset( $old_nav_menu_locations[ $location ] ); 1074 } 1075 } 1076 1077 // If there are no old nav menu locations left, then we're done. 1078 if ( empty( $old_nav_menu_locations ) ) { 1079 return $new_nav_menu_locations; 1080 } 1081 1082 /* 1083 * If old and new theme both have locations that contain phrases 1084 * from within the same group, make an educated guess and map it. 1085 */ 1086 $common_slug_groups = array( 1087 array( 'header', 'main', 'navigation', 'primary', 'top' ), 1088 array( 'bottom', 'footer', 'secondary', 'subsidiary' ), 1089 array( 'social' ), 1090 // TODO: Find a second slug or remove, since locations with same slug are already mapped. 1091 ); 1092 1093 // Go through each group... 1094 foreach ( $common_slug_groups as $slug_group ) { 1095 1096 // ...and see if any of these slugs... 1097 foreach ( $slug_group as $slug ) { 1098 1099 // ...and any of the new menu locations... 1100 foreach ( $registered_nav_menus as $new_location => $name ) { 1101 1102 // ...actually match! 1103 if ( false === stripos( $new_location, $slug ) && false === stripos( $slug, $new_location ) ) { 1104 continue; 1105 } 1106 1107 // Then see if any of the old locations... 1108 foreach ( $old_nav_menu_locations as $location => $menu_id ) { 1109 1110 // ...match a slug in the same group. 1111 foreach ( $slug_group as $slug ) { 1112 1113 // But skip if the location and slug don't match. 1114 if ( false === stripos( $location, $slug ) && false === stripos( $slug, $location ) ) { 1115 continue; 1116 } 1117 1118 // Make sure this location wasn't mapped and removed previously. 1119 if ( ! empty( $old_nav_menu_locations[ $location ] ) ) { 1120 1121 // We have a match that can be mapped! 1122 $new_nav_menu_locations[ $new_location ] = $old_nav_menu_locations[ $location ]; 1123 1124 // Remove the mapped location so it can't be mapped again. 1125 unset( $old_nav_menu_locations[ $location ] ); 1126 1127 // Go back and check the next new menu location. 1128 continue 3; 1129 } 1130 } // endforeach ( $slug_group as $slug ) 1131 } // endforeach ( $old_nav_menu_locations as $location => $menu_id ) 1132 } // endforeach foreach ( $registered_nav_menus as $new_location => $name ) 1133 } // endforeach ( $slug_group as $slug ) 1134 } // endforeach ( $common_slug_groups as $slug_group ) 1135 1136 return $new_nav_menu_locations; 1137 } -
src/wp-includes/theme.php
diff --git src/wp-includes/theme.php src/wp-includes/theme.php index 2b2fbf2403..1d55f4f27c 100644
function switch_theme( $stylesheet ) { 691 691 } 692 692 693 693 $nav_menu_locations = get_theme_mod( 'nav_menu_locations' ); 694 add_option( 'theme_switch_menu_locations', $nav_menu_locations ); 694 695 695 696 if ( func_num_args() > 1 ) { 696 697 $stylesheet = func_get_arg( 1 ); … … function switch_theme( $stylesheet ) { 731 732 if ( 'wp_ajax_customize_save' === current_action() ) { 732 733 remove_theme_mod( 'sidebars_widgets' ); 733 734 } 734 735 if ( ! empty( $nav_menu_locations ) ) {736 $nav_mods = get_theme_mod( 'nav_menu_locations' );737 if ( empty( $nav_mods ) ) {738 set_theme_mod( 'nav_menu_locations', $nav_menu_locations );739 }740 }741 735 } 742 736 743 737 update_option( 'theme_switched', $old_theme->get_stylesheet() ); -
new file tests/phpunit/tests/menu/nav-menu.php
diff --git tests/phpunit/tests/menu/nav-menu.php tests/phpunit/tests/menu/nav-menu.php new file mode 100644 index 0000000000..db582b8a12
- + 1 <?php 2 3 /** 4 * @group navmenus 5 */ 6 class Tests_Nav_Menu_Theme_Change extends WP_UnitTestCase { 7 8 /** 9 * Set up. 10 */ 11 function setUp() { 12 parent::setUp(); 13 14 // Unregister all nav menu locations. 15 foreach ( array_keys( get_registered_nav_menus() ) as $location ) { 16 unregister_nav_menu( $location ); 17 } 18 19 register_nav_menus( array( 20 'primary' => 'Primary', 21 ) ); 22 } 23 24 /** 25 * Two themes with one location each should just map. 26 */ 27 function test_one_location_each() { 28 $old_nav_menu_locations = array( 29 'unique-slug' => 1, 30 ); 31 update_option( 'theme_switch_menu_locations', $old_nav_menu_locations ); 32 33 _wp_menus_changed(); 34 $this->assertEqualSets( $old_nav_menu_locations, get_theme_mod( 'nav_menu_locations' ) ); 35 } 36 37 /** 38 * Locations with the same name should map. 39 */ 40 function test_locations_with_same_slug() { 41 $old_nav_menu_locations = array( 42 'primary' => 1, 43 'secondary' => 2, 44 ); 45 update_option( 'theme_switch_menu_locations', $old_nav_menu_locations ); 46 register_nav_menu( 'secondary', 'Secondary' ); 47 48 _wp_menus_changed(); 49 $this->assertEqualSets( $old_nav_menu_locations, get_theme_mod( 'nav_menu_locations' ) ); 50 } 51 52 /** 53 * If the new theme was previously active, we should fall back to that data. 54 */ 55 function test_new_theme_previously_active() { 56 $old_nav_menu_locations = array( 57 'primary' => 3, 58 ); 59 update_option( 'theme_switch_menu_locations', $old_nav_menu_locations ); 60 $previous_locations = array( 61 'primary' => 1, 62 'secondary' => 2, 63 ); 64 set_theme_mod( 'nav_menu_locations', $previous_locations ); 65 66 _wp_menus_changed(); 67 $expected = array_merge( $previous_locations, $old_nav_menu_locations ); 68 $this->assertEqualSets( $expected, get_theme_mod( 'nav_menu_locations' ) ); 69 } 70 71 /** 72 * Make educated guesses on theme locations. 73 */ 74 function test_location_guessing() { 75 $old_nav_menu_locations = array( 76 'header' => 1, 77 'footer' => 2, 78 ); 79 update_option( 'theme_switch_menu_locations', $old_nav_menu_locations ); 80 register_nav_menu( 'secondary', 'Secondary' ); 81 82 _wp_menus_changed(); 83 $expected = array( 84 'primary' => 1, 85 'secondary' => 2, 86 ); 87 $this->assertEqualSets( $expected, get_theme_mod( 'nav_menu_locations' ) ); 88 } 89 90 /** 91 * Make sure two locations that fall in the same group don't get the same menu assigned. 92 */ 93 function test_location_guessing_one_menu_per_group() { 94 $old_nav_menu_locations = array( 95 'top-menu' => 1, 96 'secondary' => 2, 97 ); 98 update_option( 'theme_switch_menu_locations', $old_nav_menu_locations ); 99 register_nav_menu( 'main', 'Main' ); 100 101 _wp_menus_changed(); 102 $expected = array( 103 'main' => 1, 104 ); 105 $this->assertEqualSets( $expected, get_theme_mod( 'nav_menu_locations' ) ); 106 } 107 108 /** 109 * Make sure two locations that fall in the same group get menus assigned from the same group. 110 */ 111 function test_location_guessing_one_menu_per_location() { 112 $old_nav_menu_locations = array( 113 'navigation-menu' => 1, 114 'top-menu' => 2, 115 ); 116 update_option( 'theme_switch_menu_locations', $old_nav_menu_locations ); 117 register_nav_menu( 'main', 'Main' ); 118 119 _wp_menus_changed(); 120 $expected = array( 121 'main' => 1, 122 'primary' => 2, 123 ); 124 $this->assertEqualSets( $expected, get_theme_mod( 'nav_menu_locations' ) ); 125 } 126 127 /** 128 * Technically possible to register menu locations numerically. 129 */ 130 function test_numerical_locations() { 131 $old_nav_menu_locations = array( 132 'main' => 1, 133 'secondary' => 2, 134 'tertiary' => 3, 135 ); 136 update_option( 'theme_switch_menu_locations', $old_nav_menu_locations ); 137 register_nav_menu( 1 , 'First' ); 138 139 _wp_menus_changed(); 140 $expected = array( 141 'primary' => 1, 142 ); 143 $this->assertEqualSets( $expected, get_theme_mod( 'nav_menu_locations' ) ); 144 } 145 }