REST API: Add support for modifying the term relation when querying posts.

By default, a post most contain any of the requested terms to be included in the response. This commit adds a new `operator` property that can be set to `AND` to require a post to contain all of the requested terms.

For example, `/wp/v2/posts?tags[terms]=1,2,3&tags[operator]=AND` will return posts that have tags with the ids of 1, 2, and 3.

Props dlh, earnjam, Clorith, jnylen0, sebbb.
Fixes #41287.


git-svn-id: https://develop.svn.wordpress.org/trunk@51026 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Timothy Jacobs
2021-05-26 02:15:51 +00:00
parent 9d3e32ecbf
commit 852a2c216c
3 changed files with 857 additions and 260 deletions
@@ -2941,12 +2941,17 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
if ( $tax_include ) {
$terms = array();
$include_children = false;
$operator = 'IN';
if ( rest_is_array( $tax_include ) ) {
$terms = $tax_include;
} elseif ( rest_is_object( $tax_include ) ) {
$terms = empty( $tax_include['terms'] ) ? array() : $tax_include['terms'];
$include_children = ! empty( $tax_include['include_children'] );
if ( isset( $tax_include['operator'] ) && 'AND' === $tax_include['operator'] ) {
$operator = 'AND';
}
}
if ( $terms ) {
@@ -2955,6 +2960,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
'field' => 'term_id',
'terms' => $terms,
'include_children' => $include_children,
'operator' => $operator,
);
}
}
@@ -3048,6 +3054,14 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
),
$limit_schema
);
// 'operator' is supported only for 'include' queries.
$include_schema['oneOf'][1]['properties']['operator'] = array(
'description' => __( 'Whether items must be assigned all or any of the specified terms.' ),
'type' => 'string',
'enum' => array( 'AND', 'OR' ),
'default' => 'OR',
);
$exclude_schema = array_merge(
array(
/* translators: %s: Taxonomy name. */
@@ -1294,6 +1294,47 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te
$this->assertContains( $p2, $found_ids );
}
/**
* @ticket 41287
*/
public function test_get_items_with_all_categories() {
$taxonomy = get_taxonomy( 'category' );
$categories = static::factory()->term->create_many( 2, array( 'taxonomy' => $taxonomy->name ) );
$p1 = static::factory()->post->create(
array(
'post_status' => 'publish',
'post_category' => array( $categories[0] ),
)
);
$p2 = static::factory()->post->create(
array(
'post_status' => 'publish',
'post_category' => array( $categories[1] ),
)
);
$p3 = static::factory()->post->create(
array(
'post_status' => 'publish',
'post_category' => $categories,
)
);
$request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
$request->set_param(
$taxonomy->rest_base,
array(
'terms' => $categories,
'operator' => 'AND',
)
);
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$this->assertCount( 1, $data );
$this->assertSame( $p3, $data[0]['id'] );
}
/**
* @ticket 44326
*/
File diff suppressed because it is too large Load Diff