diff --git a/src/wp-admin/js/nav-menu.js b/src/wp-admin/js/nav-menu.js index 264dc574fc..de11878da5 100644 --- a/src/wp-admin/js/nav-menu.js +++ b/src/wp-admin/js/nav-menu.js @@ -43,6 +43,7 @@ var wpNavMenu; this.attachQuickSearchListeners(); this.attachThemeLocationsListeners(); + this.attachMenuSaveSubmitListeners(); this.attachTabsPanelListeners(); @@ -834,6 +835,17 @@ var wpNavMenu; }); }, + attachMenuSaveSubmitListeners : function() { + /* + * When a navigation menu is saved, store a JSON representation of all form data + * in a single input to avoid PHP `max_input_vars` limitations. See #14134. + */ + $('#update-nav-menu').submit(function() { + var navMenuData = $('#update-nav-menu').serializeArray(); + $('[name="nav-menu-data"]').val( JSON.stringify( navMenuData ) ); + }); + }, + attachThemeLocationsListeners : function() { var loc = $('#nav-menu-theme-locations'), params = {}; params.action = 'menu-locations-save'; diff --git a/src/wp-admin/nav-menus.php b/src/wp-admin/nav-menus.php index 8f17e03031..7a6a18c8ad 100644 --- a/src/wp-admin/nav-menus.php +++ b/src/wp-admin/nav-menus.php @@ -49,6 +49,26 @@ $num_locations = count( array_keys( $locations ) ); // Allowed actions: add, update, delete $action = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : 'edit'; +/* + * If a JSON blob of navigation menu data is found, expand it and inject it + * into `$_POST` to avoid PHP `max_input_vars` limitations. See #14134. + */ +if ( isset( $_POST['nav-menu-data'] ) ) { + $data = json_decode( stripslashes( $_POST['nav-menu-data'] ) ); + if ( ! is_null( $data ) && $data ) { + foreach ( $data as $post_input_data ) { + // For input names that are arrays (e.g. `menu-item-db-id[3]`), derive the array path keys via regex. + if ( preg_match( '#(.*)(?:\[(\d+)\])#', $post_input_data->name, $matches ) ) { + if ( empty( $_POST[$matches[1]] ) ) { + $_POST[$matches[1]] = array(); + } + $_POST[$matches[1]][(int)$matches[2]] = $post_input_data->value; + } else { + $_POST[$post_input_data->name] = $post_input_data->value; + } + } + } +} switch ( $action ) { case 'add-menu-item': check_admin_referer( 'add-menu_item', 'menu-settings-column-nonce' ); @@ -731,6 +751,7 @@ require_once( ABSPATH . 'wp-admin/admin-header.php' );