diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php index e0cdc79a2f..872a6607cb 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php @@ -148,6 +148,11 @@ class WP_REST_Posts_Controller extends WP_REST_Controller { return new WP_Error( 'rest_no_search_term_defined', __( 'You need to define a search term to order by relevance.' ), array( 'status' => 400 ) ); } + // Ensure an include parameter is set in case the orderby is set to 'include'. + if ( ! empty( $request['orderby'] ) && 'include' === $request['orderby'] && empty( $request['include'] ) ) { + return new WP_Error( 'rest_orderby_include_missing_include', sprintf( __( 'Missing parameter(s): %s' ), 'include' ), array( 'status' => 400 ) ); + } + // Retrieve the list of registered collection query parameters. $registered = $this->get_collection_params(); $args = array(); @@ -836,8 +841,17 @@ class WP_REST_Posts_Controller extends WP_REST_Controller { $query_args['ignore_sticky_posts'] = true; } - if ( 'include' === $query_args['orderby'] ) { - $query_args['orderby'] = 'post__in'; + // Map to proper WP_Query orderby param. + if ( isset( $query_args['orderby'] ) && isset( $request['orderby'] ) ) { + $orderby_mappings = array( + 'id' => 'ID', + 'include' => 'post__in', + 'slug' => 'post_name', + ); + + if ( isset( $orderby_mappings[ $request['orderby'] ] ) ) { + $query_args['orderby'] = $orderby_mappings[ $request['orderby'] ]; + } } return $query_args; diff --git a/tests/phpunit/tests/rest-api/rest-posts-controller.php b/tests/phpunit/tests/rest-api/rest-posts-controller.php index 8f8bc73476..886ae3c5a6 100644 --- a/tests/phpunit/tests/rest-api/rest-posts-controller.php +++ b/tests/phpunit/tests/rest-api/rest-posts-controller.php @@ -444,6 +444,50 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } + public function test_get_items_with_orderby_include_without_include_param() { + $this->factory->post->create( array( 'post_status' => 'publish' ) ); + $request = new WP_REST_Request( 'GET', '/wp/v2/posts' ); + $request->set_param( 'orderby', 'include' ); + + $response = $this->server->dispatch( $request ); + + $this->assertErrorResponse( 'rest_orderby_include_missing_include', $response, 400 ); + } + + public function test_get_items_with_orderby_id() { + $id1 = $this->factory->post->create( array( 'post_status' => 'publish', 'post_date' => '2016-01-13 02:26:48' ) ); + $id2 = $this->factory->post->create( array( 'post_status' => 'publish', 'post_date' => '2016-01-12 02:26:48' ) ); + $id3 = $this->factory->post->create( array( 'post_status' => 'publish', 'post_date' => '2016-01-11 02:26:48' ) ); + + $request = new WP_REST_Request( 'GET', '/wp/v2/posts' ); + $request->set_param( 'orderby', 'id' ); + $request->set_param( 'include', array( $id1, $id2, $id3 ) ); + + $response = $this->server->dispatch( $request ); + $data = $response->get_data(); + + // Default ORDER is DESC. + $this->assertEquals( $id3, $data[0]['id'] ); + $this->assertEquals( $id2, $data[1]['id'] ); + $this->assertEquals( $id1, $data[2]['id'] ); + } + + public function test_get_items_with_orderby_slug() { + $id1 = $this->factory->post->create( array( 'post_title' => 'ABC', 'post_name' => 'xyz', 'post_status' => 'publish' ) ); + $id2 = $this->factory->post->create( array( 'post_title' => 'XYZ', 'post_name' => 'abc', 'post_status' => 'publish' ) ); + + $request = new WP_REST_Request( 'GET', '/wp/v2/posts' ); + $request->set_param( 'orderby', 'slug' ); + $request->set_param( 'include', array( $id1, $id2 ) ); + + $response = $this->server->dispatch( $request ); + $data = $response->get_data(); + + // Default ORDER is DESC. + $this->assertEquals( 'xyz', $data[0]['slug'] ); + $this->assertEquals( 'abc', $data[1]['slug'] ); + } + public function test_get_items_with_orderby_relevance() { $this->factory->post->create( array( 'post_title' => 'Title is more relevant', 'post_content' => 'Content is', 'post_status' => 'publish' ) ); $this->factory->post->create( array( 'post_title' => 'Title is', 'post_content' => 'Content is less relevant', 'post_status' => 'publish' ) );