Make WordPress Core


Ignore:
Timestamp:
10/09/2025 05:21:12 AM (4 months ago)
Author:
ramonopoly
Message:

Attachments REST API endpoint: add support for filtering attachments by multiple media types

This patch enhances the REST API media endpoint to allow filtering by multiple values for the media_type and mime_type parameters. String, comma-separated values and array are supported.

Props abcd95, ramonopoly, andrewserong, mukesh27, adamsilverstein, timothyblynjacobs, swissspidy.

Fixes #63668.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/rest-api/rest-attachments-controller.php

    r60916 r60917  
    3939
    4040    /**
     41     * @var string The path to the test video.
     42     */
     43    private static $test_video_file;
     44
     45    /**
     46     * @var string The path to the test audio.
     47     */
     48    private static $test_audio_file;
     49
     50    /**
     51     * @var string The path to the test RTF file.
     52     */
     53    private static $test_rtf_file;
     54
     55    /**
    4156     * @var array The recorded posts query clauses.
    4257     */
     
    86101            unlink( self::$test_avif_file );
    87102        }
     103        if ( file_exists( self::$test_video_file ) ) {
     104            unlink( self::$test_video_file );
     105        }
     106        if ( file_exists( self::$test_audio_file ) ) {
     107            unlink( self::$test_audio_file );
     108        }
     109        if ( file_exists( self::$test_rtf_file ) ) {
     110            unlink( self::$test_rtf_file );
     111        }
    88112
    89113        self::delete_user( self::$editor_id );
     
    125149        if ( ! file_exists( self::$test_svg_file ) ) {
    126150            copy( $test_svg_file, self::$test_svg_file );
     151        }
     152
     153        $test_video_file       = DIR_TESTDATA . '/uploads/small-video.mp4';
     154        self::$test_video_file = get_temp_dir() . 'small-video.mp4';
     155        if ( ! file_exists( self::$test_video_file ) ) {
     156            copy( $test_video_file, self::$test_video_file );
     157        }
     158
     159        $test_audio_file       = DIR_TESTDATA . '/uploads/small-audio.mp3';
     160        self::$test_audio_file = get_temp_dir() . 'small-audio.mp3';
     161        if ( ! file_exists( self::$test_audio_file ) ) {
     162            copy( $test_audio_file, self::$test_audio_file );
     163        }
     164
     165        $test_rtf_file       = DIR_TESTDATA . '/uploads/test.rtf';
     166        self::$test_rtf_file = get_temp_dir() . 'test.rtf';
     167        if ( ! file_exists( self::$test_rtf_file ) ) {
     168            copy( $test_rtf_file, self::$test_rtf_file );
    127169        }
    128170
     
    268310            'text',
    269311        );
    270         $this->assertSameSets( $media_types, $data['endpoints'][0]['args']['media_type']['enum'] );
     312        $this->assertSameSets( $media_types, $data['endpoints'][0]['args']['media_type']['items']['enum'] );
    271313    }
    272314
     
    417459        $data     = $response->get_data();
    418460        $this->assertSame( $id1, $data[0]['id'] );
     461    }
     462
     463    /**
     464     * Test multiple media types support with various input formats.
     465     *
     466     * @ticket 63668
     467     */
     468    public function test_get_items_multiple_media_types() {
     469        $image_id = self::factory()->attachment->create_object(
     470            self::$test_file,
     471            0,
     472            array(
     473                'post_mime_type' => 'image/jpeg',
     474            )
     475        );
     476
     477        $video_id = self::factory()->attachment->create_object(
     478            self::$test_video_file,
     479            0,
     480            array(
     481                'post_mime_type' => 'video/mp4',
     482            )
     483        );
     484
     485        $audio_id = self::factory()->attachment->create_object(
     486            self::$test_audio_file,
     487            0,
     488            array(
     489                'post_mime_type' => 'audio/mpeg',
     490            )
     491        );
     492
     493        $request = new WP_REST_Request( 'GET', '/wp/v2/media' );
     494
     495        // Test single media type.
     496        $request->set_param( 'media_type', 'image' );
     497        $response = rest_get_server()->dispatch( $request );
     498        $data     = $response->get_data();
     499        $this->assertCount( 1, $data, 'Response count for single media type is not 1' );
     500        $this->assertSame( $image_id, $data[0]['id'], 'Image ID not found in response for single media type' );
     501
     502        // Test multiple media types with comma-separated string.
     503        $request->set_param( 'media_type', 'image,video' );
     504        $response = rest_get_server()->dispatch( $request );
     505        $data     = $response->get_data();
     506        $this->assertCount( 2, $data, 'Response count for multiple media types with comma-separated string is not 2' );
     507        $ids = wp_list_pluck( $data, 'id' );
     508        $this->assertContains( $image_id, $ids, 'Image ID not found in response for multiple media types with comma-separated string' );
     509        $this->assertContains( $video_id, $ids, 'Video ID not found in response for multiple media types with comma-separated string' );
     510        $this->assertNotContains( $audio_id, $ids, 'Audio ID found in response for multiple media types with comma-separated string' );
     511
     512        // Test multiple media types with array format.
     513        $request->set_param( 'media_type', array( 'image', 'video', 'audio' ) );
     514        $response = rest_get_server()->dispatch( $request );
     515        $data     = $response->get_data();
     516        $this->assertCount( 3, $data, 'Response count for multiple media types with array format is not 3' );
     517        $ids = wp_list_pluck( $data, 'id' );
     518        $this->assertContains( $image_id, $ids, 'Image ID not found in response for multiple media types with array format' );
     519        $this->assertContains( $video_id, $ids, 'Video ID not found in response for multiple media types with array format' );
     520        $this->assertContains( $audio_id, $ids, 'Audio ID not found in response for multiple media types with array format' );
     521
     522        // Test invalid media type mixed with valid ones.
     523        $request->set_param( 'media_type', 'image,invalid,video' );
     524        $response = rest_get_server()->dispatch( $request );
     525        $this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
     526    }
     527
     528    /**
     529     * Test multiple MIME types support and combination with media types.
     530     *
     531     * @ticket 63668
     532     */
     533    public function test_get_items_multiple_mime_types_and_combination() {
     534        $jpeg_id = self::factory()->attachment->create_object(
     535            self::$test_file,
     536            0,
     537            array(
     538                'post_mime_type' => 'image/jpeg',
     539            )
     540        );
     541
     542        $png_id = self::factory()->attachment->create_object(
     543            self::$test_file2,
     544            0,
     545            array(
     546                'post_mime_type' => 'image/png',
     547            )
     548        );
     549
     550        $mp4_id = self::factory()->attachment->create_object(
     551            self::$test_video_file,
     552            0,
     553            array(
     554                'post_mime_type' => 'video/mp4',
     555            )
     556        );
     557
     558        $request = new WP_REST_Request( 'GET', '/wp/v2/media' );
     559
     560        // Test single MIME type
     561        $request->set_param( 'mime_type', 'image/jpeg' );
     562        $response = rest_get_server()->dispatch( $request );
     563        $data     = $response->get_data();
     564        $this->assertCount( 1, $data, 'Response count for single MIME type is not 1' );
     565        $this->assertSame( $jpeg_id, $data[0]['id'], 'JPEG ID not found in response for single MIME type' );
     566
     567        // Test multiple MIME types with comma-separated string.
     568        $request->set_param( 'mime_type', 'image/jpeg,image/png' );
     569        $response = rest_get_server()->dispatch( $request );
     570        $data     = $response->get_data();
     571        $this->assertCount( 2, $data, 'Response count for multiple MIME types with comma-separated string is not 2' );
     572        $ids = wp_list_pluck( $data, 'id' );
     573        $this->assertContains( $jpeg_id, $ids, 'JPEG ID not found in response for multiple MIME types with comma-separated string' );
     574        $this->assertContains( $png_id, $ids, 'PNG ID not found in response for multiple MIME types with comma-separated string' );
     575
     576        // Test multiple MIME types with array format.
     577        $request->set_param( 'mime_type', array( 'image/jpeg', 'video/mp4' ) );
     578        $response = rest_get_server()->dispatch( $request );
     579        $data     = $response->get_data();
     580        $this->assertCount( 2, $data, 'Response count for multiple MIME types with array format is not 2' );
     581        $ids = wp_list_pluck( $data, 'id' );
     582
     583        $this->assertContains( $jpeg_id, $ids, 'JPEG ID not found in response for multiple MIME types with array format' );
     584        $this->assertContains( $mp4_id, $ids, 'MP4 ID not found in response for multiple MIME types with array format' );
     585    }
     586
     587    /**
     588     * Test combination of media type and mime type parameters.
     589     *
     590     * @ticket 63668
     591     */
     592    public function test_get_items_with_media_type_and_media_types() {
     593        $audio_id = self::factory()->attachment->create_object(
     594            self::$test_audio_file,
     595            0,
     596            array(
     597                'post_mime_type' => 'audio/mpeg',
     598                'post_excerpt'   => 'A sample caption',
     599            )
     600        );
     601
     602        $jpeg_id = self::factory()->attachment->create_object(
     603            self::$test_file,
     604            0,
     605            array(
     606                'post_mime_type' => 'image/jpeg',
     607                'post_excerpt'   => 'A sample caption',
     608            )
     609        );
     610
     611        $png_id = self::factory()->attachment->create_object(
     612            self::$test_file2,
     613            0,
     614            array(
     615                'post_mime_type' => 'image/png',
     616            )
     617        );
     618
     619        $video_id = self::factory()->attachment->create_object(
     620            self::$test_video_file,
     621            0,
     622            array(
     623                'post_mime_type' => 'video/mp4',
     624            )
     625        );
     626
     627        $rtf_id = self::factory()->attachment->create_object(
     628            self::$test_rtf_file,
     629            0,
     630            array(
     631                'post_mime_type' => 'application/rtf',
     632            )
     633        );
     634
     635        // Test combination of single media type and single mime type parameters.
     636        $request = new WP_REST_Request( 'GET', '/wp/v2/media' );
     637        $request->set_param( 'media_type', 'image' );
     638        $request->set_param( 'mime_type', 'audio/mpeg' );
     639        $response = rest_get_server()->dispatch( $request );
     640        $data     = $response->get_data();
     641        $ids      = wp_list_pluck( $data, 'id' );
     642
     643        $this->assertCount( 3, $data, 'Response count for combination of single media type and single mime type parameters is not 3' );
     644        $this->assertContains( $jpeg_id, $ids, 'JPEG ID not found in response' );
     645        $this->assertContains( $png_id, $ids, 'PNG ID not found in response' );
     646        $this->assertContains( $audio_id, $ids, 'Audio ID found in response' );
     647
     648        // Test combination of single media type and multiple mime type parameters.
     649        $request = new WP_REST_Request( 'GET', '/wp/v2/media' );
     650        $request->set_param( 'media_type', 'audio' );
     651        $request->set_param( 'mime_type', array( 'image/jpeg', 'image/png' ) );
     652        $response = rest_get_server()->dispatch( $request );
     653        $data     = $response->get_data();
     654        $ids      = wp_list_pluck( $data, 'id' );
     655
     656        $this->assertCount( 3, $data, 'Response count for combination of single media type and multiple mime type parameters is not 3' );
     657        $this->assertContains( $audio_id, $ids, 'Audio ID not found in response' );
     658        $this->assertContains( $jpeg_id, $ids, 'JPEG ID not found in response' );
     659        $this->assertContains( $png_id, $ids, 'PNG ID not found in response' );
     660
     661        // Test combination of multiple media types and single mime type parameters.
     662        $request = new WP_REST_Request( 'GET', '/wp/v2/media' );
     663        $request->set_param( 'media_type', 'audio,video' );
     664        $request->set_param( 'mime_type', array( 'image/jpeg' ) );
     665        $response = rest_get_server()->dispatch( $request );
     666        $data     = $response->get_data();
     667        $ids      = wp_list_pluck( $data, 'id' );
     668
     669        $this->assertCount( 3, $data, 'Response count for combination of multiple media type and multiple mime type parameters is not 3' );
     670        $this->assertContains( $audio_id, $ids, 'Audio ID not found in response' );
     671        $this->assertContains( $jpeg_id, $ids, 'JPEG ID not found in response' );
     672        $this->assertContains( $video_id, $ids, 'Video ID not found in response' );
     673
     674        // Test combination of multiple media types and multiple mime type parameters.
     675        $request = new WP_REST_Request( 'GET', '/wp/v2/media' );
     676        $request->set_param( 'media_type', 'audio,video' );
     677        $request->set_param( 'mime_type', array( 'image/jpeg', 'image/png', 'application/rtf' ) );
     678        $response = rest_get_server()->dispatch( $request );
     679        $data     = $response->get_data();
     680        $ids      = wp_list_pluck( $data, 'id' );
     681
     682        $this->assertCount( 5, $data, 'Response count for combination of multiple media type and multiple mime type parameters is not 3' );
     683        $this->assertContains( $audio_id, $ids, 'Audio ID not found in response' );
     684        $this->assertContains( $jpeg_id, $ids, 'JPEG ID not found in response' );
     685        $this->assertContains( $video_id, $ids, 'Video ID not found in response' );
     686        $this->assertContains( $png_id, $ids, 'PNG ID not found in response' );
     687        $this->assertContains( $rtf_id, $ids, 'RTF ID not found in response' );
    419688    }
    420689
     
    26862955    /**
    26872956     * Tests that the attachment fields caption, description, and title, post and alt_text are updated correctly.
     2957     *
    26882958     * @ticket 64035
    26892959     * @requires function imagejpeg
Note: See TracChangeset for help on using the changeset viewer.