diff --git a/src/wp-admin/includes/nav-menu.php b/src/wp-admin/includes/nav-menu.php
index 18dcc97..951c03c 100644
|
a
|
b
|
function wp_nav_menu_update_menu_items ( $nav_menu_selected_id, $nav_menu_select
|
| 1057 | 1057 | |
| 1058 | 1058 | return $messages; |
| 1059 | 1059 | } |
| | 1060 | |
| | 1061 | /** |
| | 1062 | * If a JSON blob of navigation menu data is in POST data, expand it and inject |
| | 1063 | * it into `$_POST` to avoid PHP `max_input_vars` limitations. See #14134. |
| | 1064 | * |
| | 1065 | * @since 4.5.1 |
| | 1066 | */ |
| | 1067 | function wp_expand_nav_menu_post_data() { |
| | 1068 | if ( ! isset( $_POST['nav-menu-data'] ) ) { |
| | 1069 | return; |
| | 1070 | } |
| | 1071 | $data = json_decode( stripslashes( $_POST['nav-menu-data'] ) ); |
| | 1072 | if ( ! is_null( $data ) && $data ) { |
| | 1073 | foreach ( $data as $post_input_data ) { |
| | 1074 | // For input names that are arrays (e.g. `menu-item-db-id[3][4][5]`), derive the array path keys via regex. |
| | 1075 | if ( preg_match( '#([^\[]*)\[(.+)\]#', $post_input_data->name, $matches ) ) { |
| | 1076 | $array_bits = explode( '][', $matches[2] ); |
| | 1077 | $_new_data = array(); |
| | 1078 | for ( $i = count($array_bits) - 1; $i >= 0; $i -- ) { |
| | 1079 | if ( $i == count($array_bits) - 1 ) { |
| | 1080 | $_new_data[ $array_bits[$i] ] = wp_slash( $post_input_data->value ); |
| | 1081 | } else { |
| | 1082 | $_i = array(); |
| | 1083 | $_i[ $array_bits[$i] ] = $_new_data; |
| | 1084 | $_new_data = $_i; |
| | 1085 | } |
| | 1086 | } |
| | 1087 | $new_data = array(); |
| | 1088 | $new_data[$matches[1]] = $_new_data; |
| | 1089 | $_POST = array_merge_recursive( $_POST, $new_data ); |
| | 1090 | } else { |
| | 1091 | $_POST[ $post_input_data->name ] = wp_slash( $post_input_data->value ); |
| | 1092 | } |
| | 1093 | } |
| | 1094 | } |
| | 1095 | } |
diff --git a/src/wp-admin/nav-menus.php b/src/wp-admin/nav-menus.php
index 7099e49..a037659 100644
|
a
|
b
|
$action = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : 'edit';
|
| 53 | 53 | * If a JSON blob of navigation menu data is found, expand it and inject it |
| 54 | 54 | * into `$_POST` to avoid PHP `max_input_vars` limitations. See #14134. |
| 55 | 55 | */ |
| 56 | | if ( 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_input_data ) { |
| 60 | | // For input names that are arrays (e.g. `menu-item-db-id[3][4][5]`), derive the array path keys via regex. |
| 61 | | if ( preg_match( '#([^\[]*)\[(.+)\]#', $post_input_data->name, $matches ) ) { |
| 62 | | $array_bits = explode( '][', $matches[2] ); |
| 63 | | $_new_data = array(); |
| 64 | | for ( $i = count($array_bits) - 1; $i >= 0; $i -- ) { |
| 65 | | if ( $i == count($array_bits) - 1 ) { |
| 66 | | $_new_data[ $array_bits[$i] ] = wp_slash( $post_input_data->value ); |
| 67 | | } else { |
| 68 | | $_i = array(); |
| 69 | | $_i[ $array_bits[$i] ] = $_new_data; |
| 70 | | $_new_data = $_i; |
| 71 | | } |
| 72 | | } |
| 73 | | $new_data = array(); |
| 74 | | $new_data[$matches[1]] = $_new_data; |
| 75 | | $_POST = array_merge_recursive( $_POST, $new_data ); |
| 76 | | } else { |
| 77 | | $_POST[ $post_input_data->name ] = wp_slash( $post_input_data->value ); |
| 78 | | } |
| 79 | | } |
| 80 | | } |
| 81 | | } |
| | 56 | wp_expand_nav_menu_post_data(); |
| | 57 | |
| 82 | 58 | switch ( $action ) { |
| 83 | 59 | case 'add-menu-item': |
| 84 | 60 | check_admin_referer( 'add-menu_item', 'menu-settings-column-nonce' ); |
diff --git a/tests/phpunit/tests/menu/wpExpandNavMenuPostData.php b/tests/phpunit/tests/menu/wpExpandNavMenuPostData.php
new file mode 100644
index 0000000..9db1858
|
-
|
+
|
|
| | 1 | <?php |
| | 2 | |
| | 3 | /** |
| | 4 | * @group menu |
| | 5 | */ |
| | 6 | class Tests_Menu_WpExpandNavMenuPostData extends WP_UnitTestCase { |
| | 7 | |
| | 8 | public function test_multidimensional_nested_array_should_expand() { |
| | 9 | include_once( ABSPATH . 'wp-admin/includes/nav-menu.php' ); |
| | 10 | if ( empty( $_POST ) ) { |
| | 11 | $_POST = array(); |
| | 12 | } |
| | 13 | $data = array(); |
| | 14 | $data[0] = new StdClass; |
| | 15 | $data[0]->name = "would[1][do][the][trick]"; |
| | 16 | $data[0]->value = "yes"; |
| | 17 | $_POST['nav-menu-data'] = addslashes( json_encode( $data ) ); |
| | 18 | wp_expand_nav_menu_post_data(); |
| | 19 | $expected = array( |
| | 20 | 'nav-menu-data' => $_POST['nav-menu-data'], |
| | 21 | 'would' => array( |
| | 22 | 1 => array( |
| | 23 | 'do' => array( |
| | 24 | 'the' => array( |
| | 25 | 'trick' => 'yes' |
| | 26 | ) |
| | 27 | ) |
| | 28 | ) |
| | 29 | ) |
| | 30 | ); |
| | 31 | $this->assertEquals( $expected, $_POST ); |
| | 32 | } |
| | 33 | |
| | 34 | public function test_multidimensional_nested_array_should_expand_and_merge() { |
| | 35 | include_once( ABSPATH . 'wp-admin/includes/nav-menu.php' ); |
| | 36 | if ( empty( $_POST ) ) { |
| | 37 | $_POST = array(); |
| | 38 | } |
| | 39 | $data = array(); |
| | 40 | $data[0] = new StdClass; |
| | 41 | $data[0]->name = "would[1][do][the][trick]"; |
| | 42 | $data[0]->value = "yes"; |
| | 43 | $data[1] = new StdClass; |
| | 44 | $data[1]->name = "would[2][do][the][trick]"; |
| | 45 | $data[1]->value = "yes"; |
| | 46 | $data[2] = new StdClass; |
| | 47 | $data[2]->name = "would[2][do][the][job]"; |
| | 48 | $data[2]->value = "yes"; |
| | 49 | $_POST['nav-menu-data'] = addslashes( json_encode( $data ) ); |
| | 50 | wp_expand_nav_menu_post_data(); |
| | 51 | $expected = array( |
| | 52 | 'nav-menu-data' => $_POST['nav-menu-data'], |
| | 53 | 'would' => array( |
| | 54 | 1 => array( |
| | 55 | 'do' => array( |
| | 56 | 'the' => array( |
| | 57 | 'trick' => 'yes' |
| | 58 | ) |
| | 59 | ) |
| | 60 | ), |
| | 61 | 2 => array( |
| | 62 | 'do' => array( |
| | 63 | 'the' => array( |
| | 64 | 'trick' => 'yes', |
| | 65 | 'job' => 'yes' |
| | 66 | ) |
| | 67 | ) |
| | 68 | ) |
| | 69 | ) |
| | 70 | ); |
| | 71 | $this->assertEquals( $expected, $_POST ); |
| | 72 | } |
| | 73 | |
| | 74 | } |