Ticket #39692: 39692.7.diff
File 39692.7.diff, 14.0 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..3b9ca487fd 100644
final class WP_Customize_Nav_Menus { 27 27 public $manager; 28 28 29 29 /** 30 * Previewed Menus.30 * Original nav menu locations before the theme was switched. 31 31 * 32 * @since 4. 3.032 * @since 4.9.0 33 33 * @var array 34 34 */ 35 p ublic $previewed_menus;35 protected $original_nav_menu_locations; 36 36 37 37 /** 38 38 * Constructor. … … final class WP_Customize_Nav_Menus { 42 42 * @param object $manager An instance of the WP_Customize_Manager class. 43 43 */ 44 44 public function __construct( $manager ) { 45 $this-> previewed_menus = array();46 $this-> manager = $manager;45 $this->manager = $manager; 46 $this->original_nav_menu_locations = get_nav_menu_locations(); 47 47 48 48 // See https://github.com/xwp/wp-customize-snapshots/blob/962586659688a5b1fd9ae93618b7ce2d4e7a421c/php/class-customize-snapshot-manager.php#L469-L499 49 49 add_action( 'customize_register', array( $this, 'customize_register' ), 11 ); … … final class WP_Customize_Nav_Menus { 582 582 $choices[ $menu->term_id ] = wp_html_excerpt( $menu->name, 40, '…' ); 583 583 } 584 584 585 // Attempt to re-map the nav menu location assignments when previewing a theme switch. 586 $mapped_nav_menu_locations = array(); 587 if ( ! $this->manager->is_theme_active() ) { 588 $mapped_nav_menu_locations = wp_map_nav_menu_locations( get_nav_menu_locations(), $this->original_nav_menu_locations ); 589 } 590 585 591 foreach ( $locations as $location => $description ) { 586 592 $setting_id = "nav_menu_locations[{$location}]"; 587 593 … … final class WP_Customize_Nav_Menus { 600 606 ) ); 601 607 } 602 608 609 // Override the assigned nav menu location if mapped during previewed theme switch. 610 if ( isset( $mapped_nav_menu_locations[ $location ] ) ) { 611 $this->manager->set_post_value( $setting_id, $mapped_nav_menu_locations[ $location ] ); 612 } 613 603 614 $this->manager->add_control( new WP_Customize_Nav_Menu_Location_Control( $this->manager, $setting_id, array( 604 615 'label' => $description, 605 616 '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..882aee6287 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 $mapped_nav_menu_locations = wp_map_nav_menu_locations( $new_nav_menu_locations, $old_nav_menu_locations ); 1040 set_theme_mod( 'nav_menu_locations', $mapped_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 mapped to new nav menu locations. 1052 */ 1053 function wp_map_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..ec346da53b
- + 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 20 /** 21 * Register nav menu locations. 22 * 23 * @param array $locations Location slugs. 24 */ 25 function register_nav_menu_locations( $locations ) { 26 foreach ( $locations as $location ) { 27 register_nav_menu( $location, ucfirst( $location ) ); 28 } 29 } 30 31 /** 32 * Two themes with one location each should just map, switching to a theme not previously-active. 33 * 34 * @covers wp_map_nav_menu_locations() 35 */ 36 function test_one_location_each() { 37 $this->register_nav_menu_locations( array( 'primary' ) ); 38 $prev_theme_nav_menu_locations = array( 39 'unique-slug' => 1, 40 ); 41 $old_next_theme_nav_menu_locations = array(); // It was not active before. 42 $new_next_theme_nav_menu_locations = wp_map_nav_menu_locations( $old_next_theme_nav_menu_locations, $prev_theme_nav_menu_locations ); 43 44 $expected_nav_menu_locations = array( 45 'primary' => 1, 46 ); 47 $this->assertEquals( $expected_nav_menu_locations, $new_next_theme_nav_menu_locations ); 48 } 49 50 /** 51 * Locations with the same name should map, switching to a theme not previously-active. 52 * 53 * @covers wp_map_nav_menu_locations() 54 */ 55 function test_locations_with_same_slug() { 56 $this->register_nav_menu_locations( array( 'primary', 'secondary' ) ); 57 $prev_theme_nav_menu_locations = array( 58 'primary' => 1, 59 'secondary' => 2, 60 ); 61 62 $old_next_theme_nav_menu_locations = array(); // It was not active before. 63 $new_next_theme_nav_menu_locations = wp_map_nav_menu_locations( $old_next_theme_nav_menu_locations, $prev_theme_nav_menu_locations ); 64 65 $expected_nav_menu_locations = $prev_theme_nav_menu_locations; 66 $this->assertEquals( $expected_nav_menu_locations, $new_next_theme_nav_menu_locations ); 67 } 68 69 /** 70 * If the new theme was previously active, we should honor any changes to nav menu mapping done when the other theme was active. 71 * 72 * @covers wp_map_nav_menu_locations() 73 */ 74 function test_new_theme_previously_active() { 75 $this->register_nav_menu_locations( array( 'primary' ) ); 76 77 $prev_theme_nav_menu_locations = array( 78 'primary' => 1, 79 'secondary' => 2, 80 ); 81 82 // Nav menu location assignments that were set on the next theme when it was previously active. 83 $old_next_theme_nav_menu_locations = array( 84 'primary' => 3, 85 ); 86 87 $new_next_theme_nav_menu_locations = wp_map_nav_menu_locations( $old_next_theme_nav_menu_locations, $prev_theme_nav_menu_locations ); 88 89 $expected_nav_menu_locations = wp_array_slice_assoc( $prev_theme_nav_menu_locations, array_keys( get_registered_nav_menus() ) ); 90 $this->assertEquals( $expected_nav_menu_locations, $new_next_theme_nav_menu_locations ); 91 } 92 93 /** 94 * Make educated guesses on theme locations. 95 * 96 * @covers wp_map_nav_menu_locations() 97 */ 98 function test_location_guessing() { 99 $this->register_nav_menu_locations( array( 'primary', 'secondary' ) ); 100 101 $prev_theme_nav_menu_locations = array( 102 'header' => 1, 103 'footer' => 2, 104 ); 105 106 $old_next_theme_nav_menu_locations = array(); 107 $new_next_theme_nav_menu_locations = wp_map_nav_menu_locations( $old_next_theme_nav_menu_locations, $prev_theme_nav_menu_locations ); 108 109 $expected_nav_menu_locations = array( 110 'primary' => 1, 111 'secondary' => 2, 112 ); 113 $this->assertEquals( $expected_nav_menu_locations, $new_next_theme_nav_menu_locations ); 114 } 115 116 /** 117 * Make sure two locations that fall in the same group don't get the same menu assigned. 118 * 119 * @covers wp_map_nav_menu_locations() 120 */ 121 function test_location_guessing_one_menu_per_group() { 122 $this->register_nav_menu_locations( array( 'primary' ) ); 123 $prev_theme_nav_menu_locations = array( 124 'top-menu' => 1, 125 'secondary' => 2, 126 ); 127 128 $old_next_theme_nav_menu_locations = array(); 129 $new_next_theme_nav_menu_locations = wp_map_nav_menu_locations( $old_next_theme_nav_menu_locations, $prev_theme_nav_menu_locations ); 130 131 $expected_nav_menu_locations = array( 132 'main' => 1, 133 ); 134 $this->assertEqualSets( $expected_nav_menu_locations, $new_next_theme_nav_menu_locations ); 135 } 136 137 /** 138 * Make sure two locations that fall in the same group get menus assigned from the same group. 139 * 140 * @covers wp_map_nav_menu_locations() 141 */ 142 function test_location_guessing_one_menu_per_location() { 143 $this->register_nav_menu_locations( array( 'primary', 'main' ) ); 144 145 $prev_theme_nav_menu_locations = array( 146 'navigation-menu' => 1, 147 'top-menu' => 2, 148 ); 149 150 $old_next_theme_nav_menu_locations = array(); 151 $new_next_theme_nav_menu_locations = wp_map_nav_menu_locations( $old_next_theme_nav_menu_locations, $prev_theme_nav_menu_locations ); 152 153 $expected_nav_menu_locations = array( 154 'main' => 1, 155 'primary' => 2, 156 ); 157 $this->assertEquals( $expected_nav_menu_locations, $new_next_theme_nav_menu_locations ); 158 } 159 160 /** 161 * Technically possible to register menu locations numerically. 162 * 163 * @covers wp_map_nav_menu_locations() 164 */ 165 function test_numerical_locations() { 166 $this->register_nav_menu_locations( array( 'primary', 1 ) ); 167 168 $prev_theme_nav_menu_locations = array( 169 'main' => 1, 170 'secondary' => 2, 171 'tertiary' => 3, 172 ); 173 174 $old_next_theme_nav_menu_locations = array(); 175 $new_next_theme_nav_menu_locations = wp_map_nav_menu_locations( $old_next_theme_nav_menu_locations, $prev_theme_nav_menu_locations ); 176 177 $expected_nav_menu_locations = array( 178 'primary' => 1, 179 ); 180 $this->assertEqualSets( $expected_nav_menu_locations, $new_next_theme_nav_menu_locations ); 181 } 182 }