REST API: Fix handling of some orderby parameters for the Posts controller.

- 'orderby' => 'include' requires an array of post_ids via the include collection param.
- 'orderby' => 'id' and 'orderby' => 'slug' need map the correct WP_Query equivalents. 

Merges [39440] to the 4.7 branch.

Props flixos90, hnle, dd32, rachelbaker, joehoyle, pento.
Fixes #38971 for 4.7.


git-svn-id: https://develop.svn.wordpress.org/branches/4.7@39441 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Rachel Baker 2016-12-02 22:20:27 +00:00
parent fde4185ae4
commit 334635ee5e
2 changed files with 60 additions and 2 deletions

View File

@ -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;

View File

@ -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' ) );