Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/wp-includes/rest-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ function create_initial_rest_routes() {
new WP_REST_Post_Search_Handler(),
new WP_REST_Term_Search_Handler(),
new WP_REST_Post_Format_Search_Handler(),
new WP_REST_Media_Search_Handler(),
);

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ class WP_REST_Search_Controller extends WP_REST_Controller {
*/
const PROP_SUBTYPE = 'subtype';

/**
* Label property name.
*/
const PROP_LABEL = 'label';

/**
* Identifier for the 'any' type.
*/
Expand Down Expand Up @@ -283,6 +288,12 @@ public function get_item_schema() {
'context' => array( 'view', 'embed' ),
'readonly' => true,
),
self::PROP_LABEL => array(
'description' => __( 'Object human readable subtype.' ),
'type' => 'string',
'context' => array( 'view', 'embed' ),
'readonly' => true,
),
),
);

Expand Down
109 changes: 109 additions & 0 deletions src/wp-includes/rest-api/search/class-wp-rest-media-search-handler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<?php
/**
* REST API: WP_REST_Media_Search_Handler class
*
* @package WordPress
* @subpackage REST_API
* @since 6.6.0
*/

/**
* Core class representing a search handler for attachments in the REST API.
*
* @since 6.6.0
*
* @see WP_REST_Search_Handler
*/
class WP_REST_Media_Search_Handler extends WP_REST_Post_Search_Handler {

/**
* Constructor.
*
* @since 6.6.0
*/
public function __construct() {
parent::__construct();
$this->type = 'media';
$this->subtypes = array();
}

/**
* 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.
* @since 6.6.0
*
*/
public function search_items( WP_REST_Request $request ) {

$query_args = array(
'post_type' => 'attachment',
'post_status' => 'inherit',
'paged' => (int) $request['page'],
'posts_per_page' => (int) $request['per_page'],
);

if ( ! empty( $request['search'] ) ) {
$query_args['s'] = $request['search'];

// Filter query clauses to include filenames.
add_filter( 'wp_allow_query_attachment_by_filename', '__return_true' );
}

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.
*
* Enables adding extra arguments or setting defaults for a media search request.
*
* @param array $query_args Key value array of query var to query value.
* @param WP_REST_Request $request The request used.
*
* @since 6.6.0
*
*/
$query_args = apply_filters( 'rest_media_search_query', $query_args, $request );

$query = new WP_Query();
$posts = $query->query( $query_args );
// Querying the whole post object will warm the object cache, avoiding an extra query per result.
$found_ids = wp_list_pluck( $posts, 'ID' );
$total = $query->found_posts;

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.
* @since 6.6.0
*
*/
public function prepare_item( $id, array $fields ) {
$data = parent::prepare_item( $id, $fields );

if ( isset( $data[ WP_REST_Search_Controller::PROP_SUBTYPE ] ) ) {
unset( $data[ WP_REST_Search_Controller::PROP_SUBTYPE ] );
}

return $data;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ public function prepare_item( $id, array $fields ) {
$data[ WP_REST_Search_Controller::PROP_TYPE ] = $this->type;
}

if ( in_array( WP_REST_Search_Controller::PROP_LABEL, $fields, true ) ) {
$data[ WP_REST_Search_Controller::PROP_LABEL ] = get_post_format_string( $id );
}

return $data;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,12 @@ public function prepare_item( $id, array $fields ) {
$data[ WP_REST_Search_Controller::PROP_SUBTYPE ] = $post->post_type;
}

if ( in_array( WP_REST_Search_Controller::PROP_LABEL, $fields, true ) ) {
$ptype = get_post_type_object( $post->post_type );
$label = $ptype ? $ptype->labels->singular_name : $post->post_type;
$data[ WP_REST_Search_Controller::PROP_LABEL ] = $label;
}

return $data;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,12 @@ public function prepare_item( $id, array $fields ) {
$data[ WP_REST_Search_Controller::PROP_TYPE ] = $term->taxonomy;
}

if ( in_array( WP_REST_Search_Controller::PROP_LABEL, $fields, true ) ) {
$taxonomy = get_taxonomy( $term->taxonomy );
$label = $taxonomy ? $taxonomy->labels->singular_name : $term->taxonomy;
$data[ WP_REST_Search_Controller::PROP_LABEL ] = $label;
}

return $data;
}

Expand Down
1 change: 1 addition & 0 deletions src/wp-settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@
require ABSPATH . WPINC . '/rest-api/search/class-wp-rest-post-search-handler.php';
require ABSPATH . WPINC . '/rest-api/search/class-wp-rest-term-search-handler.php';
require ABSPATH . WPINC . '/rest-api/search/class-wp-rest-post-format-search-handler.php';
require ABSPATH . WPINC . '/rest-api/search/class-wp-rest-media-search-handler.php';
require ABSPATH . WPINC . '/sitemaps.php';
require ABSPATH . WPINC . '/sitemaps/class-wp-sitemaps.php';
require ABSPATH . WPINC . '/sitemaps/class-wp-sitemaps-index.php';
Expand Down
19 changes: 17 additions & 2 deletions tests/phpunit/includes/class-wp-rest-test-search-handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,28 @@ class WP_REST_Test_Search_Handler extends WP_REST_Search_Handler {
public function __construct( $amount = 10 ) {
$this->type = 'test';

$this->subtypes = array( 'test_first_type', 'test_second_type' );
$this->subtypes = array( 'test_first_type', 'test_second_type' );
$test_first_type_object = new \WP_Post_Type(
'test_first_type',
array(
'labels' => array(
'name' => 'Test first types',
'singular_name' => 'Test first type',
),
)
);

$this->items = array();
for ( $i = 1; $i <= $amount; $i++ ) {
$subtype = $i > $amount / 2 ? 'test_second_type' : 'test_first_type';
$subtype = $i > $amount / 2 ? 'test_second_type' : 'test_first_type';
$subtype_object = $i > $amount / 2 ? false : $test_first_type_object;

$this->items[ $i ] = (object) array(
'test_id' => $i,
'test_title' => sprintf( 'Title %d', $i ),
'test_url' => sprintf( home_url( '/tests/%d' ), $i ),
'test_type' => $subtype,
'test_label' => $subtype_object ? $subtype_object->labels->singular_name : $subtype,
);
}
}
Expand Down Expand Up @@ -82,6 +93,10 @@ public function prepare_item( $id, array $fields ) {
$data[ WP_REST_Search_Controller::PROP_SUBTYPE ] = $test->test_type;
}

if ( in_array( WP_REST_Search_Controller::PROP_LABEL, $fields, true ) ) {
$data[ WP_REST_Search_Controller::PROP_LABEL ] = $test->test_label;
}

return $data;
}

Expand Down
82 changes: 82 additions & 0 deletions tests/phpunit/tests/rest-api/rest-search-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ class WP_Test_REST_Search_Controller extends WP_Test_REST_Controller_Testcase {
*/
private static $my_content_post_ids = array();

/**
* Attachments
*
* @var array
*/
private static $my_attachment_ids;

/**
* Categories.
*
Expand Down Expand Up @@ -90,6 +97,13 @@ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
'name' => 'Test Tag',
)
);

self::$my_attachment_ids = $factory->attachment->create_many(
4,
array(
'post_title' => 'my-footitle',
)
);
}

/**
Expand Down Expand Up @@ -413,6 +427,7 @@ public function test_prepare_item() {
'url',
'type',
'subtype',
'label',
'_links',
),
array_keys( $data[0] )
Expand Down Expand Up @@ -458,6 +473,7 @@ public function test_get_item_schema() {
$this->assertArrayHasKey( 'url', $properties );
$this->assertArrayHasKey( 'type', $properties );
$this->assertArrayHasKey( 'subtype', $properties );
$this->assertArrayHasKey( 'label', $properties );
}

/**
Expand Down Expand Up @@ -523,6 +539,7 @@ public function test_custom_search_handler_prepare_item() {
'url',
'type',
'subtype',
'label',
),
array_keys( $data )
);
Expand Down Expand Up @@ -902,4 +919,69 @@ public function test_sanitize_subtypes_validates_type() {

$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
}

/**
* Search through attachments.
*
* @ticket 61254
*/
public function test_get_items_search_type_media() {
$response = $this->do_request_with_params(
array(
'per_page' => 100,
'type' => 'media',
)
);
$this->assertSame( 200, $response->get_status() );
$this->assertSameSets(
self::$my_attachment_ids,
wp_list_pluck( $response->get_data(), 'id' )
);
}

/**
* @ticket 61254
*/
public function test_label_field_contain_the_post_type_singular_name() {
$response = $this->do_request_with_params(
array(
'subtype' => 'page',
'per_page' => 1,
)
);

$response_data = $response->get_data();
$this->assertSame( 'Page', $response_data[0]['label'] );
}

/**
* @ticket 61254
*/
public function test_label_field_contain_the_taxonomy_name() {
$response = $this->do_request_with_params(
array(
'type' => 'term',
'subtype' => 'category',
'per_page' => 1,
)
);

$response_data = $response->get_data();
$this->assertSame( 'Category', $response_data[0]['label'] );
}

/**
* @ticket 61254
*/
public function test_label_field_contain_the_post_format_name() {
$response = $this->do_request_with_params(
array(
'type' => 'post-format',
'per_page' => 1,
)
);

$response_data = $response->get_data();
$this->assertSame( 'Aside', $response_data[0]['label'] );
}
}
3 changes: 2 additions & 1 deletion tests/qunit/fixtures/wp-api-generated.js
Original file line number Diff line number Diff line change
Expand Up @@ -10202,7 +10202,8 @@ mockedApiResponse.Schema = {
"enum": [
"post",
"term",
"post-format"
"post-format",
"media"
],
"required": false
},
Expand Down