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 | } |