WordPress.org

Make WordPress Core

Ticket #34923: 34923.11.diff

File 34923.11.diff, 38.1 KB (added by westonruter, 15 months ago)

Changes: https://github.com/xwp/wordpress-develop/compare/d0f13ae...32afe4c PR: https://github.com/xwp/wordpress-develop/pull/152

  • src/wp-admin/css/customize-controls.css

    diff --git src/wp-admin/css/customize-controls.css src/wp-admin/css/customize-controls.css
    index d2eef49..af62e5e 100644
    body.cheatin p { 
    12191219} 
    12201220 
    12211221.add-new-widget:before, 
    1222 .add-new-menu-item:before { 
     1222.add-new-menu-item:before, 
     1223#available-menu-items .new-content-item .add-content:before { 
    12231224        content: "\f132"; 
    12241225        display: inline-block; 
    12251226        position: relative; 
  • 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 afe0cbc..66d2b08 100644
     
    6161        text-align: right; 
    6262} 
    6363 
     64.customize-control-nav_menu_item.has-notifications .menu-item-handle { 
     65        border-left: 4px solid #00a0d2; 
     66} 
     67 
    6468.wp-customizer .menu-item-settings { 
    6569        max-width: 100%; 
    6670        overflow: hidden; 
     
    497501        color: #23282d; 
    498502} 
    499503 
    500 #available-menu-items .accordion-section-content { 
     504#available-menu-items .available-menu-items-list { 
    501505        overflow-y: auto; 
    502506        max-height: 200px; /* This gets set in JS to fit the screen size, and based on # of sections. */ 
    503507        background: transparent; 
     
    534538} 
    535539 
    536540#available-menu-items .accordion-section-content { 
    537         padding: 1px 15px 15px 15px; 
    538         margin: 0; 
    539541        max-height: 290px; 
     542        margin: 0; 
     543        padding: 0; 
     544        position: relative; 
     545        background: transparent; 
     546} 
     547 
     548#available-menu-items .accordion-section-content .available-menu-items-list { 
     549        margin: 0 0 45px 0; 
     550        padding: 1px 15px 15px 15px; 
     551} 
     552 
     553#available-menu-items .accordion-section-content .available-menu-items-list:only-child { /* Types that do not support new items for the current user */ 
     554        margin-bottom: 0; 
     555} 
     556 
     557#new-custom-menu-item .accordion-section-content { 
     558        padding: 0 15px 15px 15px; 
     559} 
     560 
     561#available-menu-items .accordion-section-content .new-content-item { 
     562        width: calc(100% - 30px); 
     563        padding: 8px 15px; 
     564        position: absolute; 
     565        bottom: 0; 
     566        z-index: 10; 
     567        background: #eee; 
     568        display: -webkit-box; 
     569        display: -moz-box; 
     570        display: -ms-flexbox; 
     571        display: -webkit-flex; 
     572        display: flex; 
     573} 
     574 
     575#available-menu-items .new-content-item .create-item-input { 
     576        -webkit-box-flex: 10; 
     577        -webkit-flex-grow: 10; 
     578        -moz-box-flex: 10; 
     579        -ms-flex-positive: 10; 
     580        -ms-flex: 10; 
     581        flex-grow: 10; 
     582        margin-left: 5px; 
     583        padding: 4.5px; 
     584} 
     585#available-menu-items .new-content-item .add-content { 
     586        padding-left: 6px; 
     587        -webkit-box-flex: 10; 
     588        -webkit-flex-grow: 10; 
     589        -moz-box-flex: 10; 
     590        -ms-flex-positive: 10; 
     591        -ms-flex: 10; 
     592        flex-grow: 1; 
    540593} 
    541594 
    542595#available-menu-items .menu-item-tpl { 
     
    546599#custom-menu-item-name.invalid, 
    547600#custom-menu-item-url.invalid, 
    548601.menu-name-field.invalid, 
    549 .menu-name-field.invalid:focus { 
     602.menu-name-field.invalid:focus, 
     603#available-menu-items .new-content-item .create-item-input.invalid, 
     604#available-menu-items .new-content-item .create-item-input.invalid:focus { 
    550605        border: 1px solid #f00; 
    551606} 
    552607 
  • 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 25495fe..e514a0a 100644
     
    8080        }); 
    8181        api.Menus.availableMenuItems = new api.Menus.AvailableItemCollection( api.Menus.data.availableMenuItems ); 
    8282 
     83        api.Menus.insertedAutoDrafts = []; 
     84 
     85        /** 
     86         * Insert a new `auto-draft` post. 
     87         * 
     88         * @param {object} params - Parameters for the draft post to create. 
     89         * @param {string} params.post_type - Post type to add. 
     90         * @param {string} params.post_title - Post title to use. 
     91         * @return {jQuery.promise} Promise resolved with the added post. 
     92         */ 
     93        api.Menus.insertAutoDraftPost = function insertAutoDraftPost( params ) { 
     94                var request, deferred = $.Deferred(); 
     95 
     96                request = wp.ajax.post( 'customize-nav-menus-insert-auto-draft', { 
     97                        'customize-menus-nonce': api.settings.nonce['customize-menus'], 
     98                        'wp_customize': 'on', 
     99                        'params': params 
     100                } ); 
     101 
     102                request.done( function( response ) { 
     103                        if ( response.post_id ) { 
     104                                deferred.resolve( response ); 
     105                                api.Menus.insertedAutoDrafts.push( response.post_id ); 
     106                                api( 'nav_menus_created_posts' ).set( _.clone( api.Menus.insertedAutoDrafts ) ); 
     107                        } 
     108                } ); 
     109 
     110                request.fail( function( response ) { 
     111                        var error = response || ''; 
     112 
     113                        if ( 'undefined' !== typeof response.message ) { 
     114                                error = response.message; 
     115                        } 
     116 
     117                        console.error( error ); 
     118                        deferred.rejectWith( error ); 
     119                } ); 
     120 
     121                return deferred.promise(); 
     122        }; 
     123 
    83124        /** 
    84125         * wp.customize.Menus.AvailableMenuItemsPanelView 
    85126         * 
     
    100141                        'click .menu-item-tpl': '_submit', 
    101142                        'click #custom-menu-item-submit': '_submitLink', 
    102143                        'keypress #custom-menu-item-name': '_submitLink', 
     144                        'click .new-content-item .add-content': '_submitNew', 
     145                        'keypress .create-item-input': '_submitNew', 
    103146                        'keydown': 'keyboardAccessible' 
    104147                }, 
    105148 
     
    115158                pages: {}, 
    116159                sectionContent: '', 
    117160                loading: false, 
     161                addingNew: false, 
    118162 
    119163                initialize: function() { 
    120164                        var self = this; 
     
    124168                        } 
    125169 
    126170                        this.$search = $( '#menu-items-search' ); 
    127                         this.sectionContent = this.$el.find( '.accordion-section-content' ); 
     171                        this.sectionContent = this.$el.find( '.available-menu-items-list' ); 
    128172 
    129173                        this.debounceSearch = _.debounce( self.search, 500 ); 
    130174 
     
    160204 
    161205                        // Load more items. 
    162206                        this.sectionContent.scroll( function() { 
    163                                 var totalHeight = self.$el.find( '.accordion-section.open .accordion-section-content' ).prop( 'scrollHeight' ), 
     207                                var totalHeight = self.$el.find( '.accordion-section.open .available-menu-items-list' ).prop( 'scrollHeight' ), 
    164208                                        visibleHeight = self.$el.find( '.accordion-section.open' ).height(); 
    165209 
    166210                                if ( ! self.loading && $( this ).scrollTop() > 3 / 4 * totalHeight - visibleHeight ) { 
     
    337381                                } 
    338382                                items = new api.Menus.AvailableItemCollection( items ); // @todo Why is this collection created and then thrown away? 
    339383                                self.collection.add( items.models ); 
    340                                 typeInner = availableMenuItemContainer.find( '.accordion-section-content' ); 
     384                                typeInner = availableMenuItemContainer.find( '.available-menu-items-list' ); 
    341385                                items.each(function( menuItem ) { 
    342386                                        typeInner.append( itemTemplate( menuItem.attributes ) ); 
    343387                                }); 
     
    356400 
    357401                // Adjust the height of each section of items to fit the screen. 
    358402                itemSectionHeight: function() { 
    359                         var sections, totalHeight, accordionHeight, diff; 
     403                        var sections, lists, totalHeight, accordionHeight, diff; 
    360404                        totalHeight = window.innerHeight; 
    361405                        sections = this.$el.find( '.accordion-section:not( #available-menu-items-search ) .accordion-section-content' ); 
    362                         accordionHeight =  46 * ( 2 + sections.length ) - 13; // Magic numbers. 
     406                        lists = this.$el.find( '.accordion-section:not( #available-menu-items-search ) .available-menu-items-list:not(":only-child")' ); 
     407                        accordionHeight =  46 * ( 1 + sections.length ) + 14; // Magic numbers. 
    363408                        diff = totalHeight - accordionHeight; 
    364409                        if ( 120 < diff && 290 > diff ) { 
    365410                                sections.css( 'max-height', diff ); 
     411                                lists.css( 'max-height', ( diff - 60 ) ); 
    366412                        } 
    367413                }, 
    368414 
     
    456502                        itemName.val( '' ); 
    457503                }, 
    458504 
     505                // Submit handler for keypress (enter) on field and click on button. 
     506                _submitNew: function( event ) { 
     507                        var container; 
     508 
     509                        // Only proceed with keypress if it is Enter. 
     510                        if ( 'keypress' === event.type && 13 !== event.which ) { 
     511                                return; 
     512                        } 
     513 
     514                        if ( this.addingNew ) { 
     515                                return; 
     516                        } 
     517 
     518                        container = $( event.target ).closest( '.accordion-section' ); 
     519 
     520                        this.submitNew( container ); 
     521                }, 
     522 
     523                // Creates a new object and adds an associated menu item to the menu. 
     524                submitNew: function( container ) { 
     525                        var panel = this, 
     526                                itemName = container.find( '.create-item-input' ), 
     527                                title = itemName.val(), 
     528                                dataContainer = container.find( '.available-menu-items-list' ), 
     529                                itemType = dataContainer.data( 'type' ), 
     530                                itemObject = dataContainer.data( 'object' ), 
     531                                itemTypeLabel = dataContainer.data( 'type_label' ), 
     532                                promise; 
     533 
     534                        if ( ! this.currentMenuControl ) { 
     535                                return; 
     536                        } 
     537 
     538                        // Only posts are supported currently. 
     539                        if ( 'post_type' !== itemType ) { 
     540                                return; 
     541                        } 
     542 
     543                        if ( '' === $.trim( itemName.val() ) ) { 
     544                                itemName.addClass( 'invalid' ); 
     545                                itemName.focus(); 
     546                                return; 
     547                        } else { 
     548                                itemName.removeClass( 'invalid' ); 
     549                                container.find( '.accordion-section-title' ).addClass( 'loading' ); 
     550                        } 
     551 
     552                        panel.addingNew = true; 
     553                        itemName.attr( 'disabled', 'disabled' ); 
     554                        promise = api.Menus.insertAutoDraftPost( { 
     555                                post_title: title, 
     556                                post_type: itemObject 
     557                        } ); 
     558                        promise.done( function( data ) { 
     559                                var availableItem, $content, itemTemplate; 
     560                                availableItem = new api.Menus.AvailableItemModel( { 
     561                                        'id': 'post-' + data.post_id, // Used for available menu item Backbone models. 
     562                                        'title': itemName.val(), 
     563                                        'type': itemType, 
     564                                        'type_label': itemTypeLabel, 
     565                                        'object': itemObject, 
     566                                        'object_id': data.post_id, 
     567                                        'url': data.url 
     568                                } ); 
     569 
     570                                // Add new item to menu. 
     571                                panel.currentMenuControl.addItemToMenu( availableItem.attributes ); 
     572 
     573                                // Add the new item to the list of available items. 
     574                                api.Menus.availableMenuItemsPanel.collection.add( availableItem ); 
     575                                $content = container.find( '.available-menu-items-list' ); 
     576                                itemTemplate = wp.template( 'available-menu-item' ); 
     577                                $content.prepend( itemTemplate( availableItem.attributes ) ); 
     578                                $content.scrollTop(); 
     579 
     580                                // Reset the create content form. 
     581                                itemName.val( '' ).removeAttr( 'disabled' ); 
     582                                panel.addingNew = false; 
     583                                container.find( '.accordion-section-title' ).removeClass( 'loading' ); 
     584                        } ); 
     585                }, 
     586 
    459587                // Opens the panel. 
    460588                open: function( menuControl ) { 
    461589                        this.currentMenuControl = menuControl; 
     
    25452673                        if ( data.nav_menu_updates || data.nav_menu_item_updates ) { 
    25462674                                api.Menus.applySavedData( data ); 
    25472675                        } 
     2676 
     2677                        // Reset list of inserted auto draft post IDs. 
     2678                        api.Menus.insertedAutoDrafts = []; 
    25482679                } ); 
    25492680 
    25502681                // Open and focus menu control. 
  • 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 f9832a6..898152d 100644
    final class WP_Customize_Nav_Menus { 
    5656                add_filter( 'customize_refresh_nonces', array( $this, 'filter_nonces' ) ); 
    5757                add_action( 'wp_ajax_load-available-menu-items-customizer', array( $this, 'ajax_load_available_items' ) ); 
    5858                add_action( 'wp_ajax_search-available-menu-items-customizer', array( $this, 'ajax_search_available_items' ) ); 
     59                add_action( 'wp_ajax_customize-nav-menus-insert-auto-draft', array( $this, 'ajax_insert_auto_draft_post' ) ); 
    5960                add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); 
    60  
    61                 // Needs to run after core Navigation section is set up. 
    6261                add_action( 'customize_register', array( $this, 'customize_register' ), 11 ); 
    63  
    6462                add_filter( 'customize_dynamic_setting_args', array( $this, 'filter_dynamic_setting_args' ), 10, 2 ); 
    6563                add_filter( 'customize_dynamic_setting_class', array( $this, 'filter_dynamic_setting_class' ), 10, 3 ); 
    6664                add_action( 'customize_controls_print_footer_scripts', array( $this, 'print_templates' ) ); 
    6765                add_action( 'customize_controls_print_footer_scripts', array( $this, 'available_items_template' ) ); 
    6866                add_action( 'customize_preview_init', array( $this, 'customize_preview_init' ) ); 
     67                add_action( 'customize_preview_init', array( $this, 'make_auto_draft_status_previewable' ) ); 
     68                add_action( 'customize_save_nav_menus_created_posts', array( $this, 'save_nav_menus_created_posts' ) ); 
    6969 
    7070                // Selective Refresh partials. 
    7171                add_filter( 'customize_dynamic_partial_args', array( $this, 'customize_dynamic_partial_args' ), 10, 2 ); 
    final class WP_Customize_Nav_Menus { 
    626626                        'section'  => 'add_menu', 
    627627                        'settings' => array(), 
    628628                ) ) ); 
     629 
     630                $this->manager->add_setting( new WP_Customize_Filter_Setting( $this->manager, 'nav_menus_created_posts', array( 
     631                        'transport' => 'postMessage', 
     632                        'default' => array(), 
     633                        'sanitize_callback' => array( $this, 'sanitize_nav_menus_created_posts' ), 
     634                ) ) ); 
    629635        } 
    630636 
    631637        /** 
    final class WP_Customize_Nav_Menus { 
    648654         * Return an array of all the available item types. 
    649655         * 
    650656         * @since 4.3.0 
     657         * @since 4.7.0  Each array item now includes a `$type_label` in in addition to `$title`, `$type`, and `$object`. 
    651658         * @access public 
    652659         * 
    653660         * @return array The available menu item types. 
    final class WP_Customize_Nav_Menus { 
    660667                        foreach ( $post_types as $slug => $post_type ) { 
    661668                                $item_types[] = array( 
    662669                                        'title'  => $post_type->labels->name, 
    663                                         'type'   => 'post_type', 
     670                                        'type_label' => $post_type->labels->singular_name, 
     671                                        'type' => 'post_type', 
    664672                                        'object' => $post_type->name, 
    665673                                ); 
    666674                        } 
    final class WP_Customize_Nav_Menus { 
    673681                                        continue; 
    674682                                } 
    675683                                $item_types[] = array( 
    676                                         'title'  => $taxonomy->labels->name, 
    677                                         'type'   => 'taxonomy', 
     684                                        'title' => $taxonomy->labels->name, 
     685                                        'type_label' => $taxonomy->labels->singular_name, 
     686                                        'type' => 'taxonomy', 
    678687                                        'object' => $taxonomy->name, 
    679688                                ); 
    680689                        } 
    final class WP_Customize_Nav_Menus { 
    684693                 * Filters the available menu item types. 
    685694                 * 
    686695                 * @since 4.3.0 
     696                 * @since 4.7.0  Each array item now includes a `$type_label` in in addition to `$title`, `$type`, and `$object`. 
    687697                 * 
    688698                 * @param array $item_types Custom menu item types. 
    689699                 */ 
    final class WP_Customize_Nav_Menus { 
    693703        } 
    694704 
    695705        /** 
     706         * Add a new `auto-draft` post. 
     707         * 
     708         * @access public 
     709         * @since 4.7.0 
     710         * 
     711         * @param array $postarr { 
     712         *     Abbreviated post array. 
     713         * 
     714         *     @var string $post_title Post title. 
     715         *     @var string $post_type  Post type. 
     716         * } 
     717         * @return WP_Post|WP_Error Inserted auto-draft post object or error. 
     718         */ 
     719        public function insert_auto_draft_post( $postarr ) { 
     720                if ( ! isset( $postarr['post_type'] ) || ! post_type_exists( $postarr['post_type'] )  ) { 
     721                        return new WP_Error( 'unknown_post_type', __( 'Unknown post type' ) ); 
     722                } 
     723                if ( ! isset( $postarr['post_title'] ) ) { 
     724                        $postarr['post_title'] = ''; 
     725                } 
     726 
     727                add_filter( 'wp_insert_post_empty_content', '__return_false', 1000 ); 
     728                $args = array( 
     729                        'post_status' => 'auto-draft', 
     730                        'post_type'   => $postarr['post_type'], 
     731                        'post_title'  => $postarr['post_title'], 
     732                        'post_name'   => sanitize_title( $postarr['post_title'] ), // Auto-drafts are allowed to have empty post_names, so we need to explicitly set it. 
     733                ); 
     734                $r = wp_insert_post( wp_slash( $args ), true ); 
     735                remove_filter( 'wp_insert_post_empty_content', '__return_false', 1000 ); 
     736 
     737                if ( is_wp_error( $r ) ) { 
     738                        return $r; 
     739                } else { 
     740                        return get_post( $r ); 
     741                } 
     742        } 
     743 
     744        /** 
     745         * Ajax handler for adding a new auto-draft post. 
     746         * 
     747         * @access public 
     748         * @since 4.7.0 
     749         */ 
     750        public function ajax_insert_auto_draft_post() { 
     751                if ( ! check_ajax_referer( 'customize-menus', 'customize-menus-nonce', false ) ) { 
     752                        status_header( 400 ); 
     753                        wp_send_json_error( 'bad_nonce' ); 
     754                } 
     755 
     756                if ( ! current_user_can( 'customize' ) ) { 
     757                        status_header( 403 ); 
     758                        wp_send_json_error( 'customize_not_allowed' ); 
     759                } 
     760 
     761                if ( empty( $_POST['params'] ) || ! is_array( $_POST['params'] ) ) { 
     762                        status_header( 400 ); 
     763                        wp_send_json_error( 'missing_params' ); 
     764                } 
     765 
     766                $params = wp_array_slice_assoc( 
     767                        array_merge( 
     768                                array( 
     769                                        'post_type' => '', 
     770                                        'post_title' => '', 
     771                                ), 
     772                                wp_unslash( $_POST['params'] ) 
     773                        ), 
     774                        array( 'post_type', 'post_title' ) 
     775                ); 
     776 
     777                if ( empty( $params['post_type'] ) || ! post_type_exists( $params['post_type'] ) ) { 
     778                        status_header( 400 ); 
     779                        wp_send_json_error( 'missing_post_type_param' ); 
     780                } 
     781 
     782                $post_type_object = get_post_type_object( $params['post_type'] ); 
     783                if ( ! current_user_can( $post_type_object->cap->create_posts ) || ! current_user_can( $post_type_object->cap->publish_posts ) ) { 
     784                        status_header( 403 ); 
     785                        wp_send_json_error( 'insufficient_post_permissions' ); 
     786                } 
     787 
     788                $params['post_title'] = trim( $params['post_title'] ); 
     789                if ( '' === $params['post_title'] ) { 
     790                        status_header( 400 ); 
     791                        wp_send_json_error( 'missing_post_title' ); 
     792                } 
     793 
     794                $r = $this->insert_auto_draft_post( $params ); 
     795                if ( is_wp_error( $r ) ) { 
     796                        $error = $r; 
     797                        if ( ! empty( $post_type_object->labels->singular_name ) ) { 
     798                                $singular_name = $post_type_object->labels->singular_name; 
     799                        } else { 
     800                                $singular_name = __( 'Post' ); 
     801                        } 
     802 
     803                        $data = array( 
     804                                /* translators: %1$s is the post type name and %2$s is the error message. */ 
     805                                'message' => sprintf( __( '%1$s could not be created: %2$s' ), $singular_name, $error->get_error_message() ), 
     806                        ); 
     807                        wp_send_json_error( $data ); 
     808                } else { 
     809                        $post = $r; 
     810                        $data = array( 
     811                                'post_id' => $post->ID, 
     812                                'url'     => get_permalink( $post->ID ), 
     813                        ); 
     814                        wp_send_json_success( $data ); 
     815                } 
     816        } 
     817 
     818        /** 
    696819         * Print the JavaScript templates used to render Menu Customizer components. 
    697820         * 
    698821         * Templates are imported into the JS use wp.template. 
    final class WP_Customize_Nav_Menus { 
    768891                                        <span class="spinner"></span> 
    769892                                </div> 
    770893                                <button type="button" class="clear-results"><span class="screen-reader-text"><?php _e( 'Clear Results' ); ?></span></button> 
    771                                 <ul class="accordion-section-content" data-type="search"></ul> 
     894                                <ul class="accordion-section-content available-menu-items-list" data-type="search"></ul> 
    772895                        </div> 
    773896                        <div id="new-custom-menu-item" class="accordion-section"> 
    774897                                <h4 class="accordion-section-title" role="presentation"> 
    final class WP_Customize_Nav_Menus { 
    797920                                </div> 
    798921                        </div> 
    799922                        <?php 
    800                         // Containers for per-post-type item browsing; items added with JS. 
     923 
     924                        // Containers for per-post-type item browsing; items are added with JS. 
    801925                        foreach ( $this->available_item_types() as $available_item_type ) { 
    802926                                $id = sprintf( 'available-menu-items-%s-%s', $available_item_type['type'], $available_item_type['object'] ); 
    803927                                ?> 
    final class WP_Customize_Nav_Menus { 
    813937                                                        <span class="toggle-indicator" aria-hidden="true"></span> 
    814938                                                </button> 
    815939                                        </h4> 
    816                                         <ul class="accordion-section-content" data-type="<?php echo esc_attr( $available_item_type['type'] ); ?>" data-object="<?php echo esc_attr( $available_item_type['object'] ); ?>"></ul> 
     940                                        <div class="accordion-section-content"> 
     941                                                <?php if ( 'post_type' === $available_item_type['type'] ) : ?> 
     942                                                        <?php $post_type_obj = get_post_type_object( $available_item_type['object'] ); ?> 
     943                                                        <?php if ( current_user_can( $post_type_obj->cap->create_posts ) && current_user_can( $post_type_obj->cap->publish_posts ) ) : ?> 
     944                                                                <div class="new-content-item"> 
     945                                                                        <input type="text" class="create-item-input" placeholder="<?php 
     946                                                                        /* translators: %s: Singular title of post type or taxonomy */ 
     947                                                                        printf( __( 'Create New %s' ), $post_type_obj->labels->singular_name ); ?>"> 
     948                                                                        <button type="button" class="button add-content"><?php _e( 'Add' ); ?></button> 
     949                                                                </div> 
     950                                                        <?php endif; ?> 
     951                                                <?php endif; ?> 
     952                                                <ul class="available-menu-items-list" data-type="<?php echo esc_attr( $available_item_type['type'] ); ?>" data-object="<?php echo esc_attr( $available_item_type['object'] ); ?>" data-type_label="<?php echo esc_attr( isset( $available_item_type['type_label'] ) ? $available_item_type['type_label'] : $available_item_type['type'] ); ?>"></ul> 
     953                                        </div> 
    817954                                </div> 
    818955                                <?php 
    819956                        } 
    final class WP_Customize_Nav_Menus { 
    8811018        } 
    8821019 
    8831020        /** 
     1021         * Make the auto-draft status protected so that it can be queried. 
     1022         * 
     1023         * @since 4.7.0 
     1024         * @access public 
     1025         */ 
     1026        public function make_auto_draft_status_previewable() { 
     1027                global $wp_post_statuses; 
     1028                $wp_post_statuses['auto-draft']->protected = true; 
     1029        } 
     1030 
     1031        /** 
     1032         * Sanitize post IDs for auto-draft posts created for nav menu items to be published. 
     1033         * 
     1034         * @since 4.7.0 
     1035         * @access public 
     1036         * 
     1037         * @param array $value Post IDs. 
     1038         * @returns array Post IDs. 
     1039         */ 
     1040        public function sanitize_nav_menus_created_posts( $value ) { 
     1041                $post_ids = array(); 
     1042                foreach ( wp_parse_id_list( $value ) as $post_id ) { 
     1043                        if ( empty( $post_id ) ) { 
     1044                                continue; 
     1045                        } 
     1046                        $post = get_post( $post_id ); 
     1047                        if ( 'auto-draft' !== $post->post_status ) { 
     1048                                continue; 
     1049                        } 
     1050                        $post_type_obj = get_post_type_object( $post->post_type ); 
     1051                        if ( ! $post_type_obj ) { 
     1052                                continue; 
     1053                        } 
     1054                        if ( ! current_user_can( $post_type_obj->cap->publish_posts ) || ! current_user_can( $post_type_obj->cap->edit_post, $post_id ) ) { 
     1055                                continue; 
     1056                        } 
     1057                        $post_ids[] = $post->ID; 
     1058                } 
     1059                return $post_ids; 
     1060        } 
     1061 
     1062        /** 
     1063         * Publish the auto-draft posts that were created for nav menu items. 
     1064         * 
     1065         * The post IDs will have been sanitized by already by 
     1066         * `WP_Customize_Nav_Menu_Items::sanitize_nav_menus_created_posts()` to 
     1067         * remove any post IDs for which the user cannot publish or for which the 
     1068         * post is not an auto-draft. 
     1069         * 
     1070         * @since 4.7.0 
     1071         * @access public 
     1072         * 
     1073         * @param WP_Customize_Setting $setting Customizer setting object. 
     1074         */ 
     1075        public function save_nav_menus_created_posts( $setting ) { 
     1076                $post_ids = $setting->post_value(); 
     1077                if ( ! empty( $post_ids ) ) { 
     1078                        foreach ( $post_ids as $post_id ) { 
     1079                                wp_publish_post( $post_id ); 
     1080                        } 
     1081                } 
     1082        } 
     1083 
     1084        /** 
    8841085         * Keep track of the arguments that are being passed to wp_nav_menu(). 
    8851086         * 
    8861087         * @since 4.3.0 
  • 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 a0d04d3..a16b100 100644
    class WP_Customize_Setting { 
    498498        /** 
    499499         * Fetch and sanitize the $_POST value for the setting. 
    500500         * 
     501         * During a save request prior to save, post_value() provides the new value while value() does not. 
     502         * 
    501503         * @since 3.4.0 
    502504         * 
    503505         * @param mixed $default A default value which is used as a fallback. Default is null. 
  • tests/phpunit/tests/ajax/CustomizeMenus.php

    diff --git tests/phpunit/tests/ajax/CustomizeMenus.php tests/phpunit/tests/ajax/CustomizeMenus.php
    index 025d29f..28871b7 100644
    class Tests_Ajax_CustomizeMenus extends WP_Ajax_UnitTestCase { 
    526526                        ), 
    527527                ); 
    528528        } 
     529 
     530        /** 
     531         * Testing successful ajax_insert_auto_draft_post() call. 
     532         * 
     533         * @covers WP_Customize_Nav_Menus::ajax_insert_auto_draft_post() 
     534         */ 
     535        function test_ajax_insert_auto_draft_post_success() { 
     536                $_POST = wp_slash( array( 
     537                        'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ), 
     538                        'params' => array( 
     539                                'post_type' => 'post', 
     540                                'post_title' => 'Hello World', 
     541                        ), 
     542                ) ); 
     543                $this->_last_response = ''; 
     544                $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' ); 
     545                $response = json_decode( $this->_last_response, true ); 
     546 
     547                $this->assertTrue( $response['success'] ); 
     548                $this->assertArrayHasKey( 'post_id', $response['data'] ); 
     549                $this->assertArrayHasKey( 'url', $response['data'] ); 
     550        } 
     551 
     552        /** 
     553         * Testing unsuccessful ajax_insert_auto_draft_post() call. 
     554         * 
     555         * @covers WP_Customize_Nav_Menus::ajax_insert_auto_draft_post() 
     556         */ 
     557        function test_ajax_insert_auto_draft_failures() { 
     558                // No nonce. 
     559                $_POST = array(); 
     560                $this->_last_response = ''; 
     561                $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' ); 
     562                $response = json_decode( $this->_last_response, true ); 
     563                $this->assertFalse( $response['success'] ); 
     564                $this->assertEquals( 'bad_nonce', $response['data'] ); 
     565 
     566                // Bad nonce. 
     567                $_POST = wp_slash( array( 
     568                        'customize-menus-nonce' => 'bad', 
     569                ) ); 
     570                $this->_last_response = ''; 
     571                $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' ); 
     572                $response = json_decode( $this->_last_response, true ); 
     573                $this->assertFalse( $response['success'] ); 
     574                $this->assertEquals( 'bad_nonce', $response['data'] ); 
     575 
     576                // Bad nonce. 
     577                wp_set_current_user( $this->factory()->user->create( array( 'role' => 'subscriber' ) ) ); 
     578                $_POST = wp_slash( array( 
     579                        'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ), 
     580                ) ); 
     581                $this->_last_response = ''; 
     582                $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' ); 
     583                $response = json_decode( $this->_last_response, true ); 
     584                $this->assertFalse( $response['success'] ); 
     585                $this->assertEquals( 'customize_not_allowed', $response['data'] ); 
     586 
     587                // Missing params. 
     588                wp_set_current_user( $this->factory()->user->create( array( 'role' => 'administrator' ) ) ); 
     589                $_POST = wp_slash( array( 
     590                        'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ), 
     591                ) ); 
     592                $this->_last_response = ''; 
     593                $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' ); 
     594                $response = json_decode( $this->_last_response, true ); 
     595                $this->assertFalse( $response['success'] ); 
     596                $this->assertEquals( 'missing_params', $response['data'] ); 
     597 
     598                // insufficient_post_permissions. 
     599                register_post_type( 'privilege', array( 'capability_type' => 'privilege' ) ); 
     600                $_POST = wp_slash( array( 
     601                        'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ), 
     602                        'params' => array( 
     603                                'post_type' => 'privilege', 
     604                        ), 
     605                ) ); 
     606                $this->_last_response = ''; 
     607                $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' ); 
     608                $response = json_decode( $this->_last_response, true ); 
     609                $this->assertFalse( $response['success'] ); 
     610                $this->assertEquals( 'insufficient_post_permissions', $response['data'] ); 
     611 
     612                // insufficient_post_permissions. 
     613                $_POST = wp_slash( array( 
     614                        'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ), 
     615                        'params' => array( 
     616                                'post_type' => 'non-existent', 
     617                        ), 
     618                ) ); 
     619                $this->_last_response = ''; 
     620                $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' ); 
     621                $response = json_decode( $this->_last_response, true ); 
     622                $this->assertFalse( $response['success'] ); 
     623                $this->assertEquals( 'missing_post_type_param', $response['data'] ); 
     624 
     625                // missing_post_title. 
     626                $_POST = wp_slash( array( 
     627                        'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ), 
     628                        'params' => array( 
     629                                'post_type' => 'post', 
     630                                'post_title' => '    ', 
     631                        ), 
     632                ) ); 
     633                $this->_last_response = ''; 
     634                $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' ); 
     635                $response = json_decode( $this->_last_response, true ); 
     636                $this->assertFalse( $response['success'] ); 
     637                $this->assertEquals( 'missing_post_title', $response['data'] ); 
     638        } 
    529639} 
  • tests/phpunit/tests/customize/nav-menus.php

    diff --git tests/phpunit/tests/customize/nav-menus.php tests/phpunit/tests/customize/nav-menus.php
    index f5d56b6..06e2333 100644
    class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase { 
    4545         */ 
    4646        function filter_item_types( $items ) { 
    4747                $items[] = array( 
    48                         'title'  => 'Custom', 
    49                         'type'   => 'custom_type', 
     48                        'title' => 'Custom', 
     49                        'type' => 'custom_type', 
    5050                        'object' => 'custom_object', 
     51                        'type_label' => 'Custom Type', 
    5152                ); 
    5253 
    5354                return $items; 
    class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase { 
    8485                do_action( 'customize_register', $this->wp_customize ); 
    8586                $menus = new WP_Customize_Nav_Menus( $this->wp_customize ); 
    8687                $this->assertInstanceOf( 'WP_Customize_Manager', $menus->manager ); 
     88 
     89                $this->assertEquals( 10, add_filter( 'customize_refresh_nonces', array( $menus, 'filter_nonces' ) ) ); 
     90                $this->assertEquals( 10, add_action( 'wp_ajax_load-available-menu-items-customizer', array( $menus, 'ajax_load_available_items' ) ) ); 
     91                $this->assertEquals( 10, add_action( 'wp_ajax_search-available-menu-items-customizer', array( $menus, 'ajax_search_available_items' ) ) ); 
     92                $this->assertEquals( 10, add_action( 'wp_ajax_customize-nav-menus-insert-auto-draft', array( $menus, 'ajax_insert_auto_draft_post' ) ) ); 
     93                $this->assertEquals( 10, add_action( 'customize_controls_enqueue_scripts', array( $menus, 'enqueue_scripts' ) ) ); 
     94                $this->assertEquals( 11, add_action( 'customize_register', array( $menus, 'customize_register' ) ) ); 
     95                $this->assertEquals( 10, add_filter( 'customize_dynamic_setting_args', array( $menus, 'filter_dynamic_setting_args' ) ) ); 
     96                $this->assertEquals( 10, add_filter( 'customize_dynamic_setting_class', array( $menus, 'filter_dynamic_setting_class' ) ) ); 
     97                $this->assertEquals( 10, add_action( 'customize_controls_print_footer_scripts', array( $menus, 'print_templates' ) ) ); 
     98                $this->assertEquals( 10, add_action( 'customize_controls_print_footer_scripts', array( $menus, 'available_items_template' ) ) ); 
     99                $this->assertEquals( 10, add_action( 'customize_preview_init', array( $menus, 'customize_preview_init' ) ) ); 
     100                $this->assertEquals( 10, add_action( 'customize_preview_init', array( $menus, 'make_auto_draft_status_previewable' ) ) ); 
     101                $this->assertEquals( 10, add_action( 'customize_save_nav_menus_created_posts', array( $menus, 'save_nav_menus_created_posts' ) ) ); 
     102                $this->assertEquals( 10, add_filter( 'customize_dynamic_partial_args', array( $menus, 'customize_dynamic_partial_args' ) ) ); 
    87103        } 
    88104 
    89105        /** 
    class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase { 
    444460                        'menu-item-title'     => 'Hello World', 
    445461                        'menu-item-status'    => 'publish', 
    446462                ) ); 
    447                 $setting = new WP_Customize_Nav_Menu_Item_Setting( $this->wp_customize, "nav_menu_item[$item_id]" ); 
    448463                do_action( 'customize_register', $this->wp_customize ); 
     464                $this->assertInstanceOf( 'WP_Customize_Nav_Menu_Item_Setting', $this->wp_customize->get_setting( "nav_menu_item[$item_id]" ) ); 
    449465                $this->assertEquals( 'Primary', $this->wp_customize->get_section( "nav_menu[$menu_id]" )->title ); 
    450466                $this->assertEquals( 'Hello World', $this->wp_customize->get_control( "nav_menu_item[$item_id]" )->label ); 
     467 
     468                $nav_menus_created_posts_setting = $this->wp_customize->get_setting( 'nav_menus_created_posts' ); 
     469                $this->assertInstanceOf( 'WP_Customize_Filter_Setting', $nav_menus_created_posts_setting ); 
     470                $this->assertEquals( 'postMessage', $nav_menus_created_posts_setting->transport ); 
     471                $this->assertEquals( array(), $nav_menus_created_posts_setting->default ); 
     472                $this->assertEquals( array( $this->wp_customize->nav_menus, 'sanitize_nav_menus_created_posts' ), $nav_menus_created_posts_setting->sanitize_callback ); 
    451473        } 
    452474 
    453475        /** 
    class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase { 
    479501                $menus = new WP_Customize_Nav_Menus( $this->wp_customize ); 
    480502 
    481503                $expected = array( 
    482                         array( 'title' => 'Posts', 'type' => 'post_type', 'object' => 'post' ), 
    483                         array( 'title' => 'Pages', 'type' => 'post_type', 'object' => 'page' ), 
    484                         array( 'title' => 'Categories', 'type' => 'taxonomy', 'object' => 'category' ), 
    485                         array( 'title' => 'Tags', 'type' => 'taxonomy', 'object' => 'post_tag' ), 
     504                        array( 'title' => 'Posts', 'type' => 'post_type', 'object' => 'post', 'type_label' => __( 'Post' ) ), 
     505                        array( 'title' => 'Pages', 'type' => 'post_type', 'object' => 'page', 'type_label' => __( 'Page' ) ), 
     506                        array( 'title' => 'Categories', 'type' => 'taxonomy', 'object' => 'category', 'type_label' => __( 'Category' ) ), 
     507                        array( 'title' => 'Tags', 'type' => 'taxonomy', 'object' => 'post_tag', 'type_label' => __( 'Tag' ) ), 
    486508                ); 
    487509 
    488510                if ( current_theme_supports( 'post-formats' ) ) { 
    489                         $expected[] = array( 'title' => 'Format', 'type' => 'taxonomy', 'object' => 'post_format' ); 
     511                        $expected[] = array( 'title' => 'Format', 'type' => 'taxonomy', 'object' => 'post_format', 'type_label' => __( 'Format' ) ); 
    490512                } 
    491513 
    492514                $this->assertEquals( $expected, $menus->available_item_types() ); 
    493515 
    494516                register_taxonomy( 'wptests_tax', array( 'post' ), array( 'labels' => array( 'name' => 'Foo' ) ) ); 
    495                 $expected[] = array( 'title' => 'Foo', 'type' => 'taxonomy', 'object' => 'wptests_tax' ); 
     517                $expected[] = array( 'title' => 'Foo', 'type' => 'taxonomy', 'object' => 'wptests_tax', 'type_label' => 'Foo' ); 
    496518 
    497519                $this->assertEquals( $expected, $menus->available_item_types() ); 
    498520 
    499                 $expected[] = array( 'title' => 'Custom', 'type' => 'custom_type', 'object' => 'custom_object' ); 
     521                $expected[] = array( 'title' => 'Custom', 'type' => 'custom_type', 'object' => 'custom_object', 'type_label' => 'Custom Type' ); 
    500522 
    501523                add_filter( 'customize_nav_menu_available_item_types', array( $this, 'filter_item_types' ) ); 
    502524                $this->assertEquals( $expected, $menus->available_item_types() ); 
    class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase { 
    505527        } 
    506528 
    507529        /** 
     530         * Test insert_auto_draft_post method. 
     531         * 
     532         * @covers WP_Customize_Nav_Menus::insert_auto_draft_post() 
     533         */ 
     534        public function test_insert_auto_draft_post() { 
     535                $menus = new WP_Customize_Nav_Menus( $this->wp_customize ); 
     536 
     537                $r = $menus->insert_auto_draft_post( array() ); 
     538                $this->assertInstanceOf( 'WP_Error', $r ); 
     539                $this->assertEquals( 'unknown_post_type', $r->get_error_code() ); 
     540 
     541                $r = $menus->insert_auto_draft_post( array( 'post_type' => 'fake' ) ); 
     542                $this->assertInstanceOf( 'WP_Error', $r ); 
     543                $this->assertEquals( 'unknown_post_type', $r->get_error_code() ); 
     544 
     545                $r = $menus->insert_auto_draft_post( array( 'post_title' => 'Hello World', 'post_type' => 'post' ) ); 
     546                $this->assertInstanceOf( 'WP_Post', $r ); 
     547                $this->assertEquals( 'Hello World', $r->post_title ); 
     548                $this->assertEquals( 'post', $r->post_type ); 
     549                $this->assertEquals( sanitize_title( $r->post_title ), $r->post_name ); 
     550        } 
     551 
     552        /** 
    508553         * Test the print_templates method. 
    509554         * 
    510555         * @see WP_Customize_Nav_Menus::print_templates() 
    class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase { 
    553598                                $this->assertRegExp( '#<h4 class="accordion-section-title".*>\s*' . esc_html( $type->labels->name ) . '#', $template ); 
    554599                                $this->assertContains( 'data-type="post_type"', $template ); 
    555600                                $this->assertContains( 'data-object="' . esc_attr( $type->name ) . '"', $template ); 
     601                                $this->assertContains( 'data-type_label="' . esc_attr( $type->labels->singular_name ) . '"', $template ); 
    556602                        } 
    557603                } 
    558604 
    class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase { 
    563609                                $this->assertRegExp( '#<h4 class="accordion-section-title".*>\s*' . esc_html( $tax->labels->name ) . '#', $template ); 
    564610                                $this->assertContains( 'data-type="taxonomy"', $template ); 
    565611                                $this->assertContains( 'data-object="' . esc_attr( $tax->name ) . '"', $template ); 
     612                                $this->assertContains( 'data-type_label="' . esc_attr( $tax->labels->singular_name ) . '"', $template ); 
    566613                        } 
    567614                } 
    568615 
    class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase { 
    570617                $this->assertRegExp( '#<h4 class="accordion-section-title".*>\s*Custom#', $template ); 
    571618                $this->assertContains( 'data-type="custom_type"', $template ); 
    572619                $this->assertContains( 'data-object="custom_object"', $template ); 
     620                $this->assertContains( 'data-type_label="Custom Type"', $template ); 
    573621        } 
    574622 
    575623        /** 
    class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase { 
    610658        } 
    611659 
    612660        /** 
     661         * Test make_auto_draft_status_previewable. 
     662         * 
     663         * @covers WP_Customize_Nav_Menus::make_auto_draft_status_previewable() 
     664         */ 
     665        function test_make_auto_draft_status_previewable() { 
     666                global $wp_post_statuses; 
     667                $menus = new WP_Customize_Nav_Menus( $this->wp_customize ); 
     668                $menus->make_auto_draft_status_previewable(); 
     669                $this->assertTrue( $wp_post_statuses['auto-draft']->protected ); 
     670        } 
     671 
     672        /** 
     673         * Test sanitize_nav_menus_created_posts. 
     674         * 
     675         * @covers WP_Customize_Nav_Menus::sanitize_nav_menus_created_posts() 
     676         */ 
     677        function test_sanitize_nav_menus_created_posts() { 
     678                $menus = new WP_Customize_Nav_Menus( $this->wp_customize ); 
     679                $contributor_user_id = $this->factory()->user->create( array( 'role' => 'contributor' ) ); 
     680                $author_user_id = $this->factory()->user->create( array( 'role' => 'author' ) ); 
     681                $administrator_user_id = $this->factory()->user->create( array( 'role' => 'administrator' ) ); 
     682 
     683                $contributor_post_id = $this->factory()->post->create( array( 
     684                        'post_status' => 'auto-draft', 
     685                        'post_title' => 'Contributor Post', 
     686                        'post_type' => 'post', 
     687                        'post_author' => $contributor_user_id, 
     688                ) ); 
     689                $author_post_id = $this->factory()->post->create( array( 
     690                        'post_status' => 'auto-draft', 
     691                        'post_title' => 'Author Post', 
     692                        'post_type' => 'post', 
     693                        'post_author' => $author_user_id, 
     694                ) ); 
     695                $administrator_post_id = $this->factory()->post->create( array( 
     696                        'post_status' => 'auto-draft', 
     697                        'post_title' => 'Admin Post', 
     698                        'post_type' => 'post', 
     699                        'post_author' => $administrator_user_id, 
     700                ) ); 
     701 
     702                $value = array( 
     703                        'bad', 
     704                        $contributor_post_id, 
     705                        $author_post_id, 
     706                        $administrator_post_id, 
     707                ); 
     708 
     709                wp_set_current_user( $contributor_user_id ); 
     710                $sanitized = $menus->sanitize_nav_menus_created_posts( $value ); 
     711                $this->assertEquals( array(), $sanitized ); 
     712 
     713                wp_set_current_user( $author_user_id ); 
     714                $sanitized = $menus->sanitize_nav_menus_created_posts( $value ); 
     715                $this->assertEquals( array( $author_post_id ), $sanitized ); 
     716 
     717                wp_set_current_user( $administrator_user_id ); 
     718                $sanitized = $menus->sanitize_nav_menus_created_posts( $value ); 
     719                $this->assertEquals( array( $contributor_post_id, $author_post_id, $administrator_post_id ), $sanitized ); 
     720        } 
     721 
     722        /** 
     723         * Test save_nav_menus_created_posts. 
     724         * 
     725         * @covers WP_Customize_Nav_Menus::save_nav_menus_created_posts() 
     726         */ 
     727        function test_save_nav_menus_created_posts() { 
     728                $menus = new WP_Customize_Nav_Menus( $this->wp_customize ); 
     729                do_action( 'customize_register', $this->wp_customize ); 
     730 
     731                $post_ids = $this->factory()->post->create_many( 3, array( 
     732                        'post_status' => 'auto-draft', 
     733                        'post_type' => 'post', 
     734                ) ); 
     735                $pre_published_post_id = $this->factory()->post->create( array( 'post_status' => 'publish' ) ); 
     736 
     737                $setting_id = 'nav_menus_created_posts'; 
     738                $this->wp_customize->set_post_value( $setting_id, array_merge( $post_ids, array( $pre_published_post_id ) ) ); 
     739                $setting = $this->wp_customize->get_setting( $setting_id ); 
     740                $this->assertInstanceOf( 'WP_Customize_Filter_Setting', $setting ); 
     741                $this->assertEquals( array( $menus, 'sanitize_nav_menus_created_posts' ), $setting->sanitize_callback ); 
     742                $this->assertEquals( $post_ids, $setting->post_value() ); 
     743                foreach ( $post_ids as $post_id ) { 
     744                        $this->assertEquals( 'auto-draft', get_post_status( $post_id ) ); 
     745                } 
     746 
     747                $save_action_count = did_action( 'customize_save_nav_menus_created_posts' ); 
     748                $setting->save(); 
     749                $this->assertEquals( $save_action_count + 1, did_action( 'customize_save_nav_menus_created_posts' ) ); 
     750                foreach ( $post_ids as $post_id ) { 
     751                        $this->assertEquals( 'publish', get_post_status( $post_id ) ); 
     752                } 
     753        } 
     754 
     755        /** 
    613756         * Test the filter_wp_nav_menu_args method. 
    614757         * 
    615758         * @see WP_Customize_Nav_Menus::filter_wp_nav_menu_args()