diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-search-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-search-controller.php index 76021ff0b0..93502d60f4 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-search-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-search-controller.php @@ -331,6 +331,24 @@ class WP_REST_Search_Controller extends WP_REST_Controller { 'sanitize_callback' => array( $this, 'sanitize_subtypes' ), ); + $query_params['exclude'] = array( + 'description' => __( 'Ensure result set excludes specific IDs.' ), + 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), + 'default' => array(), + ); + + $query_params['include'] = array( + 'description' => __( 'Limit result set to specific IDs.' ), + 'type' => 'array', + 'items' => array( + 'type' => 'integer', + ), + 'default' => array(), + ); + return $query_params; } diff --git a/src/wp-includes/rest-api/search/class-wp-rest-post-search-handler.php b/src/wp-includes/rest-api/search/class-wp-rest-post-search-handler.php index 5d20661b05..5809245acf 100644 --- a/src/wp-includes/rest-api/search/class-wp-rest-post-search-handler.php +++ b/src/wp-includes/rest-api/search/class-wp-rest-post-search-handler.php @@ -69,6 +69,14 @@ class WP_REST_Post_Search_Handler extends WP_REST_Search_Handler { $query_args['s'] = $request['search']; } + if ( ! empty( $request['exclude'] ) ) { + $query_args['post__not_in'] = $request['exclude']; + } + + if ( ! empty( $request['include'] ) ) { + $query_args['post__in'] = $request['include']; + } + /** * Filters the query arguments for a REST API search request. * diff --git a/src/wp-includes/rest-api/search/class-wp-rest-term-search-handler.php b/src/wp-includes/rest-api/search/class-wp-rest-term-search-handler.php index af9b2e5663..eed35e7470 100644 --- a/src/wp-includes/rest-api/search/class-wp-rest-term-search-handler.php +++ b/src/wp-includes/rest-api/search/class-wp-rest-term-search-handler.php @@ -70,6 +70,14 @@ class WP_REST_Term_Search_Handler extends WP_REST_Search_Handler { $query_args['search'] = $request['search']; } + if ( ! empty( $request['exclude'] ) ) { + $query_args['exclude'] = $request['exclude']; + } + + if ( ! empty( $request['include'] ) ) { + $query_args['include'] = $request['include']; + } + /** * Filters the query arguments for a REST API search request. * diff --git a/tests/phpunit/tests/rest-api/rest-search-controller.php b/tests/phpunit/tests/rest-api/rest-search-controller.php index 1e59b26396..2b2e87adeb 100644 --- a/tests/phpunit/tests/rest-api/rest-search-controller.php +++ b/tests/phpunit/tests/rest-api/rest-search-controller.php @@ -819,4 +819,78 @@ class WP_Test_REST_Search_Controller extends WP_Test_REST_Controller_Testcase { return $request; } + /** + * @ticket 56546 + */ + public function test_get_items_search_posts_include_ids() { + $response = $this->do_request_with_params( + array( + 'include' => array_slice( self::$my_title_post_ids, 1, 2 ), + ) + ); + + $this->assertSame( 200, $response->get_status() ); + $this->assertSameSets( + array( self::$my_title_post_ids[1], self::$my_title_post_ids[2] ), + wp_list_pluck( $response->get_data(), 'id' ) + ); + } + + /** + * @ticket 56546 + */ + public function test_get_items_search_posts_exclude_ids() { + $response = $this->do_request_with_params( + array( + 'exclude' => self::$my_title_page_ids, + ) + ); + + $this->assertSame( 200, $response->get_status() ); + $this->assertSameSets( + array_merge( + self::$my_title_post_ids, + self::$my_content_post_ids + ), + wp_list_pluck( $response->get_data(), 'id' ) + ); + } + + /** + * @ticket 56546 + */ + public function test_get_items_search_terms_include_ids() { + $response = $this->do_request_with_params( + array( + 'include' => self::$my_tag_id, + 'type' => 'term', + ) + ); + + $this->assertSame( 200, $response->get_status() ); + $this->assertSameSets( + array( self::$my_tag_id ), + wp_list_pluck( $response->get_data(), 'id' ) + ); + } + + /** + * @ticket 56546 + */ + public function test_get_items_search_terms_exclude_ids() { + $response = $this->do_request_with_params( + array( + // "1" is the default category. + 'exclude' => array( 1, self::$my_tag_id ), + 'type' => 'term', + ) + ); + + $this->assertSame( 200, $response->get_status() ); + $this->assertSameSets( + array( self::$my_category_id ), + wp_list_pluck( $response->get_data(), 'id' ) + ); + } + } diff --git a/tests/qunit/fixtures/wp-api-generated.js b/tests/qunit/fixtures/wp-api-generated.js index 00b6a2f834..4020b25da8 100644 --- a/tests/qunit/fixtures/wp-api-generated.js +++ b/tests/qunit/fixtures/wp-api-generated.js @@ -9269,6 +9269,24 @@ mockedApiResponse.Schema = { "type": "string" }, "required": false + }, + "exclude": { + "description": "Ensure result set excludes specific IDs.", + "type": "array", + "items": { + "type": "integer" + }, + "default": [], + "required": false + }, + "include": { + "description": "Limit result set to specific IDs.", + "type": "array", + "items": { + "type": "integer" + }, + "default": [], + "required": false } } }