REST API: Add tax relation parameter to posts collection.

The REST API supports filtering by terms across multiple taxonomies using an AND relation. This adds support for an OR relation by adding "tax_relation=OR" as a query parameter.

Props earnjam.
Fixes #44326.


git-svn-id: https://develop.svn.wordpress.org/trunk@46646 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Timothy Jacobs 2019-11-03 23:12:44 +00:00
parent 20d984f4c9
commit a104c82526
3 changed files with 91 additions and 0 deletions

View File

@ -270,6 +270,10 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
$taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) );
if ( ! empty( $request['tax_relation'] ) ) {
$query_args['tax_query'] = array( 'relation' => $request['tax_relation'] );
}
foreach ( $taxonomies as $taxonomy ) {
$base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;
$tax_exclude = $base . '_exclude';
@ -2531,6 +2535,14 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
$taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) );
if ( ! empty( $taxonomies ) ) {
$query_params['tax_relation'] = array(
'description' => __( 'Limit result set based on relationship between multiple taxonomies.' ),
'type' => 'string',
'enum' => array( 'AND', 'OR' ),
);
}
foreach ( $taxonomies as $taxonomy ) {
$base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;

View File

@ -175,6 +175,7 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te
'sticky',
'tags',
'tags_exclude',
'tax_relation',
),
$keys
);
@ -959,6 +960,32 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te
$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
}
/**
* @ticket 44326
*/
public function test_get_items_tags_or_categories_query() {
$id1 = self::$post_id;
$id2 = $this->factory->post->create( array( 'post_status' => 'publish' ) );
$id3 = $this->factory->post->create( array( 'post_status' => 'publish' ) );
$id4 = $this->factory->post->create( array( 'post_status' => 'publish' ) );
$tag = wp_insert_term( 'My Tag', 'post_tag' );
$category = wp_insert_term( 'My Category', 'category' );
wp_set_object_terms( $id1, array( $tag['term_id'] ), 'post_tag' );
wp_set_object_terms( $id2, array( $category['term_id'] ), 'category' );
$request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
$request->set_param( 'tax_relation', 'OR' );
$request->set_param( 'tags', array( $tag['term_id'] ) );
$request->set_param( 'categories', array( $category['term_id'] ) );
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$this->assertCount( 2, $data );
$this->assertEquals( $id2, $data[0]['id'] );
$this->assertEquals( $id1, $data[1]['id'] );
}
public function test_get_items_tags_and_categories_exclude_query() {
$id1 = self::$post_id;
$id2 = $this->factory->post->create( array( 'post_status' => 'publish' ) );
@ -985,6 +1012,49 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te
$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
}
/**
* @ticket 44326
*/
public function test_get_items_tags_or_categories_exclude_query() {
$id1 = self::$post_id;
$id2 = $this->factory->post->create( array( 'post_status' => 'publish' ) );
$id3 = $this->factory->post->create( array( 'post_status' => 'publish' ) );
$id4 = $this->factory->post->create( array( 'post_status' => 'publish' ) );
$tag = wp_insert_term( 'My Tag', 'post_tag' );
$category = wp_insert_term( 'My Category', 'category' );
wp_set_object_terms( $id1, array( $tag['term_id'] ), 'post_tag' );
wp_set_object_terms( $id2, array( $tag['term_id'] ), 'post_tag' );
wp_set_object_terms( $id2, array( $category['term_id'] ), 'category' );
wp_set_object_terms( $id3, array( $category['term_id'] ), 'category' );
$request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
$request->set_param( 'tags', array( $tag['term_id'] ) );
$request->set_param( 'categories_exclude', array( $category['term_id'] ) );
$request->set_param( 'tax_relation', 'OR' );
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$this->assertCount( 3, $data );
$this->assertEquals( $id2, $data[0]['id'] );
$this->assertEquals( $id4, $data[1]['id'] );
$this->assertEquals( $id1, $data[2]['id'] );
}
/**
* @ticket 44326
*/
public function test_get_items_relation_with_no_tax_query() {
$request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
$request->set_param( 'tax_relation', 'OR' );
$request->set_param( 'include', self::$post_id );
$response = rest_get_server()->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$this->assertCount( 1, $response->get_data() );
$this->assertEquals( self::$post_id, $response->get_data()[0]['id'] );
}
public function test_get_items_sticky() {
$id1 = self::$post_id;
$id2 = $this->factory->post->create( array( 'post_status' => 'publish' ) );

View File

@ -322,6 +322,15 @@ mockedApiResponse.Schema = {
"type": "string"
}
},
"tax_relation": {
"required": false,
"enum": [
"AND",
"OR"
],
"description": "Limit result set based on relationship between multiple taxonomies.",
"type": "string"
},
"categories": {
"required": false,
"default": [],