WordPress.org

Make WordPress Core

Ticket #36697: 36697.5.diff

File 36697.5.diff, 9.5 KB (added by curdin, 4 years ago)

https://github.com/xwp/wordpress-develop/pull/189

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

    diff --git a/src/wp-admin/js/customize-nav-menus.js b/src/wp-admin/js/customize-nav-menus.js
    index 58af669..04fee07 100644
    a b  
    360360                        // Render the template for each item by type.
    361361                        _.each( api.Menus.data.itemTypes, function( itemType ) {
    362362                                self.pages[ itemType.type + ':' + itemType.object ] = 0;
    363                                 self.loadItems( itemType.type, itemType.object ); // @todo we need to combine these Ajax requests.
    364363                        } );
     364                        self.loadItems( api.Menus.data.itemTypes );
    365365                },
    366366
    367367                // Load available menu items.
    368368                loadItems: function( type, object ) {
    369                         var self = this, params, request, itemTemplate, availableMenuItemContainer;
     369                        var self = this, params, request, requestParams, itemTemplate, availableMenuItemContainers = {}, container;
    370370                        itemTemplate = wp.template( 'available-menu-item' );
    371371
    372                         if ( -1 === self.pages[ type + ':' + object ] ) {
    373                                 return;
     372                        if ( type instanceof Array ) {
     373
     374                                _.each( type, function( itemType, index ) {
     375                                        var type, object, container;
     376                                        type = itemType.type;
     377                                        object = itemType.object;
     378
     379                                        if ( -1 === self.pages[ type + ':' + object ] ) {
     380                                                type.splice( index );
     381                                        }  else {
     382                                                container = $( '#available-menu-items-' + type + '-' + object );
     383                                                container.find( '.accordion-section-title' ).addClass( 'loading' );
     384                                                availableMenuItemContainers[ type + ':' + object ] = container;
     385                                        }
     386
     387                                } );
     388
     389                                requestParams = {
     390                                        'item_types': type
     391                                };
     392
     393                        } else {
     394
     395                                if ( -1 === self.pages[ type + ':' + object ] ) {
     396                                        return;
     397                                }
     398
     399                                container = $( '#available-menu-items-' + type + '-' + object );
     400                                container.find( '.accordion-section-title' ).addClass( 'loading' );
     401                                availableMenuItemContainers[ type + ':' + object ] = container;
     402
     403                                requestParams = {
     404                                        'type': type,
     405                                        'object': object,
     406                                        'page': self.pages[ type + ':' + object ]
     407                                };
    374408                        }
    375                         availableMenuItemContainer = $( '#available-menu-items-' + type + '-' + object );
    376                         availableMenuItemContainer.find( '.accordion-section-title' ).addClass( 'loading' );
     409
    377410                        self.loading = true;
    378411                        params = {
    379412                                'customize-menus-nonce': api.settings.nonce['customize-menus'],
    380                                 'wp_customize': 'on',
    381                                 'type': type,
    382                                 'object': object,
    383                                 'page': self.pages[ type + ':' + object ]
     413                                'wp_customize': 'on'
    384414                        };
     415                        _.extend( params, requestParams );
    385416                        request = wp.ajax.post( 'load-available-menu-items-customizer', params );
    386417
    387418                        request.done(function( data ) {
    388419                                var items, typeInner;
    389420                                items = data.items;
    390                                 if ( 0 === items.length ) {
    391                                         if ( 0 === self.pages[ type + ':' + object ] ) {
    392                                                 availableMenuItemContainer
    393                                                         .addClass( 'cannot-expand' )
    394                                                         .removeClass( 'loading' )
    395                                                         .find( '.accordion-section-title > button' )
    396                                                         .prop( 'tabIndex', -1 );
    397                                         }
    398                                         self.pages[ type + ':' + object ] = -1;
    399                                         return;
    400                                 } else if ( ( 'page' === object ) && ( ! availableMenuItemContainer.hasClass( 'open' ) ) ) {
    401                                         availableMenuItemContainer.find( '.accordion-section-title > button' ).click();
    402                                 }
    403                                 items = new api.Menus.AvailableItemCollection( items ); // @todo Why is this collection created and then thrown away?
    404                                 self.collection.add( items.models );
    405                                 typeInner = availableMenuItemContainer.find( '.available-menu-items-list' );
    406                                 items.each(function( menuItem ) {
    407                                         typeInner.append( itemTemplate( menuItem.attributes ) );
    408                                 });
    409                                 self.pages[ type + ':' + object ] += 1;
     421                                _.each( items, function( item, name ) {
     422                                                if ( 0 === item.length ) {
     423                                                        if ( 0 === self.pages[ name ] ) {
     424                                                                availableMenuItemContainers[ name ].find( '.accordion-section-title' )
     425                                                                        .addClass( 'cannot-expand' )
     426                                                                        .removeClass( 'loading' )
     427                                                                        .find( '.accordion-section-title > button' )
     428                                                                        .prop( 'tabIndex', -1 );
     429                                                        }
     430                                                        self.pages[ name ] = -1;
     431                                                        return;
     432                                                } else if ( ( 'post_type:page' === name ) && ( ! availableMenuItemContainers[ name ].hasClass( 'open' ) ) ) {
     433                                                        availableMenuItemContainers[ name ].find( '.accordion-section-title > button' ).click();
     434                                                }
     435                                                item = new api.Menus.AvailableItemCollection( item ); // @todo Why is this collection created and then thrown away?
     436                                                self.collection.add( item.models );
     437                                                typeInner = availableMenuItemContainers[ name ].find( '.available-menu-items-list' );
     438                                                item.each( function( menuItem ) {
     439                                                        typeInner.append( itemTemplate( menuItem.attributes ) );
     440                                                } );
     441                                                self.pages[ name ] += 1;
     442                                        });
    410443                        });
    411444                        request.fail(function( data ) {
    412445                                if ( typeof console !== 'undefined' && console.error ) {
     
    414447                                }
    415448                        });
    416449                        request.always(function() {
    417                                 availableMenuItemContainer.find( '.accordion-section-title' ).removeClass( 'loading' );
     450                                _.each( availableMenuItemContainers, function( container ) {
     451                                        container.find( '.accordion-section-title' ).removeClass( 'loading' );
     452                                } );
    418453                                self.loading = false;
    419454                        });
    420455                },
  • src/wp-includes/class-wp-customize-nav-menus.php

    diff --git a/src/wp-includes/class-wp-customize-nav-menus.php b/src/wp-includes/class-wp-customize-nav-menus.php
    index 66dd466..d448048 100644
    a b public function ajax_load_available_items() { 
    100100                        wp_die( -1 );
    101101                }
    102102
    103                 if ( empty( $_POST['type'] ) || empty( $_POST['object'] ) ) {
     103                $all_items = array();
     104
     105                $item_types = array();
     106                if ( isset( $_POST['item_types'] ) ) {
     107                        $item_types = $_POST['item_types'];
     108                } elseif ( isset( $_POST['type'] ) && isset( $_POST['object'] ) ) {
     109                        $type = sanitize_key( $_POST['type'] );
     110                        $object = sanitize_key( $_POST['object'] );
     111                        $page = empty( $_POST['page'] ) ? 0 : absint( $_POST['page'] );
     112                        $item_types[0] = array(
     113                                'type' => $type,
     114                                'object' => $object,
     115                                'page' => $page,
     116                        );
     117                } else {
    104118                        wp_send_json_error( 'nav_menus_missing_type_or_object_parameter' );
    105119                }
    106120
    107                 $type = sanitize_key( $_POST['type'] );
    108                 $object = sanitize_key( $_POST['object'] );
    109                 $page = empty( $_POST['page'] ) ? 0 : absint( $_POST['page'] );
    110                 $items = $this->load_available_items_query( $type, $object, $page );
    111 
    112                 if ( is_wp_error( $items ) ) {
    113                         wp_send_json_error( $items->get_error_code() );
    114                 } else {
    115                         wp_send_json_success( array( 'items' => $items ) );
     121                foreach ( $item_types as $item_type ) {
     122                        if ( empty( $item_type['type'] ) || empty( $item_type['object'] ) ) {
     123                                wp_send_json_error( 'nav_menus_missing_type_or_object_parameter' );
     124                        }
     125                        $type = sanitize_key( $item_type['type'] );
     126                        $object = sanitize_key( $item_type['object'] );
     127                        $page = empty( $item_type['page'] ) ? 0 : absint( $item_type['page'] );
     128                        $items = $this->load_available_items_query( $type, $object, $page );
     129                        if ( is_wp_error( $items ) ) {
     130                                wp_send_json_error( $items->get_error_code() );
     131                        }
     132                        $all_items[ $item_type['type'] . ':' . $item_type['object'] ] = $items;
    116133                }
     134
     135                wp_send_json_success( array( 'items' => $all_items ) );
    117136        }
    118137
    119138        /**
  • tests/phpunit/tests/ajax/CustomizeMenus.php

    diff --git a/tests/phpunit/tests/ajax/CustomizeMenus.php b/tests/phpunit/tests/ajax/CustomizeMenus.php
    index 8614350..5013701 100644
    a b function data_ajax_load_available_items_error_messages() { 
    174174                        // Testing empty obj_type.
    175175                        array(
    176176                                array(
    177                                         'type'     => '',
    178                                         'object'   => 'post',
     177                                        'type'     => 'post_type',
     178                                        'object'   => '',
    179179                                ),
    180180                                array(
    181181                                        'success'  => false,
    function data_ajax_load_available_items_error_messages() { 
    193193                                        'data'     => 'nav_menus_missing_type_or_object_parameter',
    194194                                ),
    195195                        ),
     196                        // Testing empty type of a bulk request.
     197                        array(
     198                                array(
     199                                        'item_types' => array(
     200                                                array(
     201                                                        'type'     => 'post_type',
     202                                                        'object'   => 'post',
     203                                                ),
     204                                                array(
     205                                                        'type'     => 'post_type',
     206                                                        'object'   => '',
     207                                                ),
     208                                        ),
     209                                ),
     210                                array(
     211                                        'success'  => false,
     212                                        'data'     => 'nav_menus_missing_type_or_object_parameter',
     213                                ),
     214                        ),
    196215                        // Testing incorrect type option.
    197216                        array(
    198217                                array(
    function data_ajax_load_available_items_success_status() { 
    276295                                ),
    277296                                true,
    278297                        ),
     298                        // Testing a bulk request.
     299                        array(
     300                                array(
     301                                        'item_types' => array(
     302                                                array(
     303                                                        'type'     => 'post_type',
     304                                                        'object'   => 'post',
     305                                                ),
     306                                                array(
     307                                                        'type'     => 'post_type',
     308                                                        'object'   => 'page',
     309                                                ),
     310                                        ),
     311                                ),
     312                                true,
     313                        ),
    279314                );
    280315        }
    281316
    function test2_ajax_load_available_items_structure( $post_args ) { 
    313348                // Get the results.
    314349                $response = json_decode( $this->_last_response, true );
    315350
    316                 $this->assertNotEmpty( $response['data']['items'] );
     351                $this->assertNotEmpty( current( $response['data']['items'] ) );
    317352
    318353                // Get the second index to avoid the home page edge case.
    319                 $test_item = $response['data']['items'][1];
     354                $first_prop = current( $response['data']['items'] );
     355                $test_item = $first_prop[1];
    320356
    321357                foreach ( $expected_keys as $key ) {
    322358                        $this->assertArrayHasKey( $key, $test_item );
    function test2_ajax_load_available_items_structure( $post_args ) { 
    325361
    326362                // Special test for the home page.
    327363                if ( 'page' === $test_item['object'] ) {
    328                         $home = $response['data']['items'][0];
     364                        $first_prop = current( $response['data']['items'] );
     365                        $home = $first_prop[0];
    329366                        foreach ( $expected_keys as $key ) {
    330367                                if ( 'object_id' !== $key ) {
    331368                                        $this->assertArrayHasKey( $key, $home );