From a0f36df8a596dc9043cf407a0fd0fdb84490f9aa Mon Sep 17 00:00:00 2001 From: andrei draganescu Date: Tue, 25 Aug 2020 06:41:45 +0300 Subject: [PATCH] Adds suggestions for categories and formats to LinkControl (#22600) * adds suggestions for categories and formats adds a format search handler adds a category search handler hooks the new handlers in the search endpoint updates LinkControl's fetchLinkSuggestions to handle formats and categories as well * adds concurent search for suggestions also searches for category matches via term query and limits formats with no items * generalizes the category search handler to all terms * lint * adds links to terms search results * adds default listing for empty searches and a stup test class * shows empty terms in results for search and tests pass * REST API: Add pagination to term search handler * Navigation: Remove unnecessary async * REST API: Fix doc comments * REST API: Use null instead of empty string * REST API: Add pagination to page format search handler * REST API: Fix term search handler tests * REST API: Add post format search handler tests * REST API: Only show term subtypes which are REST API enabled * REST API: Use WP_Term_Query's 'search' param * REST API: Use wp_count_terms() instead of WP_Term_Query * REST API: Set fields=all when fetching terms so that they're cached * REST API: Use rest_get_route_for_term() instead of custom method * REST API: Pass forwards-compatible array to rest_post_format_search_query * REST API: Improve stability of WP_REST_Post_Format_Search_Handler tests * REST API: Add test for when no term matches search query * Navigation: Don't call /v2/search?type=post-format if theme does not support formats * REST API: Fix post format handler tests Co-authored-by: Robert Anderson --- ...ass-wp-rest-post-format-search-handler.php | 120 ++++++++ lib/class-wp-rest-term-search-handler.php | 142 ++++++++++ lib/load.php | 6 + lib/rest-api.php | 29 ++ packages/edit-navigation/src/index.js | 59 +++- .../editor/src/components/provider/index.js | 57 +++- ...p-rest-post-format-search-handler-test.php | 158 +++++++++++ ...class-wp-rest-term-search-handler-test.php | 263 ++++++++++++++++++ 8 files changed, 809 insertions(+), 25 deletions(-) create mode 100644 lib/class-wp-rest-post-format-search-handler.php create mode 100644 lib/class-wp-rest-term-search-handler.php create mode 100644 phpunit/class-wp-rest-post-format-search-handler-test.php create mode 100644 phpunit/class-wp-rest-term-search-handler-test.php diff --git a/lib/class-wp-rest-post-format-search-handler.php b/lib/class-wp-rest-post-format-search-handler.php new file mode 100644 index 00000000000000..e13bbbfab32286 --- /dev/null +++ b/lib/class-wp-rest-post-format-search-handler.php @@ -0,0 +1,120 @@ +type = 'post-format'; + } + + /** + * Searches the object type content for a given search request. + * + * @param WP_REST_Request $request Full REST request. + * @return array Associative array containing an `WP_REST_Search_Handler::RESULT_IDS` containing + * an array of found IDs and `WP_REST_Search_Handler::RESULT_TOTAL` containing the + * total count for the matching search results. + */ + public function search_items( WP_REST_Request $request ) { + $format_strings = get_post_format_strings(); + $format_slugs = array_keys( $format_strings ); + + $query_args = array(); + + if ( ! empty( $request['search'] ) ) { + $query_args['search'] = $request['search']; + } + + /** + * Filters the query arguments for a search request. + * + * Enables adding extra arguments or setting defaults for a post format search request. + * + * @param array $query_args Key value array of query var to query value. + * @param WP_REST_Request $request The request used. + */ + $query_args = apply_filters( 'rest_post_format_search_query', $query_args, $request ); + + $found_ids = array(); + foreach ( $format_slugs as $index => $format_slug ) { + if ( ! empty( $query_args['search'] ) ) { + $format_string = get_post_format_string( $format_slug ); + $format_slug_match = stripos( $format_slug, $query_args['search'] ) !== false; + $format_string_match = stripos( $format_string, $query_args['search'] ) !== false; + if ( ! $format_slug_match && ! $format_string_match ) { + continue; + } + } + + $format_link = get_post_format_link( $format_slug ); + if ( $format_link ) { + // Formats don't have an ID, so fake one using the array index. + $found_ids[] = $index + 1; + } + } + + $page = (int) $request['page']; + $per_page = (int) $request['per_page']; + + return array( + self::RESULT_IDS => array_slice( $found_ids, ( $page - 1 ) * $per_page, $per_page ), + self::RESULT_TOTAL => count( $found_ids ), + ); + } + + /** + * Prepares the search result for a given ID. + * + * @param int $id Item ID. + * @param array $fields Fields to include for the item. + * @return array Associative array containing all fields for the item. + */ + public function prepare_item( $id, array $fields ) { + $format_strings = get_post_format_strings(); + $format_slugs = array_keys( $format_strings ); + $format_slug = $format_slugs[ $id - 1 ]; + + $data = array(); + + if ( in_array( WP_REST_Search_Controller::PROP_ID, $fields, true ) ) { + $data[ WP_REST_Search_Controller::PROP_ID ] = $id; + } + + if ( in_array( WP_REST_Search_Controller::PROP_TITLE, $fields, true ) ) { + $data[ WP_REST_Search_Controller::PROP_TITLE ] = get_post_format_string( $format_slug ); + } + + if ( in_array( WP_REST_Search_Controller::PROP_URL, $fields, true ) ) { + $data[ WP_REST_Search_Controller::PROP_URL ] = get_post_format_link( $format_slug ); + } + + if ( in_array( WP_REST_Search_Controller::PROP_TYPE, $fields, true ) ) { + $data[ WP_REST_Search_Controller::PROP_TYPE ] = $this->type; + } + + return $data; + } + + /** + * Prepares links for the search result. + * + * @param string $id Item ID. + * @return array Links for the given item. + */ + public function prepare_item_links( $id ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable + return array(); + } + +} diff --git a/lib/class-wp-rest-term-search-handler.php b/lib/class-wp-rest-term-search-handler.php new file mode 100644 index 00000000000000..53b5eb5ad62267 --- /dev/null +++ b/lib/class-wp-rest-term-search-handler.php @@ -0,0 +1,142 @@ +type = 'term'; + + $this->subtypes = array_values( + get_taxonomies( + array( + 'public' => true, + 'show_in_rest' => true, + ), + 'names' + ) + ); + } + + /** + * Searches the object type content for a given search request. + * + * @param WP_REST_Request $request Full REST request. + * @return array Associative array containing an `WP_REST_Search_Handler::RESULT_IDS` containing + * an array of found IDs and `WP_REST_Search_Handler::RESULT_TOTAL` containing the + * total count for the matching search results. + */ + public function search_items( WP_REST_Request $request ) { + $taxonomies = $request[ WP_REST_Search_Controller::PROP_SUBTYPE ]; + if ( in_array( WP_REST_Search_Controller::TYPE_ANY, $taxonomies, true ) ) { + $taxonomies = $this->subtypes; + } + + $page = (int) $request['page']; + $per_page = (int) $request['per_page']; + + $query_args = array( + 'taxonomy' => $taxonomies, + 'hide_empty' => false, + 'offset' => ( $page - 1 ) * $per_page, + 'number' => $per_page, + ); + + if ( ! empty( $request['search'] ) ) { + $query_args['search'] = $request['search']; + } + + /** + * Filters the query arguments for a search request. + * + * Enables adding extra arguments or setting defaults for a term search request. + * + * @param array $query_args Key value array of query var to query value. + * @param WP_REST_Request $request The request used. + */ + $query_args = apply_filters( 'rest_term_search_query', $query_args, $request ); + + $query = new WP_Term_Query(); + $found_terms = $query->query( $query_args ); + $found_ids = wp_list_pluck( $found_terms, 'term_id' ); + + unset( $query_args['offset'], $query_args['number'] ); + + $total = wp_count_terms( $query_args ); + + // wp_count_terms() can return a falsey value when the term has no children. + if ( ! $total ) { + $total = 0; + } + + return array( + self::RESULT_IDS => $found_ids, + self::RESULT_TOTAL => $total, + ); + } + + /** + * Prepares the search result for a given ID. + * + * @param int $id Item ID. + * @param array $fields Fields to include for the item. + * @return array Associative array containing all fields for the item. + */ + public function prepare_item( $id, array $fields ) { + $term = get_term( $id ); + + $data = array(); + + if ( in_array( WP_REST_Search_Controller::PROP_ID, $fields, true ) ) { + $data[ WP_REST_Search_Controller::PROP_ID ] = (int) $id; + } + if ( in_array( WP_REST_Search_Controller::PROP_TITLE, $fields, true ) ) { + $data[ WP_REST_Search_Controller::PROP_TITLE ] = $term->name; + } + if ( in_array( WP_REST_Search_Controller::PROP_URL, $fields, true ) ) { + $data[ WP_REST_Search_Controller::PROP_URL ] = get_term_link( $id ); + } + if ( in_array( WP_REST_Search_Controller::PROP_TYPE, $fields, true ) ) { + $data[ WP_REST_Search_Controller::PROP_TYPE ] = $term->taxonomy; + } + + return $data; + } + + /** + * Prepares links for the search result of a given ID. + * + * @param int $id Item ID. + * @return array Links for the given item. + */ + public function prepare_item_links( $id ) { + $term = get_term( $id ); + + $links = array(); + + $item_route = rest_get_route_for_term( $term ); + if ( $item_route ) { + $links['self'] = array( + 'href' => rest_url( $item_route ), + 'embeddable' => true, + ); + } + + $links['about'] = array( + 'href' => rest_url( sprintf( 'wp/v2/taxonomies/%s', $term->taxonomy ) ), + ); + + return $links; + } +} diff --git a/lib/load.php b/lib/load.php index cf62c6ec05008a..f6d3156950f388 100644 --- a/lib/load.php +++ b/lib/load.php @@ -61,6 +61,12 @@ function gutenberg_is_experiment_enabled( $name ) { if ( ! class_exists( 'WP_REST_Plugins_Controller' ) ) { require_once dirname( __FILE__ ) . '/class-wp-rest-plugins-controller.php'; } + if ( ! class_exists( 'WP_REST_Post_Format_Search_Handler' ) ) { + require_once dirname( __FILE__ ) . '/class-wp-rest-post-format-search-handler.php'; + } + if ( ! class_exists( 'WP_REST_Term_Search_Handler' ) ) { + require_once dirname( __FILE__ ) . '/class-wp-rest-term-search-handler.php'; + } /** * End: Include for phase 2 */ diff --git a/lib/rest-api.php b/lib/rest-api.php index e8f3a2bc7827d8..7142cfffceb384 100644 --- a/lib/rest-api.php +++ b/lib/rest-api.php @@ -330,3 +330,32 @@ function gutenberg_register_image_editor() { } } add_filter( 'rest_api_init', 'gutenberg_register_image_editor' ); + +/** + * Registers the post format search handler. + * + * @param string $search_handlers Title list of current handlers. + * + * @return array Title updated list of handlers. + */ +function gutenberg_post_format_search_handler( $search_handlers ) { + if ( current_theme_supports( 'post-formats' ) ) { + $search_handlers[] = new WP_REST_Post_Format_Search_Handler(); + } + + return $search_handlers; +} +add_filter( 'wp_rest_search_handlers', 'gutenberg_post_format_search_handler', 10, 5 ); + +/** + * Registers the terms search handler. + * + * @param string $search_handlers Title list of current handlers. + * + * @return array Title updated list of handlers. + */ +function gutenberg_term_search_handler( $search_handlers ) { + $search_handlers[] = new WP_REST_Term_Search_Handler(); + return $search_handlers; +} +add_filter( 'wp_rest_search_handlers', 'gutenberg_term_search_handler', 10, 5 ); diff --git a/packages/edit-navigation/src/index.js b/packages/edit-navigation/src/index.js index f634f05e70552d..55ffe57d9d5159 100644 --- a/packages/edit-navigation/src/index.js +++ b/packages/edit-navigation/src/index.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { map, set } from 'lodash'; +import { map, set, flatten, partialRight } from 'lodash'; /** * WordPress dependencies @@ -39,12 +39,19 @@ function disableInsertingNonNavigationBlocks( settings, name ) { * It seems like there is no suitable package to import this from. Ideally it would be either part of core-data. * Until we refactor it, just copying the code is the simplest solution. * - * @param {Object} search - * @param {number} perPage + * @param {string} search + * @param {Object} [searchArguments] + * @param {number} [searchArguments.perPage=20] + * @param {Object} [editorSettings] + * @param {boolean} [editorSettings.disablePostFormats=false] * @return {Promise} List of suggestions */ -async function fetchLinkSuggestions( search, { perPage = 20 } = {} ) { - const posts = await apiFetch( { +const fetchLinkSuggestions = ( + search, + { perPage = 20 } = {}, + { disablePostFormats = false } = {} +) => { + const posts = apiFetch( { path: addQueryArgs( '/wp/v2/search', { search, per_page: perPage, @@ -52,13 +59,36 @@ async function fetchLinkSuggestions( search, { perPage = 20 } = {} ) { } ), } ); - return map( posts, ( post ) => ( { - id: post.id, - url: post.url, - title: decodeEntities( post.title ) || __( '(no title)' ), - type: post.subtype || post.type, - } ) ); -} + const terms = apiFetch( { + path: addQueryArgs( '/wp/v2/search', { + search, + per_page: perPage, + type: 'term', + } ), + } ); + + let formats; + if ( disablePostFormats ) { + formats = Promise.resolve( [] ); + } else { + formats = apiFetch( { + path: addQueryArgs( '/wp/v2/search', { + search, + per_page: perPage, + type: 'post-format', + } ), + } ); + } + + return Promise.all( [ posts, terms, formats ] ).then( ( results ) => { + return map( flatten( results ).slice( 0, perPage ), ( result ) => ( { + id: result.id, + url: result.url, + title: decodeEntities( result.title ) || __( '(no title)' ), + type: result.subtype || result.type, + } ) ); + } ); +}; export function initialize( id, settings ) { if ( ! settings.blockNavMenus ) { @@ -75,7 +105,10 @@ export function initialize( id, settings ) { __experimentalRegisterExperimentalCoreBlocks( settings ); } - settings.__experimentalFetchLinkSuggestions = fetchLinkSuggestions; + settings.__experimentalFetchLinkSuggestions = partialRight( + fetchLinkSuggestions, + settings + ); render( , diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index 99b1495152eccf..a0b8b9b4562860 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { map, pick, defaultTo } from 'lodash'; +import { map, pick, defaultTo, flatten, partialRight } from 'lodash'; import memize from 'memize'; /** @@ -37,12 +37,19 @@ import ConvertToGroupButtons from '../convert-to-group-buttons'; * It seems like there is no suitable package to import this from. Ideally it would be either part of core-data. * Until we refactor it, just copying the code is the simplest solution. * - * @param {Object} search - * @param {number} perPage + * @param {string} search + * @param {Object} [searchArguments] + * @param {number} [searchArguments.perPage=20] + * @param {Object} [editorSettings] + * @param {boolean} [editorSettings.disablePostFormats=false] * @return {Promise} List of suggestions */ -const fetchLinkSuggestions = async ( search, { perPage = 20 } = {} ) => { - const posts = await apiFetch( { +const fetchLinkSuggestions = ( + search, + { perPage = 20 } = {}, + { disablePostFormats = false } = {} +) => { + const posts = apiFetch( { path: addQueryArgs( '/wp/v2/search', { search, per_page: perPage, @@ -50,12 +57,35 @@ const fetchLinkSuggestions = async ( search, { perPage = 20 } = {} ) => { } ), } ); - return map( posts, ( post ) => ( { - id: post.id, - url: post.url, - title: decodeEntities( post.title ) || __( '(no title)' ), - type: post.subtype || post.type, - } ) ); + const terms = apiFetch( { + path: addQueryArgs( '/wp/v2/search', { + search, + per_page: perPage, + type: 'term', + } ), + } ); + + let formats; + if ( disablePostFormats ) { + formats = Promise.resolve( [] ); + } else { + formats = apiFetch( { + path: addQueryArgs( '/wp/v2/search', { + search, + per_page: perPage, + type: 'post-format', + } ), + } ); + } + + return Promise.all( [ posts, terms, formats ] ).then( ( results ) => { + return map( flatten( results ).slice( 0, perPage ), ( result ) => ( { + id: result.id, + url: result.url, + title: decodeEntities( result.title ) || __( '(no title)' ), + type: result.subtype || result.type, + } ) ); + } ); }; class EditorProvider extends Component { @@ -155,7 +185,10 @@ class EditorProvider extends Component { mediaUpload: hasUploadPermissions ? mediaUpload : undefined, __experimentalReusableBlocks: reusableBlocks, __experimentalFetchReusableBlocks, - __experimentalFetchLinkSuggestions: fetchLinkSuggestions, + __experimentalFetchLinkSuggestions: partialRight( + fetchLinkSuggestions, + settings + ), __experimentalCanUserUseUnfilteredHTML: canUserUseUnfilteredHTML, __experimentalUndo: undo, __experimentalShouldInsertAtTheTop: shouldInsertAtTheTop, diff --git a/phpunit/class-wp-rest-post-format-search-handler-test.php b/phpunit/class-wp-rest-post-format-search-handler-test.php new file mode 100644 index 00000000000000..4c9837b9026213 --- /dev/null +++ b/phpunit/class-wp-rest-post-format-search-handler-test.php @@ -0,0 +1,158 @@ +post->create( + array( + 'post_title' => 'Test post', + ) + ); + + set_post_format( self::$my_post_id, 'aside' ); + } + + /** + * Delete our fake data after our tests run. + */ + public static function wpTearDownAfterClass() { + wp_delete_post( self::$my_post_id ); + + remove_theme_support( 'post-formats' ); + } + + /** + * Search through terms of any type. + */ + public function test_get_items_search_type_post_format() { + $response = $this->do_request_with_params( + array( + 'per_page' => 100, + 'type' => 'post-format', + ) + ); + $this->assertEquals( 200, $response->get_status() ); + $this->assertContains( + 'Aside', + wp_list_pluck( $response->get_data(), 'title' ) + ); + } + + /** + * Search through all that matches a 'Aside' search. + */ + public function test_get_items_search_for_test_post_format() { + $response = $this->do_request_with_params( + array( + 'per_page' => 100, + 'search' => 'Aside', + 'type' => 'post-format', + ) + ); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertContains( + 'Aside', + wp_list_pluck( $response->get_data(), 'title' ) + ); + } + + /** + * Searching for a post format that doesn't exist should return an empty + * result. + */ + public function test_get_items_search_for_missing_post_format() { + $response = $this->do_request_with_params( + array( + 'per_page' => 100, + 'search' => 'Doesn\'t exist', + 'type' => 'post-format', + ) + ); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertEmpty( $response->get_data() ); + } + + public function test_register_routes() { + $this->markTestSkipped( 'Covered by Search controller tests.' ); + } + + public function test_context_param() { + $this->markTestSkipped( 'Covered by Search controller tests.' ); + } + + public function test_get_items() { + $this->markTestSkipped( 'Covered by Search controller tests.' ); + } + + public function test_get_item() { + $this->markTestSkipped( 'Covered by Search controller tests.' ); + } + + public function test_create_item() { + $this->markTestSkipped( 'Covered by Search controller tests.' ); + } + + public function test_update_item() { + $this->markTestSkipped( 'Covered by Search controller tests.' ); + } + + public function test_delete_item() { + $this->markTestSkipped( 'Covered by Search controller tests.' ); + } + + public function test_prepare_item() { + $this->markTestSkipped( 'Covered by Search controller tests.' ); + } + + public function test_get_item_schema() { + $this->markTestSkipped( 'Covered by Search controller tests.' ); + } + + /** + * Perform a REST request to our search endpoint with given parameters. + */ + private function do_request_with_params( $params = array(), $method = 'GET' ) { + $request = $this->get_request( $params, $method ); + + return rest_get_server()->dispatch( $request ); + } + + /** + * Get a REST request object for given parameters. + */ + private function get_request( $params = array(), $method = 'GET' ) { + $request = new WP_REST_Request( $method, '/wp/v2/search' ); + + foreach ( $params as $param => $value ) { + $request->set_param( $param, $value ); + } + + return $request; + } +} diff --git a/phpunit/class-wp-rest-term-search-handler-test.php b/phpunit/class-wp-rest-term-search-handler-test.php new file mode 100644 index 00000000000000..a2c248fd8bfd85 --- /dev/null +++ b/phpunit/class-wp-rest-term-search-handler-test.php @@ -0,0 +1,263 @@ +term->create( + array( + 'taxonomy' => 'category', + 'name' => 'Test Category', + ) + ); + + self::$my_tag = $factory->term->create( + array( + 'taxonomy' => 'post_tag', + 'name' => 'Test Tag', + ) + ); + + } + + /** + * Delete our fake data after our tests run. + */ + public static function wpTearDownAfterClass() { + $term_ids = array( + self::$my_category, + self::$my_tag, + ); + + foreach ( $term_ids as $term_id ) { + wp_delete_term( $term_id, true ); + } + } + + + /** + * Search through terms of any type. + */ + public function test_get_items_search_type_term() { + $response = $this->do_request_with_params( + array( + 'per_page' => 100, + 'type' => 'term', + ) + ); + $this->assertEquals( 200, $response->get_status() ); + $this->assertEqualSets( + array( + 0 => 1, // That is the default category. + self::$my_category, + self::$my_tag, + ), + wp_list_pluck( $response->get_data(), 'id' ) + ); + } + + /** + * Search through terms of subtype 'category'. + */ + public function test_get_items_search_type_term_subtype_category() { + $response = $this->do_request_with_params( + array( + 'per_page' => 100, + 'type' => 'term', + 'subtype' => 'category', + ) + ); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertEqualSets( + array( + 0 => 1, // That is the default category. + self::$my_category, + ), + wp_list_pluck( $response->get_data(), 'id' ) + ); + } + + /** + * Search through posts of an invalid post type. + */ + public function test_get_items_search_term_subtype_invalid() { + $response = $this->do_request_with_params( + array( + 'per_page' => 100, + 'type' => 'term', + 'subtype' => 'invalid', + ) + ); + + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); + } + + /** + * Search through posts and pages. + */ + public function test_get_items_search_categories_and_tags() { + $response = $this->do_request_with_params( + array( + 'per_page' => 100, + 'type' => 'term', + 'subtype' => 'category,post_tag', + ) + ); + $this->assertEquals( 200, $response->get_status() ); + $this->assertEqualSets( + array( + 0 => 1, // This is the default category. + self::$my_category, + self::$my_tag, + ), + wp_list_pluck( $response->get_data(), 'id' ) + ); + } + + /** + * Search through all that matches a 'Test Category' search. + */ + public function test_get_items_search_for_testcategory() { + $response = $this->do_request_with_params( + array( + 'per_page' => 100, + 'search' => 'Test Category', + 'type' => 'term', + ) + ); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertEqualSets( + array( + self::$my_category, + ), + wp_list_pluck( $response->get_data(), 'id' ) + ); + } + + /** + * Search through all that matches a 'Test Tag' search. + */ + public function test_get_items_search_for_testtag() { + $response = $this->do_request_with_params( + array( + 'per_page' => 100, + 'search' => 'Test Tag', + 'type' => 'term', + ) + ); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertEqualSets( + array( + self::$my_tag, + ), + wp_list_pluck( $response->get_data(), 'id' ) + ); + } + + /** + * Searching for a term that doesn't exist should return an empty result. + */ + public function test_get_items_search_for_missing_term() { + $response = $this->do_request_with_params( + array( + 'per_page' => 100, + 'search' => 'Doesn\'t exist', + 'type' => 'term', + ) + ); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertEmpty( $response->get_data() ); + } + + public function test_register_routes() { + $this->markTestSkipped( 'Covered by Search controller tests.' ); + } + + public function test_context_param() { + $this->markTestSkipped( 'Covered by Search controller tests.' ); + } + + public function test_get_items() { + $this->markTestSkipped( 'Covered by Search controller tests.' ); + } + + public function test_get_item() { + $this->markTestSkipped( 'Covered by Search controller tests.' ); + } + + public function test_create_item() { + $this->markTestSkipped( 'Covered by Search controller tests.' ); + } + + public function test_update_item() { + $this->markTestSkipped( 'Covered by Search controller tests.' ); + } + + public function test_delete_item() { + $this->markTestSkipped( 'Covered by Search controller tests.' ); + } + + public function test_prepare_item() { + $this->markTestSkipped( 'Covered by Search controller tests.' ); + } + + public function test_get_item_schema() { + $this->markTestSkipped( 'Covered by Search controller tests.' ); + } + + /** + * Perform a REST request to our search endpoint with given parameters. + */ + private function do_request_with_params( $params = array(), $method = 'GET' ) { + $request = $this->get_request( $params, $method ); + + return rest_get_server()->dispatch( $request ); + } + + /** + * Get a REST request object for given parameters. + */ + private function get_request( $params = array(), $method = 'GET' ) { + $request = new WP_REST_Request( $method, '/wp/v2/search' ); + + foreach ( $params as $param => $value ) { + $request->set_param( $param, $value ); + } + + return $request; + } + + +}