WordPress.org

Make WordPress Core

Ticket #39692: 39692.5.diff

File 39692.5.diff, 9.9 KB (added by westonruter, 6 months ago)

Δ https://github.com/xwp/wordpress-develop/pull/245/files/4054096e89df767533d3c6a2047f3a44ddda4321..efa8f5e3b8d436af09d0d04777608f59c35e27e6?w=1

  • 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 ); 
    262262add_action( 'template_redirect',   'wp_shortlink_header',             11, 0 ); 
    263263add_action( 'wp_print_footer_scripts', '_wp_footer_scripts'                 ); 
    264264add_action( 'init',                'check_theme_switched',            99    ); 
     265add_action( 'after_switch_theme',  '_wp_menus_changed'                      ); 
    265266add_action( 'after_switch_theme',  '_wp_sidebars_changed'                   ); 
    266267add_action( 'wp_print_styles',     'print_emoji_styles'                     ); 
    267268 
  • 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 ) { 
    10261026        } 
    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        $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 */ 
     1053function 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 ) { 
    691691        } 
    692692 
    693693        $nav_menu_locations = get_theme_mod( 'nav_menu_locations' ); 
     694        add_option( 'theme_switch_menu_locations', $nav_menu_locations ); 
    694695 
    695696        if ( func_num_args() > 1 ) { 
    696697                $stylesheet = func_get_arg( 1 ); 
    function switch_theme( $stylesheet ) { 
    731732                if ( 'wp_ajax_customize_save' === current_action() ) { 
    732733                        remove_theme_mod( 'sidebars_widgets' ); 
    733734                } 
    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                 } 
    741735        } 
    742736 
    743737        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 */ 
     6class 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}