diff --git a/lib/class-wp-rest-menu-items-controller.php b/lib/class-wp-rest-menu-items-controller.php index ddaaf102990d0f..636376fcdee360 100644 --- a/lib/class-wp-rest-menu-items-controller.php +++ b/lib/class-wp-rest-menu-items-controller.php @@ -524,7 +524,19 @@ protected function prepare_item_for_database( $request ) { } } - // Check if nav menu is valid. + // If menu id is set, validate the value of menu item position. + if ( ! empty( $prepared_nav_item['menu-id'] ) ) { + // Check if nav menu is valid. + if ( ! is_nav_menu( $prepared_nav_item['menu-id'] ) ) { + return new WP_Error( 'invalid_menu_id', __( 'Invalid menu ID.', 'gutenberg' ), array( 'status' => 400 ) ); + } + + // Check if menu item position is non-zero and positive. + if ( (int) $prepared_nav_item['menu-item-position'] < 1 ) { + return new WP_Error( 'invalid_menu_order', __( 'Invalid menu order.', 'gutenberg' ), array( 'status' => 400 ) ); + } + } + if ( ! empty( $prepared_nav_item['menu-id'] ) && ! is_nav_menu( $prepared_nav_item['menu-id'] ) ) { return new WP_Error( 'invalid_menu_id', __( 'Invalid menu ID.', 'gutenberg' ), array( 'status' => 400 ) ); } diff --git a/phpunit/class-rest-nav-menu-items-controller-test.php b/phpunit/class-rest-nav-menu-items-controller-test.php index 172a354b23d2f3..b793a23ef72048 100644 --- a/phpunit/class-rest-nav-menu-items-controller-test.php +++ b/phpunit/class-rest-nav-menu-items-controller-test.php @@ -271,6 +271,66 @@ public function test_create_item_invalid_term() { $this->assertErrorResponse( 'rest_term_invalid_id', $response, 400 ); } + /** + * + */ + public function test_create_item_change_position() { + wp_set_current_user( self::$admin_id ); + $new_menu_id = wp_create_nav_menu( rand_str() ); + $expected = array(); + $actual = array(); + for ( $i = 1; $i < 5; $i ++ ) { + $request = new WP_REST_Request( 'POST', '/__experimental/menu-items' ); + $request->add_header( 'content-type', 'application/x-www-form-urlencoded' ); + $params = $this->set_menu_item_data( + array( + 'menu_order' => $i, + 'menus' => $new_menu_id, + ) + ); + $request->set_body_params( $params ); + $response = rest_get_server()->dispatch( $request ); + $this->check_create_menu_item_response( $response ); + $data = $response->get_data(); + + $expected[] = $i; + $actual[] = $data['menu_order']; + } + $this->assertEquals( $actual, $expected ); + } + + /** + * + */ + public function test_menu_order_must_be_set() { + wp_set_current_user( self::$admin_id ); + $new_menu_id = wp_create_nav_menu( rand_str() ); + + $request = new WP_REST_Request( 'POST', '/__experimental/menu-items' ); + $request->add_header( 'content-type', 'application/x-www-form-urlencoded' ); + $params = $this->set_menu_item_data( + array( + 'menu_order' => 0, + 'menus' => $new_menu_id, + ) + ); + $request->set_body_params( $params ); + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'invalid_menu_order', $response, 400 ); + + $request = new WP_REST_Request( 'POST', '/__experimental/menu-items' ); + $request->add_header( 'content-type', 'application/x-www-form-urlencoded' ); + $params = $this->set_menu_item_data( + array( + 'menu_order' => 1, + 'menus' => $new_menu_id, + ) + ); + $request->set_body_params( $params ); + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 201, $response->get_status() ); + } + /** * */ @@ -818,7 +878,7 @@ protected function set_menu_item_data( $args = array() ) { $defaults = array( 'object_id' => 0, 'parent' => 0, - 'menu_order' => 0, + 'menu_order' => 1, 'menus' => $this->menu_id, 'type' => 'custom', 'title' => 'Custom Link Title',