Make WordPress Core


Ignore:
Timestamp:
10/09/2025 05:21:12 AM (11 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.