Make WordPress Core

Changeset 36506


Ignore:
Timestamp:
02/10/2016 03:31:31 AM (11 years ago)
Author:
ericlewis
Message:

Menus: Allow larger menus to be created in the Edit Menu screen.

In the Edit Menu screen, each menu item creates 11 form input elements. In menus with more than 71 menu items, often items after the 71st weren't saved. This was because PHP's runtime configuration max_input_vars default value is 1000. Large menus exceed this, so PHP didn't populate the $_POST superglobal for the latter menu items.

The entire form is now JSON-encoded into a single input which populates $_POST manually on form submission.

See #14134.

Location:
trunk/src/wp-admin
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/js/nav-menu.js

    r36427 r36506  
    4444                        this.attachQuickSearchListeners();
    4545                        this.attachThemeLocationsListeners();
     46                        this.attachMenuSaveSubmitListeners();
    4647
    4748                        this.attachTabsPanelListeners();
     
    835836                },
    836837
     838                attachMenuSaveSubmitListeners : function() {
     839                        /*
     840                         * When a navigation menu is saved, store a JSON representation of all form data
     841                         * in a single input to avoid PHP `max_input_vars` limitations. See #14134.
     842                         */
     843                        $('#update-nav-menu').submit(function() {
     844                                var navMenuData = {};
     845                                $('#update-nav-menu input').each(function(index, element) {
     846                                        var name = $(element).attr('name');
     847                                        var regex = /(.*)(?:\[(\d+)\])/;
     848                                        if ( regex.test( name ) ) {
     849                                                var matches = regex.exec(name);
     850                                                if ( ! navMenuData[matches[1]] ) {
     851                                                        navMenuData[matches[1]] = [];
     852                                                }
     853                                                navMenuData[matches[1]][matches[2]] = $(element).val();
     854                                        } else {
     855                                                navMenuData[name] = $(element).val();
     856                                        }
     857                                });
     858                                $('[name="nav-menu-data"]').val( JSON.stringify( navMenuData ) );
     859                        });
     860                },
     861
    837862                attachThemeLocationsListeners : function() {
    838863                        var loc = $('#nav-menu-theme-locations'), params = {};
  • trunk/src/wp-admin/nav-menus.php

    r36422 r36506  
    4949// Allowed actions: add, update, delete
    5050$action = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : 'edit';
     51
     52/*
     53 * If a JSON blob of navigation menu data is found, expand it and inject it
     54 * into `$_POST` to avoid PHP `max_input_vars` limitations. See #14134.
     55 */
     56if ( isset( $_POST['nav-menu-data'] ) ) {
     57        $data = json_decode( stripslashes( $_POST['nav-menu-data'] ) );
     58        if ( ! is_null( $data ) && $data ) {
     59                foreach ( $data as $post_var => $post_data ) {
     60                        $_POST[$post_var] = $post_data;
     61                }
     62        }
     63}
    5164
    5265switch ( $action ) {
     
    732745                        <form id="update-nav-menu" method="post" enctype="multipart/form-data">
    733746                                <div class="menu-edit <?php if ( $add_new_screen ) echo 'blank-slate'; ?>">
     747                                        <input type="hidden" name="nav-menu-data">
    734748                                        <?php
    735749                                        wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
Note: See TracChangeset for help on using the changeset viewer.