Changeset 33071
- Timestamp:
- 07/03/2015 08:46:48 PM (10 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-admin/css/customize-nav-menus.css
r33028 r33071 655 655 656 656 #custom-menu-item-name.invalid, 657 #custom-menu-item-url.invalid { 657 #custom-menu-item-url.invalid, 658 .menu-name-field.invalid, 659 .menu-name-field.invalid:focus { 658 660 border: 1px solid #f00; 659 661 } -
trunk/src/wp-admin/js/customize-nav-menus.js
r33070 r33071 834 834 button.attr( 'aria-expanded', 'false' ); 835 835 content.slideUp( 'fast' ); 836 content.find( '.menu-name-field' ).removeClass( 'invalid' ); 836 837 } 837 838 } … … 870 871 } 871 872 menuId = matches[1]; 872 option = new Option( setting().name, menuId );873 option = new Option( displayNavMenuName( setting().name ), menuId ); 873 874 control.container.find( 'select' ).append( option ); 874 875 }); … … 896 897 control.container.find( 'option[value=' + menuId + ']' ).remove(); 897 898 } else { 898 control.container.find( 'option[value=' + menuId + ']' ).text( setting().name);899 control.container.find( 'option[value=' + menuId + ']' ).text( displayNavMenuName( setting().name ) ); 899 900 } 900 901 }); … … 1606 1607 ready: function() { 1607 1608 var control = this, 1608 menuId = control.params.menu_id; 1609 menuId = control.params.menu_id, 1610 menu = control.setting(), 1611 name; 1609 1612 1610 1613 if ( 'undefined' === typeof this.params.menu_id ) { … … 1637 1640 1638 1641 // Add menu to Custom Menu widgets. 1639 if ( control.setting() ) { 1642 if ( menu ) { 1643 name = displayNavMenuName( menu.name ); 1644 1640 1645 api.control.each( function( widgetControl ) { 1641 1646 if ( ! widgetControl.extended( api.controlConstructor.widget_form ) || 'nav_menu' !== widgetControl.params.widget_id_base ) { … … 1644 1649 var select = widgetControl.container.find( 'select' ); 1645 1650 if ( select.find( 'option[value=' + String( menuId ) + ']' ).length === 0 ) { 1646 select.append( new Option( control.setting().name, menuId ) );1651 select.append( new Option( name, menuId ) ); 1647 1652 } 1648 1653 } ); 1649 $( '#available-widgets-list .widget-inside:has(input.id_base[value=nav_menu]) select:first' ).append( new Option( control.setting().name, menuId ) );1654 $( '#available-widgets-list .widget-inside:has(input.id_base[value=nav_menu]) select:first' ).append( new Option( name, menuId ) ); 1650 1655 } 1651 1656 }, … … 1678 1683 1679 1684 control.setting.bind( function( to ) { 1685 var name; 1680 1686 if ( false === to ) { 1681 1687 control._handleDeletion(); 1682 1688 } else { 1683 1689 // Update names in the Custom Menu widgets. 1690 name = displayNavMenuName( to.name ); 1684 1691 api.control.each( function( widgetControl ) { 1685 1692 if ( ! widgetControl.extended( api.controlConstructor.widget_form ) || 'nav_menu' !== widgetControl.params.widget_id_base ) { … … 1687 1694 } 1688 1695 var select = widgetControl.container.find( 'select' ); 1689 select.find( 'option[value=' + String( menuId ) + ']' ).text( to.name );1696 select.find( 'option[value=' + String( menuId ) + ']' ).text( name ); 1690 1697 }); 1691 $( '#available-widgets-list .widget-inside:has(input.id_base[value=nav_menu]) select:first option[value=' + String( menuId ) + ']' ).text( to.name );1698 $( '#available-widgets-list .widget-inside:has(input.id_base[value=nav_menu]) select:first option[value=' + String( menuId ) + ']' ).text( name ); 1692 1699 } 1693 1700 } ); … … 1848 1855 container.find( '.theme-location-set' ).hide(); 1849 1856 } else { 1850 container.find( '.theme-location-set' ).show().find( 'span' ).text( menuSetting().name);1857 container.find( '.theme-location-set' ).show().find( 'span' ).text( displayNavMenuName( menuSetting().name ) ); 1851 1858 } 1852 1859 }; … … 1880 1887 } 1881 1888 1882 // Empty names are not allowed (will not be saved), don't update to one. 1883 if ( menu.name ) { 1884 var section = control.container.closest( '.accordion-section' ), 1885 menuId = control.params.menu_id, 1886 controlTitle = section.find( '.accordion-section-title' ), 1887 sectionTitle = section.find( '.customize-section-title h3' ), 1888 location = section.find( '.menu-in-location' ), 1889 action = sectionTitle.find( '.customize-action' ); 1890 1891 // Update the control title 1892 controlTitle.text( menu.name ); 1893 if ( location.length ) { 1894 location.appendTo( controlTitle ); 1889 var section = control.container.closest( '.accordion-section' ), 1890 menuId = control.params.menu_id, 1891 controlTitle = section.find( '.accordion-section-title' ), 1892 sectionTitle = section.find( '.customize-section-title h3' ), 1893 location = section.find( '.menu-in-location' ), 1894 action = sectionTitle.find( '.customize-action' ), 1895 name = displayNavMenuName( menu.name ); 1896 1897 // Update the control title 1898 controlTitle.text( name ); 1899 if ( location.length ) { 1900 location.appendTo( controlTitle ); 1901 } 1902 1903 // Update the section title 1904 sectionTitle.text( name ); 1905 if ( action.length ) { 1906 action.prependTo( sectionTitle ); 1907 } 1908 1909 // Update the nav menu name in location selects. 1910 api.control.each( function( control ) { 1911 if ( /^nav_menu_locations\[/.test( control.id ) ) { 1912 control.container.find( 'option[value=' + menuId + ']' ).text( name ); 1895 1913 } 1896 1897 // Update the section title 1898 sectionTitle.text( menu.name ); 1899 if ( action.length ) { 1900 action.prependTo( sectionTitle ); 1914 } ); 1915 1916 // Update the nav menu name in all location checkboxes. 1917 section.find( '.customize-control-checkbox input' ).each( function() { 1918 if ( $( this ).prop( 'checked' ) ) { 1919 $( '.current-menu-location-name-' + $( this ).data( 'location-id' ) ).text( name ); 1901 1920 } 1902 1903 // Update the nav menu name in location selects. 1904 api.control.each( function( control ) { 1905 if ( /^nav_menu_locations\[/.test( control.id ) ) { 1906 control.container.find( 'option[value=' + menuId + ']' ).text( menu.name ); 1907 } 1908 } ); 1909 1910 // Update the nav menu name in all location checkboxes. 1911 section.find( '.customize-control-checkbox input' ).each( function() { 1912 if ( $( this ).prop( 'checked' ) ) { 1913 $( '.current-menu-location-name-' + $( this ).data( 'location-id' ) ).text( menu.name ); 1914 } 1915 } ); 1916 } 1921 } ); 1917 1922 } ); 1918 1923 }, … … 2152 2157 /** 2153 2158 * Create the new menu with the name supplied. 2154 *2155 * @returns {boolean}2156 2159 */ 2157 2160 submit: function() { … … 2164 2167 customizeId, 2165 2168 placeholderId = api.Menus.generatePlaceholderAutoIncrementId(); 2169 2170 if ( ! name ) { 2171 nameInput.addClass( 'invalid' ); 2172 nameInput.focus(); 2173 return; 2174 } 2166 2175 2167 2176 customizeId = 'nav_menu[' + String( placeholderId ) + ']'; … … 2190 2199 id: customizeId, 2191 2200 panel: 'nav_menus', 2192 title: name,2201 title: displayNavMenuName( name ), 2193 2202 customizeAction: api.Menus.data.l10n.customizingMenus, 2194 2203 type: 'nav_menu', … … 2201 2210 // Clear name field. 2202 2211 nameInput.val( '' ); 2212 nameInput.removeClass( 'invalid' ); 2203 2213 2204 2214 wp.a11y.speak( api.Menus.data.l10n.menuAdded ); … … 2270 2280 2271 2281 _( data.nav_menu_updates ).each(function( update ) { 2272 var oldCustomizeId, newCustomizeId, oldSetting, newSetting, settingValue, oldSection, newSection;2282 var oldCustomizeId, newCustomizeId, customizeId, oldSetting, newSetting, setting, settingValue, oldSection, newSection, wasSaved; 2273 2283 if ( 'inserted' === update.status ) { 2274 2284 if ( ! update.previous_term_id ) { … … 2292 2302 throw new Error( 'Did not expect setting to be empty (deleted).' ); 2293 2303 } 2294 settingValue = _.clone( settingValue );2304 settingValue = $.extend( _.clone( settingValue ), update.saved_value ); 2295 2305 2296 2306 insertedMenuIdMapping[ update.previous_term_id ] = update.term_id; … … 2350 2360 2351 2361 // @todo Update the Custom Menu selects, ensuring the newly-inserted IDs are used for any that have selected a placeholder menu. 2362 } else if ( 'updated' === update.status ) { 2363 customizeId = 'nav_menu[' + String( update.term_id ) + ']'; 2364 if ( ! api.has( customizeId ) ) { 2365 throw new Error( 'Expected setting to exist: ' + customizeId ); 2366 } 2367 2368 // Make sure the setting gets updated with its sanitized server value (specifically the conflict-resolved name). 2369 setting = api( customizeId ); 2370 if ( ! _.isEqual( update.saved_value, setting.get() ) ) { 2371 wasSaved = api.state( 'saved' ).get(); 2372 setting.set( update.saved_value ); 2373 setting._dirty = false; 2374 api.state( 'saved' ).set( wasSaved ); 2375 } 2352 2376 } 2353 2377 } ); … … 2497 2521 } 2498 2522 2523 /** 2524 * Apply sanitize_text_field()-like logic to the supplied name, returning a 2525 * "unnammed" fallback string if the name is then empty. 2526 * 2527 * @param {string} name 2528 * @returns {string} 2529 */ 2530 function displayNavMenuName( name ) { 2531 name = $( '<div>' ).text( name ).html(); // Emulate esc_html() which is used in wp-admin/nav-menus.php. 2532 name = $.trim( name ); 2533 return name || api.Menus.data.l10n.unnamed; 2534 } 2535 2499 2536 })( wp.customize, wp, jQuery ); -
trunk/src/wp-includes/class-wp-customize-nav-menus.php
r33036 r33071 282 282 'l10n' => array( 283 283 'untitled' => _x( '(no label)', 'missing menu item navigation label' ), 284 'unnamed' => _x( '(unnamed)', 'Missing menu name.' ), 284 285 'custom_label' => __( 'Custom Link' ), 285 286 /* translators: %s: Current menu location */ -
trunk/src/wp-includes/class-wp-customize-setting.php
r32893 r33071 1183 1183 $this->update_status = 'error'; 1184 1184 $this->update_error = new WP_Error( 'nav_menu_setting_failure' ); 1185 return; 1185 1186 } 1186 1187 … … 1208 1209 $this->update_status = 'error'; 1209 1210 $this->update_error = new WP_Error( 'nav_menu_item_setting_failure' ); 1211 return; 1210 1212 } 1211 1213 … … 1612 1614 $value['auto_add'] = ! empty( $value['auto_add'] ); 1613 1615 1616 if ( '' === $value['name'] ) { 1617 $value['name'] = _x( '(unnamed)', 'Missing menu name.' ); 1618 } 1619 1614 1620 /** This filter is documented in wp-includes/class-wp-customize-setting.php */ 1615 1621 return apply_filters( "customize_sanitize_{$this->id}", $value, $this ); … … 1670 1676 // Insert or update menu. 1671 1677 $menu_data = wp_array_slice_assoc( $value, array( 'description', 'parent' ) ); 1672 if ( isset( $value['name'] ) ) { 1673 $menu_data['menu-name'] = $value['name']; 1674 } 1675 1676 $r = wp_update_nav_menu_object( $is_placeholder ? 0 : $this->term_id, $menu_data ); 1678 $menu_data['menu-name'] = $value['name']; 1679 1680 $menu_id = $is_placeholder ? 0 : $this->term_id; 1681 $r = wp_update_nav_menu_object( $menu_id, $menu_data ); 1682 $original_name = $menu_data['menu-name']; 1683 $name_conflict_suffix = 1; 1684 while ( is_wp_error( $r ) && 'menu_exists' === $r->get_error_code() ) { 1685 $name_conflict_suffix += 1; 1686 /* translators: 1: original menu name, 2: duplicate count */ 1687 $menu_data['menu-name'] = sprintf( __( '%1$s (%2$d)' ), $original_name, $name_conflict_suffix ); 1688 $r = wp_update_nav_menu_object( $menu_id, $menu_data ); 1689 } 1690 1677 1691 if ( is_wp_error( $r ) ) { 1678 1692 $this->update_status = 'error'; … … 1765 1779 'error' => $this->update_error ? $this->update_error->get_error_code() : null, 1766 1780 'status' => $this->update_status, 1781 'saved_value' => 'deleted' === $this->update_status ? null : $this->value(), 1767 1782 ); 1768 1783 -
trunk/tests/phpunit/tests/customize/nav-menu-setting.php
r32806 r33071 95 95 do_action( 'customize_register', $this->wp_customize ); 96 96 $_wp_customize = $this->wp_customize; 97 unset( $_wp_customize->nav_menus);97 unset( $_wp_customize->nav_menus ); 98 98 99 99 $exception = null; … … 311 311 $this->assertEquals( true, $sanitized['auto_add'] ); 312 312 $this->assertEqualSets( array( 'name', 'description', 'parent', 'auto_add' ), array_keys( $sanitized ) ); 313 314 $value['name'] = ' '; // Blank spaces. 315 $sanitized = $setting->sanitize( $value ); 316 $this->assertEquals( '(unnamed)', $sanitized['name'] ); 313 317 } 314 318 … … 361 365 $this->assertArrayHasKey( 'error', $update_result ); 362 366 $this->assertArrayHasKey( 'status', $update_result ); 367 $this->assertArrayHasKey( 'saved_value', $update_result ); 368 $this->assertEquals( $new_value, $update_result['saved_value'] ); 363 369 364 370 $this->assertEquals( $menu_id, $update_result['term_id'] ); … … 411 417 $this->assertArrayHasKey( 'error', $update_result ); 412 418 $this->assertArrayHasKey( 'status', $update_result ); 419 $this->assertArrayHasKey( 'saved_value', $update_result ); 420 $this->assertEquals( $setting->value(), $update_result['saved_value'] ); 413 421 414 422 $this->assertEquals( $menu->term_id, $update_result['term_id'] ); … … 416 424 $this->assertNull( $update_result['error'] ); 417 425 $this->assertEquals( 'inserted', $update_result['status'] ); 426 } 427 428 /** 429 * Test saving a new name that conflicts with an existing nav menu's name. 430 * 431 * @see WP_Customize_Nav_Menu_Setting::update() 432 */ 433 function test_save_inserted_conflicted_name() { 434 do_action( 'customize_register', $this->wp_customize ); 435 436 $menu_name = 'Foo'; 437 wp_update_nav_menu_object( 0, array( 'menu-name' => $menu_name ) ); 438 439 $menu_id = -123; 440 $setting_id = "nav_menu[$menu_id]"; 441 $setting = new WP_Customize_Nav_Menu_Setting( $this->wp_customize, $setting_id ); 442 $this->wp_customize->set_post_value( $setting->id, array( 'name' => $menu_name ) ); 443 $setting->save(); 444 445 $expected_resolved_menu_name = "$menu_name (2)"; 446 $new_menu = wp_get_nav_menu_object( $setting->term_id ); 447 $this->assertEquals( $expected_resolved_menu_name, $new_menu->name ); 448 449 $save_response = apply_filters( 'customize_save_response', array() ); 450 $this->assertEquals( $expected_resolved_menu_name, $save_response['nav_menu_updates'][0]['saved_value']['name'] ); 418 451 } 419 452 … … 449 482 $this->assertArrayHasKey( 'error', $update_result ); 450 483 $this->assertArrayHasKey( 'status', $update_result ); 484 $this->assertArrayHasKey( 'saved_value', $update_result ); 485 $this->assertNull( $update_result['saved_value'] ); 451 486 452 487 $this->assertEquals( $menu_id, $update_result['term_id'] );
Note: See TracChangeset
for help on using the changeset viewer.