WordPress.org

Make WordPress Core

Ticket #41287: 41287.2.diff

File 41287.2.diff, 6.9 KB (added by earnjam, 18 months ago)
  • src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php

    diff --git src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php
    index b7b2dd79f6..ab53cd8d9b 100644
    class WP_REST_Posts_Controller extends WP_REST_Controller { 
    270270                foreach ( $taxonomies as $taxonomy ) {
    271271                        $base        = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;
    272272                        $tax_exclude = $base . '_exclude';
     273                        $tax_and     = $base . '_and';
    273274
    274275                        if ( ! empty( $request[ $base ] ) ) {
    275276                                $query_args['tax_query'][] = array(
    class WP_REST_Posts_Controller extends WP_REST_Controller { 
    289290                                        'operator'         => 'NOT IN',
    290291                                );
    291292                        }
     293
     294                        if ( ! empty( $request[ $tax_and ] ) ) {
     295                                $query_args['tax_query'][] = array(
     296                                        'taxonomy'         => $taxonomy->name,
     297                                        'field'            => 'term_id',
     298                                        'terms'            => $request[ $tax_and ],
     299                                        'include_children' => false,
     300                                        'operator'         => 'AND',
     301                                );
     302                        }
    292303                }
    293304
    294305                $posts_query  = new WP_Query();
    class WP_REST_Posts_Controller extends WP_REST_Controller { 
    22392250                                ),
    22402251                                'default'     => array(),
    22412252                        );
     2253
     2254                        $query_params[ $base . '_and' ] = array(
     2255                                /* translators: %s: taxonomy name */
     2256                                'description' => sprintf( __( 'Limit result set to all items that have all the specified terms assigned in the %s taxonomy.' ), $base ),
     2257                                'type'        => 'array',
     2258                                'items'       => array(
     2259                                        'type' => 'integer',
     2260                                ),
     2261                                'default'     => array(),
     2262                        );
    22422263                }
    22432264
    22442265                if ( 'post' === $this->post_type ) {
  • tests/phpunit/tests/rest-api/rest-posts-controller.php

    diff --git tests/phpunit/tests/rest-api/rest-posts-controller.php tests/phpunit/tests/rest-api/rest-posts-controller.php
    index 721b08292a..64e085a497 100644
    class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te 
    146146                                'author_exclude',
    147147                                'before',
    148148                                'categories',
     149                                'categories_and',
    149150                                'categories_exclude',
    150151                                'context',
    151152                                'exclude',
    class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te 
    160161                                'status',
    161162                                'sticky',
    162163                                'tags',
     164                                'tags_and',
    163165                                'tags_exclude',
    164166                        ), $keys
    165167                );
    class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te 
    865867                $this->assertEquals( $id1, $data[0]['id'] );
    866868        }
    867869
     870        public function test_get_items_tags_and_query() {
     871                $id1 = self::$post_id;
     872                $id2 = $this->factory->post->create( array( 'post_status' => 'publish' ) );
     873                $id3 = $this->factory->post->create( array( 'post_status' => 'publish' ) );
     874                $tag1 = wp_insert_term( 'Tag1', 'post_tag' );
     875                $tag2 = wp_insert_term( 'Tag2', 'post_tag' );
     876
     877                wp_set_object_terms( $id1, array( $tag1['term_id'] ), 'post_tag' );
     878                wp_set_object_terms( $id2, array( $tag2['term_id'] ), 'post_tag' );
     879                wp_set_object_terms( $id3, array( $tag1['term_id'], $tag2['term_id'] ), 'post_tag' );
     880                $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
     881                $request->set_param( 'tags_and', array( $tag1['term_id'], $tag2['term_id'] ) );
     882
     883                $response = rest_get_server()->dispatch( $request );
     884                $data     = $response->get_data();
     885                $this->assertCount( 1, $data );
     886                $this->assertEquals( $id3, $data[0]['id'] );
     887        }
     888
    868889        public function test_get_items_tags_exclude_query() {
    869890                $id1 = self::$post_id;
    870891                $id2 = $this->factory->post->create( array( 'post_status' => 'publish' ) );
    class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te 
    934955                $this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
    935956        }
    936957
     958        public function test_get_items_tags_and_and_categories_query() {
     959                $id1      = self::$post_id;
     960                $id2      = $this->factory->post->create( array( 'post_status' => 'publish' ) );
     961                $id3      = $this->factory->post->create( array( 'post_status' => 'publish' ) );
     962                $id4      = $this->factory->post->create( array( 'post_status' => 'publish' ) );
     963                $tag1     = wp_insert_term( 'Tag1', 'post_tag' );
     964                $tag2     = wp_insert_term( 'Tag2', 'post_tag' );
     965                $category = wp_insert_term( 'My Category', 'category' );
     966
     967                wp_set_object_terms( $id1, array( $tag1['term_id'], $tag2['term_id'] ), 'post_tag' );
     968                wp_set_object_terms( $id1, array( $category['term_id'] ), 'category' );
     969                wp_set_object_terms( $id2, array( $tag1['term_id'] ), 'post_tag' );
     970                wp_set_object_terms( $id2, array( $category['term_id'] ), 'category' );
     971                wp_set_object_terms( $id3, array( $category['term_id'] ), 'category' );
     972
     973                $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
     974                $request->set_param( 'tags_and', array( $tag1['term_id'], $tag2['term_id'] ) );
     975                $request->set_param( 'categories', array( $category['term_id'] ) );
     976
     977                $response = rest_get_server()->dispatch( $request );
     978                $data     = $response->get_data();
     979                $this->assertCount( 1, $data );
     980                $this->assertEquals( $id1, $data[0]['id'] );
     981        }
     982
    937983        public function test_get_items_sticky() {
    938984                $id1 = self::$post_id;
    939985                $id2 = $this->factory->post->create( array( 'post_status' => 'publish' ) );
  • tests/qunit/fixtures/wp-api-generated.js

    diff --git tests/qunit/fixtures/wp-api-generated.js tests/qunit/fixtures/wp-api-generated.js
    index fd20726c9d..49f1d6b930 100644
    mockedApiResponse.Schema = { 
    340340                                "type": "integer"
    341341                            }
    342342                        },
     343                        "categories_and": {
     344                            "required": false,
     345                            "default": [],
     346                            "description": "Limit result set to all items that have all the specified terms assigned in the categories taxonomy.",
     347                            "type": "array",
     348                            "items": {
     349                                "type": "integer"
     350                            }
     351                        },
    343352                        "tags": {
    344353                            "required": false,
    345354                            "default": [],
    mockedApiResponse.Schema = { 
    358367                                "type": "integer"
    359368                            }
    360369                        },
     370                        "tags_and": {
     371                            "required": false,
     372                            "default": [],
     373                            "description": "Limit result set to all items that have all the specified terms assigned in the tags taxonomy.",
     374                            "type": "array",
     375                            "items": {
     376                                "type": "integer"
     377                            }
     378                        },
    361379                        "sticky": {
    362380                            "required": false,
    363381                            "description": "Limit result set to items that are sticky.",