WordPress.org

Make WordPress Core

Ticket #39692: 39692.2.diff

File 39692.2.diff, 8.0 KB (added by obenland, 7 months ago)
  • src/wp-includes/default-filters.php

     
    264264add_action( 'template_redirect',   'wp_shortlink_header',             11, 0 ); 
    265265add_action( 'wp_print_footer_scripts', '_wp_footer_scripts'                 ); 
    266266add_action( 'init',                'check_theme_switched',            99    ); 
     267add_action( 'after_switch_theme',  '_wp_menus_changed'                      ); 
    267268add_action( 'after_switch_theme',  '_wp_sidebars_changed'                   ); 
    268269add_action( 'wp_print_styles',     'print_emoji_styles'                     ); 
    269270 
  • src/wp-includes/nav-menu.php

     
    10061006        } 
    10071007        add_action( 'delete_post', '_wp_delete_customize_changeset_dependent_auto_drafts' ); 
    10081008} 
     1009 
     1010/** 
     1011 * Handle menu config after theme change. 
     1012 * 
     1013 * @access private 
     1014 * @since 4.9.0 
     1015 */ 
     1016function _wp_menus_changed() { 
     1017        $old_nav_menu_locations = get_option( 'theme_switch_menu_locations', array() ); 
     1018        $new_nav_menu_locations = get_nav_menu_locations(); 
     1019        $registered_nav_menus   = get_registered_nav_menus(); 
     1020 
     1021        // If old and new theme have just one location, map it. 
     1022        if ( 1 === count( $old_nav_menu_locations ) && 1 === count( $registered_nav_menus ) ) { 
     1023                $new_nav_menu_locations[ key( $registered_nav_menus ) ] = array_pop( $old_nav_menu_locations ); 
     1024        } else { 
     1025                $old_locations = array_keys( $old_nav_menu_locations ); 
     1026 
     1027                // Map locations with the same slug. 
     1028                foreach ( $registered_nav_menus as $location => $name ) { 
     1029                        if ( in_array( $location, $old_locations ) ) { 
     1030                                $new_nav_menu_locations[ $location ] = $old_nav_menu_locations[ $location ]; 
     1031                                unset( $old_nav_menu_locations[ $location ] ); 
     1032                        } 
     1033                } 
     1034 
     1035                if ( ! empty( $old_nav_menu_locations ) ) { 
     1036                        /* 
     1037                         * If old and new theme both have locations that contain phrases 
     1038                         * from within the same group, make an educated guess and map it. 
     1039                         */ 
     1040                        $common_slug_groups = array( 
     1041                                array( 'header', 'main', 'navigation', 'primary', 'top' ), 
     1042                                array( 'bottom', 'footer', 'secondary', 'subsidiary' ), 
     1043                                array( 'social' ), // TODO: Find a second slug or remove, since locations with same slug are already mapped. 
     1044                        ); 
     1045 
     1046                        // Go through each group... 
     1047                        foreach ( $common_slug_groups as $slug_group ) { 
     1048 
     1049                                // ...and see if any of these slugs... 
     1050                                foreach ( $slug_group as $slug ) { 
     1051 
     1052                                        // ...and any of the new menu locations... 
     1053                                        foreach ( $registered_nav_menus as $new_location => $name ) { 
     1054 
     1055                                                // ...actually match! 
     1056                                                if ( false !== stripos( $new_location, $slug ) || false !== stripos( $slug, $new_location ) ) { 
     1057 
     1058                                                        // Then see if any of the old locations... 
     1059                                                        foreach ( $old_nav_menu_locations as $location => $menu_id ) { 
     1060 
     1061                                                                // ...match a slug in the same group. 
     1062                                                                foreach ( $slug_group as $slug ) { 
     1063                                                                        if ( false !== stripos( $location, $slug ) || false !== stripos( $slug, $location ) ) { 
     1064 
     1065                                                                                // Make sure this location wasn't mapped and removed previously. 
     1066                                                                                if ( ! empty( $old_nav_menu_locations[ $location ] ) ) { 
     1067 
     1068                                                                                        // We have a match that can be mapped! 
     1069                                                                                        $new_nav_menu_locations[ $new_location ] = $old_nav_menu_locations[ $location ]; 
     1070 
     1071                                                                                        // Remove the mapped location so it can't be mapped again. 
     1072                                                                                        unset( $old_nav_menu_locations[ $location ] ); 
     1073 
     1074                                                                                        // Go back and check the next new menu location. 
     1075                                                                                        continue 3; 
     1076                                                                                } 
     1077                                                                        } 
     1078                                                                } 
     1079                                                        } 
     1080                                                } 
     1081                                        } 
     1082                                } 
     1083                        } 
     1084                } 
     1085        } 
     1086 
     1087        set_theme_mod( 'nav_menu_locations', $new_nav_menu_locations ); 
     1088        delete_option( 'theme_switch_menu_locations' ); 
     1089} 
  • src/wp-includes/theme.php

     
    690690        } 
    691691 
    692692        $nav_menu_locations = get_theme_mod( 'nav_menu_locations' ); 
     693        add_option( 'theme_switch_menu_locations', $nav_menu_locations ); 
    693694 
    694695        if ( func_num_args() > 1 ) { 
    695696                $stylesheet = func_get_arg( 1 ); 
     
    730731                if ( 'wp_ajax_customize_save' === current_action() ) { 
    731732                        remove_theme_mod( 'sidebars_widgets' ); 
    732733                } 
    733  
    734                 if ( ! empty( $nav_menu_locations ) ) { 
    735                         $nav_mods = get_theme_mod( 'nav_menu_locations' ); 
    736                         if ( empty( $nav_mods ) ) { 
    737                                 set_theme_mod( 'nav_menu_locations', $nav_menu_locations ); 
    738                         } 
    739                 } 
    740734        } 
    741735 
    742736        update_option( 'theme_switched', $old_theme->get_stylesheet() ); 
  • tests/phpunit/tests/menu/nav-menu.php

     
     1<?php 
     2 
     3/** 
     4 * @group navmenus 
     5 */ 
     6class Tests_Nav_Menu_Theme_Change extends WP_UnitTestCase { 
     7 
     8        function setUp() { 
     9                register_nav_menus( array( 
     10                        'primary' => 'Primary', 
     11                ) ); 
     12 
     13                parent::setUp(); 
     14        } 
     15 
     16        function tearDown() { 
     17                global $_wp_registered_nav_menus; 
     18 
     19                remove_theme_mod( 'nav_menu_locations' ); 
     20                $_wp_registered_nav_menus = array(); 
     21 
     22                parent::tearDown(); 
     23        } 
     24 
     25        /** 
     26         * Two themes with one location each should just map. 
     27         */ 
     28        function test_one_location_each() { 
     29                $old_nav_menu_locations = array( 'unique-slug' => 1 ); 
     30                update_option( 'theme_switch_menu_locations', $old_nav_menu_locations ); 
     31 
     32                _wp_menus_changed(); 
     33                $this->assertEqualSets( get_theme_mod( 'nav_menu_locations' ), $old_nav_menu_locations ); 
     34        } 
     35 
     36        /** 
     37         * Locations with the same name should map. 
     38         */ 
     39        function test_locations_with_same_slug() { 
     40                $old_nav_menu_locations = array( 'primary' => 1, 'secondary' => 2 ); 
     41                update_option( 'theme_switch_menu_locations', $old_nav_menu_locations ); 
     42                register_nav_menu( 'secondary', 'Secondary' ); 
     43 
     44                _wp_menus_changed(); 
     45                $this->assertEqualSets( get_theme_mod( 'nav_menu_locations' ), $old_nav_menu_locations ); 
     46        } 
     47 
     48        /** 
     49         * If the new theme was previously active, we should fall back to that data. 
     50         */ 
     51        function test_new_theme_previously_active() { 
     52                $old_nav_menu_locations = array( 'primary' => 3 ); 
     53                update_option( 'theme_switch_menu_locations', $old_nav_menu_locations ); 
     54                $previous_locations = array( 'primary' => 1, 'secondary' => 2 ); 
     55                set_theme_mod( 'nav_menu_locations', $previous_locations ); 
     56 
     57                _wp_menus_changed(); 
     58                $this->assertEqualSets( get_theme_mod( 'nav_menu_locations' ), array_merge( $previous_locations, $old_nav_menu_locations ) ); 
     59        } 
     60 
     61        /** 
     62         * Make educated guesses on theme locations. 
     63         */ 
     64        function test_location_guessing() { 
     65                $old_nav_menu_locations = array( 'header' => 1, 'footer' => 2 ); 
     66                update_option( 'theme_switch_menu_locations', $old_nav_menu_locations ); 
     67                register_nav_menu( 'secondary', 'Secondary' ); 
     68 
     69                _wp_menus_changed(); 
     70                $this->assertEqualSets( get_theme_mod( 'nav_menu_locations' ), array( 'primary' => 1, 'secondary' => 2 ) ); 
     71        } 
     72 
     73        /** 
     74         * Make sure two locations that fall in the same group don't get the same menu assigned. 
     75         */ 
     76        function test_location_guessing_one_menu_per_group() { 
     77                $old_nav_menu_locations = array( 'top-menu' => 1, 'secondary' => 2 ); 
     78                update_option( 'theme_switch_menu_locations', $old_nav_menu_locations ); 
     79                register_nav_menu( 'main', 'Main' ); 
     80 
     81                _wp_menus_changed(); 
     82                $this->assertEqualSets( get_theme_mod( 'nav_menu_locations' ), array( 'main' => 1 ) ); 
     83        } 
     84 
     85        /** 
     86         * Make sure two locations that fall in the same group get menus assigned from the same group. 
     87         */ 
     88        function test_location_guessing_one_menu_per_location() { 
     89                $old_nav_menu_locations = array( 'navigation-menu' => 1, 'top-menu' => 2 ); 
     90                update_option( 'theme_switch_menu_locations', $old_nav_menu_locations ); 
     91                register_nav_menu( 'main', 'Main' ); 
     92 
     93                _wp_menus_changed(); 
     94                $this->assertEqualSets( get_theme_mod( 'nav_menu_locations' ), array( 'main' => 1, 'primary' => 2 ) ); 
     95        } 
     96}