diff --git a/src/wp-includes/nav-menu.php b/src/wp-includes/nav-menu.php index ed49892ac0eb6..dd3b78d2c5aed 100644 --- a/src/wp-includes/nav-menu.php +++ b/src/wp-includes/nav-menu.php @@ -1288,13 +1288,17 @@ function wp_map_nav_menu_locations( $new_nav_menu_locations, $old_nav_menu_locat // 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 ) { + /* + * ...and any slug in the same group. This uses its own variable + * because the outer loop's $slug is still needed for the + * remaining new locations once this one is done. + */ + foreach ( $slug_group as $old_slug ) { // ... have a match as well. - if ( is_string( $location ) && false === stripos( $location, $slug ) && false === stripos( $slug, $location ) ) { + if ( is_string( $location ) && false === stripos( $location, $old_slug ) && false === stripos( $old_slug, $location ) ) { continue; - } elseif ( is_numeric( $location ) && $location !== $slug ) { + } elseif ( is_numeric( $location ) && $location !== $old_slug ) { continue; } @@ -1310,7 +1314,7 @@ function wp_map_nav_menu_locations( $new_nav_menu_locations, $old_nav_menu_locat // Go back and check the next new menu location. continue 3; } - } // End foreach ( $slug_group as $slug ). + } // End foreach ( $slug_group as $old_slug ). } // End foreach ( $old_nav_menu_locations as $location => $menu_id ). } // End foreach foreach ( $registered_nav_menus as $new_location => $name ). } // End foreach ( $slug_group as $slug ). diff --git a/tests/phpunit/tests/menu/nav-menu.php b/tests/phpunit/tests/menu/nav-menu.php index fcd3a3ac1059c..0233f2a1a9d22 100644 --- a/tests/phpunit/tests/menu/nav-menu.php +++ b/tests/phpunit/tests/menu/nav-menu.php @@ -179,6 +179,35 @@ public function test_location_guessing_one_menu_per_location() { $this->assertSame( $expected_nav_menu_locations, $new_next_theme_nav_menu_locations ); } + /** + * A new location that matches only one slug in its group should still be mapped + * after an earlier location in the same group has been mapped. + * + * 'primary-menu' matches 'primary' and nothing else in that group, so unlike + * 'main' in the test above it has no later slug to be picked up by. + * + * @ticket 65884 + * + * @covers ::wp_map_nav_menu_locations + */ + public function test_location_guessing_after_an_earlier_location_in_the_group_matched() { + $this->register_nav_menu_locations( array( 'primary', 'primary-menu' ) ); + + $prev_theme_nav_menu_locations = array( + 'header' => 1, + 'mainmenu' => 2, + ); + + $old_next_theme_nav_menu_locations = array(); + $new_next_theme_nav_menu_locations = wp_map_nav_menu_locations( $old_next_theme_nav_menu_locations, $prev_theme_nav_menu_locations ); + + $expected_nav_menu_locations = array( + 'primary' => 1, + 'primary-menu' => 2, + ); + $this->assertSame( $expected_nav_menu_locations, $new_next_theme_nav_menu_locations ); + } + /** * Technically possible to register menu locations numerically. *