Make WordPress Core

Ticket #32760: 32760.3.diff

File 32760.3.diff, 13.1 KB (added by westonruter, 9 years ago)

Additional change: https://github.com/xwp/wordpress-develop/commit/30081684a66a8226cd8de5b7838a254f0ef02603

  • src/wp-admin/css/customize-nav-menus.css

    diff --git src/wp-admin/css/customize-nav-menus.css src/wp-admin/css/customize-nav-menus.css
    index df16735..163e935 100644
    button.not-a-button { 
    646646}
    647647
    648648#custom-menu-item-name.invalid,
    649 #custom-menu-item-url.invalid {
     649#custom-menu-item-url.invalid,
     650.menu-name-field.invalid,
     651.menu-name-field.invalid:focus {
    650652        border: 1px solid #f00;
    651653}
    652654
  • src/wp-admin/js/customize-nav-menus.js

    diff --git src/wp-admin/js/customize-nav-menus.js src/wp-admin/js/customize-nav-menus.js
    index e707e4d..c4f1873 100644
     
    863863                                button.removeClass( 'open' );
    864864                                button.attr( 'aria-expanded', 'false' );
    865865                                content.slideUp( 'fast' );
     866                                content.find( '.menu-name-field' ).removeClass( 'invalid' );
    866867                        }
    867868                }
    868869        });
     
    899900                                        return;
    900901                                }
    901902                                menuId = matches[1];
    902                                 option = new Option( setting().name, menuId );
     903                                option = new Option( displayNavMenuName( setting().name ), menuId );
    903904                                control.container.find( 'select' ).append( option );
    904905                        });
    905906                        api.bind( 'remove', function( setting ) {
     
    925926                                        }
    926927                                        control.container.find( 'option[value=' + menuId + ']' ).remove();
    927928                                } else {
    928                                         control.container.find( 'option[value=' + menuId + ']' ).text( setting().name );
     929                                        control.container.find( 'option[value=' + menuId + ']' ).text( displayNavMenuName( setting().name ) );
    929930                                }
    930931                        });
    931932                }
     
    16351636                 */
    16361637                ready: function() {
    16371638                        var control = this,
    1638                                 menuId = control.params.menu_id;
     1639                                menuId = control.params.menu_id,
     1640                                menu = control.setting(),
     1641                                name;
    16391642
    16401643                        if ( 'undefined' === typeof this.params.menu_id ) {
    16411644                                throw new Error( 'params.menu_id was not defined' );
     
    16661669                        this._setupTitle();
    16671670
    16681671                        // Add menu to Custom Menu widgets.
    1669                         if ( control.setting() ) {
     1672                        if ( menu ) {
     1673                                name = displayNavMenuName( menu.name );
     1674
    16701675                                api.control.each( function( widgetControl ) {
    16711676                                        if ( ! widgetControl.extended( api.controlConstructor.widget_form ) || 'nav_menu' !== widgetControl.params.widget_id_base ) {
    16721677                                                return;
    16731678                                        }
    16741679                                        var select = widgetControl.container.find( 'select' );
    16751680                                        if ( select.find( 'option[value=' + String( menuId ) + ']' ).length === 0 ) {
    1676                                                 select.append( new Option( control.setting().name, menuId ) );
     1681                                                select.append( new Option( name, menuId ) );
    16771682                                        }
    16781683                                } );
    1679                                 $( '#available-widgets-list .widget-inside:has(input.id_base[value=nav_menu]) select:first' ).append( new Option( control.setting().name, menuId ) );
     1684                                $( '#available-widgets-list .widget-inside:has(input.id_base[value=nav_menu]) select:first' ).append( new Option( name, menuId ) );
    16801685                        }
    16811686                },
    16821687
     
    17071712                        });
    17081713
    17091714                        control.setting.bind( function( to ) {
     1715                                var name;
    17101716                                if ( false === to ) {
    17111717                                        control._handleDeletion();
    17121718                                } else {
    17131719                                        // Update names in the Custom Menu widgets.
     1720                                        name = displayNavMenuName( to.name );
    17141721                                        api.control.each( function( widgetControl ) {
    17151722                                                if ( ! widgetControl.extended( api.controlConstructor.widget_form ) || 'nav_menu' !== widgetControl.params.widget_id_base ) {
    17161723                                                        return;
    17171724                                                }
    17181725                                                var select = widgetControl.container.find( 'select' );
    1719                                                 select.find( 'option[value=' + String( menuId ) + ']' ).text( to.name );
     1726                                                select.find( 'option[value=' + String( menuId ) + ']' ).text( name );
    17201727                                        });
    1721                                         $( '#available-widgets-list .widget-inside:has(input.id_base[value=nav_menu]) select:first option[value=' + String( menuId ) + ']' ).text( to.name );
     1728                                        $( '#available-widgets-list .widget-inside:has(input.id_base[value=nav_menu]) select:first option[value=' + String( menuId ) + ']' ).text( name );
    17221729                                }
    17231730                        } );
    17241731
     
    18771884                                        if ( ! selectedMenuId || ! menuSetting || ! menuSetting() ) {
    18781885                                                container.find( '.theme-location-set' ).hide();
    18791886                                        } else {
    1880                                                 container.find( '.theme-location-set' ).show().find( 'span' ).text( menuSetting().name );
     1887                                                container.find( '.theme-location-set' ).show().find( 'span' ).text( displayNavMenuName( menuSetting().name ) );
    18811888                                        }
    18821889                                };
    18831890
     
    19091916                                        return;
    19101917                                }
    19111918
    1912                                 // Empty names are not allowed (will not be saved), don't update to one.
    1913                                 if ( menu.name ) {
    1914                                         var section = control.container.closest( '.accordion-section' ),
    1915                                                 menuId = control.params.menu_id,
    1916                                                 controlTitle = section.find( '.accordion-section-title' ),
    1917                                                 sectionTitle = section.find( '.customize-section-title h3' ),
    1918                                                 location = section.find( '.menu-in-location' ),
    1919                                                 action = sectionTitle.find( '.customize-action' );
     1919                                var section = control.container.closest( '.accordion-section' ),
     1920                                        menuId = control.params.menu_id,
     1921                                        controlTitle = section.find( '.accordion-section-title' ),
     1922                                        sectionTitle = section.find( '.customize-section-title h3' ),
     1923                                        location = section.find( '.menu-in-location' ),
     1924                                        action = sectionTitle.find( '.customize-action' ),
     1925                                        name = displayNavMenuName( menu.name );
    19201926
    1921                                         // Update the control title
    1922                                         controlTitle.text( menu.name );
    1923                                         if ( location.length ) {
    1924                                                 location.appendTo( controlTitle );
    1925                                         }
     1927                                // Update the control title
     1928                                controlTitle.text( name );
     1929                                if ( location.length ) {
     1930                                        location.appendTo( controlTitle );
     1931                                }
    19261932
    1927                                         // Update the section title
    1928                                         sectionTitle.text( menu.name );
    1929                                         if ( action.length ) {
    1930                                                 action.prependTo( sectionTitle );
    1931                                         }
     1933                                // Update the section title
     1934                                sectionTitle.text( name );
     1935                                if ( action.length ) {
     1936                                        action.prependTo( sectionTitle );
     1937                                }
    19321938
    1933                                         // Update the nav menu name in location selects.
    1934                                         api.control.each( function( control ) {
    1935                                                 if ( /^nav_menu_locations\[/.test( control.id ) ) {
    1936                                                         control.container.find( 'option[value=' + menuId + ']' ).text( menu.name );
    1937                                                 }
    1938                                         } );
     1939                                // Update the nav menu name in location selects.
     1940                                api.control.each( function( control ) {
     1941                                        if ( /^nav_menu_locations\[/.test( control.id ) ) {
     1942                                                control.container.find( 'option[value=' + menuId + ']' ).text( name );
     1943                                        }
     1944                                } );
    19391945
    1940                                         // Update the nav menu name in all location checkboxes.
    1941                                         section.find( '.customize-control-checkbox input' ).each( function() {
    1942                                                 if ( $( this ).prop( 'checked' ) ) {
    1943                                                         $( '.current-menu-location-name-' + $( this ).data( 'location-id' ) ).text( menu.name );
    1944                                                 }
    1945                                         } );
    1946                                 }
     1946                                // Update the nav menu name in all location checkboxes.
     1947                                section.find( '.customize-control-checkbox input' ).each( function() {
     1948                                        if ( $( this ).prop( 'checked' ) ) {
     1949                                                $( '.current-menu-location-name-' + $( this ).data( 'location-id' ) ).text( name );
     1950                                        }
     1951                                } );
    19471952                        } );
    19481953                },
    19491954
     
    21812186
    21822187                /**
    21832188                 * Create the new menu with the name supplied.
    2184                  *
    2185                  * @returns {boolean}
    21862189                 */
    21872190                submit: function() {
    21882191
     
    21942197                                customizeId,
    21952198                                placeholderId = api.Menus.generatePlaceholderAutoIncrementId();
    21962199
     2200                        if ( ! name ) {
     2201                                nameInput.addClass( 'invalid' );
     2202                                nameInput.focus();
     2203                                return;
     2204                        }
     2205
    21972206                        customizeId = 'nav_menu[' + String( placeholderId ) + ']';
    21982207
    21992208                        // Register the menu control setting.
     
    22192228                                params: {
    22202229                                        id: customizeId,
    22212230                                        panel: 'nav_menus',
    2222                                         title: name,
     2231                                        title: displayNavMenuName( name ),
    22232232                                        customizeAction: api.Menus.data.l10n.customizingMenus,
    22242233                                        type: 'nav_menu',
    22252234                                        priority: 10,
     
    22302239
    22312240                        // Clear name field.
    22322241                        nameInput.val( '' );
     2242                        nameInput.removeClass( 'invalid' );
    22332243
    22342244                        wp.a11y.speak( api.Menus.data.l10n.menuAdded );
    22352245
     
    22992309                var insertedMenuIdMapping = {};
    23002310
    23012311                _( data.nav_menu_updates ).each(function( update ) {
    2302                         var oldCustomizeId, newCustomizeId, oldSetting, newSetting, settingValue, oldSection, newSection;
     2312                        var oldCustomizeId, newCustomizeId, customizeId, oldSetting, newSetting, setting, settingValue, oldSection, newSection, wasSaved;
    23032313                        if ( 'inserted' === update.status ) {
    23042314                                if ( ! update.previous_term_id ) {
    23052315                                        throw new Error( 'Expected previous_term_id' );
     
    23212331                                if ( ! settingValue ) {
    23222332                                        throw new Error( 'Did not expect setting to be empty (deleted).' );
    23232333                                }
    2324                                 settingValue = _.clone( settingValue );
     2334                                settingValue = $.extend( _.clone( settingValue ), update.saved_value );
    23252335
    23262336                                insertedMenuIdMapping[ update.previous_term_id ] = update.term_id;
    23272337                                newCustomizeId = 'nav_menu[' + String( update.term_id ) + ']';
     
    23792389                                }
    23802390
    23812391                                // @todo Update the Custom Menu selects, ensuring the newly-inserted IDs are used for any that have selected a placeholder menu.
     2392                        } else if ( 'updated' === update.status ) {
     2393                                customizeId = 'nav_menu[' + String( update.term_id ) + ']';
     2394                                if ( ! api.has( customizeId ) ) {
     2395                                        throw new Error( 'Expected setting to exist: ' + customizeId );
     2396                                }
     2397
     2398                                // Make sure the setting gets updated with its sanitized server value (specifically the conflict-resolved name).
     2399                                setting = api( customizeId );
     2400                                if ( ! _.isEqual( update.saved_value, setting.get() ) ) {
     2401                                        wasSaved = api.state( 'saved' ).get();
     2402                                        setting.set( update.saved_value );
     2403                                        setting._dirty = false;
     2404                                        api.state( 'saved' ).set( wasSaved );
     2405                                }
    23822406                        }
    23832407                } );
    23842408
     
    25262550                return 'nav_menu_item[' + menuItemId + ']';
    25272551        }
    25282552
     2553        /**
     2554         * Apply sanitize_text_field()-like logic to the supplied name, returning a
     2555         * "unnammed" fallback string if the name is then empty.
     2556         *
     2557         * @param {string} name
     2558         * @returns {string}
     2559         */
     2560        function displayNavMenuName( name ) {
     2561                name = $( '<div>' ).text( name ).html(); // Emulate esc_html() which is used in wp-admin/nav-menus.php.
     2562                name = $.trim( name );
     2563                return name || api.Menus.data.l10n.unnamed;
     2564        }
     2565
    25292566})( wp.customize, wp, jQuery );
  • 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 7fbbda8..a9aae0d 100644
    final class WP_Customize_Nav_Menus { 
    281281                        'itemTypes'            => $this->available_item_types(),
    282282                        'l10n'                 => array(
    283283                                'untitled'          => _x( '(no label)', 'missing menu item navigation label' ),
     284                                'unnamed'           => _x( '(unnamed)', 'Missing menu name.' ),
    284285                                'custom_label'      => __( 'Custom Link' ),
    285286                                /* translators: %s: Current menu location */
    286287                                'menuLocation'      => __( '(Currently set to: %s)' ),
  • src/wp-includes/class-wp-customize-setting.php

    diff --git src/wp-includes/class-wp-customize-setting.php src/wp-includes/class-wp-customize-setting.php
    index 5dd5293..3eb9824 100644
    class WP_Customize_Nav_Menu_Item_Setting extends WP_Customize_Setting { 
    11821182                                if ( false === $nav_menu_setting->save() ) {
    11831183                                        $this->update_status = 'error';
    11841184                                        $this->update_error  = new WP_Error( 'nav_menu_setting_failure' );
     1185                                        return;
    11851186                                }
    11861187
    11871188                                if ( $nav_menu_setting->previous_term_id !== intval( $value['nav_menu_term_id'] ) ) {
    class WP_Customize_Nav_Menu_Item_Setting extends WP_Customize_Setting { 
    12071208                                if ( false === $parent_nav_menu_item_setting->save() ) {
    12081209                                        $this->update_status = 'error';
    12091210                                        $this->update_error  = new WP_Error( 'nav_menu_item_setting_failure' );
     1211                                        return;
    12101212                                }
    12111213
    12121214                                if ( $parent_nav_menu_item_setting->previous_post_id !== intval( $value['menu_item_parent'] ) ) {
    class WP_Customize_Nav_Menu_Setting extends WP_Customize_Setting { 
    16061608                $value = array_merge( $default, $value );
    16071609                $value = wp_array_slice_assoc( $value, array_keys( $default ) );
    16081610
     1611                if ( '' === $value['name'] ) {
     1612                        $value['name'] = _x( '(unnamed)', 'Missing menu name.' );
     1613                }
     1614
    16091615                $value['name']        = trim( esc_html( $value['name'] ) ); // This sanitization code is used in wp-admin/nav-menus.php.
    16101616                $value['description'] = sanitize_text_field( $value['description'] );
    16111617                $value['parent']      = max( 0, intval( $value['parent'] ) );
    class WP_Customize_Nav_Menu_Setting extends WP_Customize_Setting { 
    16731679                                $menu_data['menu-name'] = $value['name'];
    16741680                        }
    16751681
    1676                         $r = wp_update_nav_menu_object( $is_placeholder ? 0 : $this->term_id, $menu_data );
     1682                        $menu_id = $is_placeholder ? 0 : $this->term_id;
     1683                        $r = wp_update_nav_menu_object( $menu_id, $menu_data );
     1684                        $original_name = $menu_data['menu-name'];
     1685                        $name_conflict_suffix = 1;
     1686                        while ( is_wp_error( $r ) && 'menu_exists' === $r->get_error_code() ) {
     1687                                $name_conflict_suffix += 1;
     1688                                $menu_data['menu-name'] = sprintf( __( '%1$s (%2$d)' ), $original_name, $name_conflict_suffix );
     1689                                $r = wp_update_nav_menu_object( $menu_id, $menu_data );
     1690                        }
     1691
    16771692                        if ( is_wp_error( $r ) ) {
    16781693                                $this->update_status = 'error';
    16791694                                $this->update_error  = $r;
    class WP_Customize_Nav_Menu_Setting extends WP_Customize_Setting { 
    17641779                        'previous_term_id' => $this->previous_term_id,
    17651780                        'error'            => $this->update_error ? $this->update_error->get_error_code() : null,
    17661781                        'status'           => $this->update_status,
     1782                        'saved_value'      => $this->value(),
    17671783                );
    17681784
    17691785                return $data;