From a6659195dcc8fc5f4f43be76e81143c78a83c13d Mon Sep 17 00:00:00 2001 From: adamsilverstein Date: Wed, 15 Jul 2026 19:47:06 -0700 Subject: [PATCH 1/2] Media REST API: Fix sideload and finalize for EXIF rotated images Treat an image_size=original sideload like a scaled sideload: the supplied file (the client-rotated original) replaces the attachment's main file and the untouched upload is kept as original_image. This is the same swap _wp_image_meta_replace_original() performs when the server rotates an image on upload. Accept transposed dimensions when validating an original sideload, since quarter-turn EXIF orientations (5-8) swap width and height; previously these uploads failed with rest_upload_dimension_mismatch. Reset the stored EXIF orientation to 1 in finalize for both original and scaled sub-sizes, as wp_create_image_subsizes() does, so exif_orientation no longer reports the pre-rotation value after the rotation has been applied. Skip original/scaled finalize entries missing the file name so a malformed payload cannot blank out the main file metadata. --- .../class-wp-rest-attachments-controller.php | 76 +++-- .../rest-api/rest-attachments-controller.php | 317 +++++++++++++++++- 2 files changed, 364 insertions(+), 29 deletions(-) diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php index a3f68154c18cd..4737ee747a52b 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php @@ -2413,14 +2413,23 @@ private function validate_image_dimensions( int $width, int $height, string $ima ); } - // 'original' size: should match original attachment dimensions. + /* + * 'original' size: the full-size image that replaces the main file (see + * sideload_item()/finalize_item()). The endpoint expects any EXIF + * orientation to be applied to the image already, which can swap width + * and height, so the dimensions must match the stored dimensions or be + * their transpose. + */ if ( 'original' === $image_size ) { $metadata = wp_get_attachment_metadata( $attachment_id, true ); if ( is_array( $metadata ) && isset( $metadata['width'], $metadata['height'] ) ) { $expected_width = (int) $metadata['width']; $expected_height = (int) $metadata['height']; - if ( $width !== $expected_width || $height !== $expected_height ) { + $matches_dimensions = $width === $expected_width && $height === $expected_height; + $transposes_dimensions = $width === $expected_height && $height === $expected_width; + + if ( ! $matches_dimensions && ! $transposes_dimensions ) { return new WP_Error( 'rest_upload_dimension_mismatch', sprintf( @@ -2665,8 +2674,6 @@ public function sideload_item( WP_REST_Request $request ) { $sub_size_data['file'] = wp_basename( $path ); $sub_size_data['mime_type'] = $type; $sub_size_data['filesize'] = wp_filesize( $path ); - } elseif ( 'original' === $image_size ) { - $sub_size_data['file'] = wp_basename( $path ); } elseif ( self::IMAGE_SIZE_SOURCE_ORIGINAL === $image_size ) { /* * Source-format original (e.g. the HEIC kept next to its JPEG @@ -2681,8 +2688,16 @@ public function sideload_item( WP_REST_Request $request ) { * finalize_item can store it under its dedicated meta key. */ $sub_size_data['file'] = wp_basename( $path ); - } elseif ( 'scaled' === $image_size ) { - // Record the current attached file as the original. + } elseif ( 'scaled' === $image_size || 'original' === $image_size ) { + /* + * 'scaled' and 'original' both replace the attachment's main file + * with the supplied image and keep the file being replaced as + * `original_image`, which is the untouched upload. A 'scaled' + * image is downsized and an 'original' image has any EXIF + * orientation already applied. This is the same swap WordPress + * makes when it scales or rotates an image on upload; see + * _wp_image_meta_replace_original(). + */ $current_file = get_attached_file( $attachment_id, true ); if ( ! $current_file ) { @@ -2695,19 +2710,19 @@ public function sideload_item( WP_REST_Request $request ) { $sub_size_data['original_image'] = wp_basename( $current_file ); - // Validate the scaled image before updating the attached file. + // Validate the supplied image before updating the attached file. $size = wp_getimagesize( $path ); $filesize = wp_filesize( $path ); if ( ! $size || ! $filesize ) { return new WP_Error( 'rest_sideload_invalid_image', - __( 'Unable to read the scaled image file.' ), + __( 'Unable to read the sideloaded image file.' ), array( 'status' => 500 ) ); } - // Update the attached file to point to the scaled version. + // Update the attached file to point to the supplied image. // This writes to _wp_attached_file meta, not _wp_attachment_metadata. if ( get_attached_file( $attachment_id, true ) !== $path && @@ -2834,8 +2849,39 @@ public function finalize_item( WP_REST_Request $request ) { continue; } - if ( 'original' === $image_size ) { - $metadata['original_image'] = $sub_size['file']; + if ( 'original' === $image_size || 'scaled' === $image_size ) { + // Skip malformed entries so a bad payload cannot blank out the + // main file metadata. + if ( empty( $sub_size['file'] ) ) { + continue; + } + + /* + * Record the supplied full-size image (from sideload_item()) as + * the main file, keeping the current attached file as + * `original_image`. A 'scaled' image is downsized and an + * 'original' image is rotated; both have any EXIF orientation + * already applied by the client. + */ + if ( ! empty( $sub_size['original_image'] ) ) { + $metadata['original_image'] = $sub_size['original_image']; + } + $metadata['width'] = $sub_size['width'] ?? 0; + $metadata['height'] = $sub_size['height'] ?? 0; + $metadata['filesize'] = $sub_size['filesize'] ?? 0; + $metadata['file'] = $sub_size['file']; + + /* + * The supplied image has its orientation applied already, so + * reset the stored value (from the upload) to 1, as + * wp_create_image_subsizes() does for both its scale and rotate + * paths. Otherwise exif_orientation would still report the + * pre-rotation value and the client would rotate the image + * again on a re-fetch. + */ + if ( ! empty( $metadata['image_meta']['orientation'] ) ) { + $metadata['image_meta']['orientation'] = 1; + } } elseif ( self::IMAGE_SIZE_SOURCE_ORIGINAL === $image_size ) { /* * Source-format original: stored under its own meta key so the @@ -2855,14 +2901,6 @@ public function finalize_item( WP_REST_Request $request ) { } elseif ( 'animated_video_poster' === $image_size ) { // Static first-frame poster for the converted video. $metadata['animated_video_poster'] = $sub_size['file']; - } elseif ( 'scaled' === $image_size ) { - if ( ! empty( $sub_size['original_image'] ) ) { - $metadata['original_image'] = $sub_size['original_image']; - } - $metadata['width'] = $sub_size['width'] ?? 0; - $metadata['height'] = $sub_size['height'] ?? 0; - $metadata['filesize'] = $sub_size['filesize'] ?? 0; - $metadata['file'] = $sub_size['file'] ?? ''; } else { $metadata['sizes'] = $metadata['sizes'] ?? array(); diff --git a/tests/phpunit/tests/rest-api/rest-attachments-controller.php b/tests/phpunit/tests/rest-api/rest-attachments-controller.php index 55859c085fdd9..d59bfe5c14966 100644 --- a/tests/phpunit/tests/rest-api/rest-attachments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-attachments-controller.php @@ -4333,10 +4333,14 @@ public function test_finalize_writes_regular_sub_sizes(): void { } /** - * Tests that the finalize endpoint records original_image from an - * 'original' sub-size collected from a sideload response. + * Tests that sideloading the 'original' size makes the supplied (rotated) + * file the attachment's main file and that finalize records the previous + * attached file as original_image, mirroring the swap + * _wp_image_meta_replace_original() performs when the server rotates an + * image on upload. * - * @ticket 65329 + * @ticket 64798 + * @covers WP_REST_Attachments_Controller::sideload_item * @covers WP_REST_Attachments_Controller::finalize_item * @requires function imagejpeg */ @@ -4356,8 +4360,11 @@ public function test_finalize_writes_original_metadata(): void { $this->assertSame( 201, $response->get_status() ); - // Sideload the 'original' version (simulating a rotated image), which - // returns the basename without writing metadata. + $attached_file_before = get_attached_file( $attachment_id, true ); + + // Sideload the 'original' version (simulating a rotated image). + // canola.jpg is 640x480, matching the stored dimensions, so + // validation passes. $request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment_id}/sideload" ); $request->set_header( 'Content-Type', 'image/jpeg' ); $request->set_header( 'Content-Disposition', 'attachment; filename=canola-original.jpg' ); @@ -4368,11 +4375,15 @@ public function test_finalize_writes_original_metadata(): void { $this->assertSame( 200, $response->get_status(), 'Sideloading the original should succeed.' ); $this->assertSame( 'original', $original_data['image_size'], 'Response should echo the image_size.' ); - $this->assertSame( 'canola-original.jpg', $original_data['file'], 'Response should return the file basename.' ); + $this->assertSame( wp_basename( $attached_file_before ), $original_data['original_image'], 'Response original_image should be the basename of the previous attached file.' ); + $this->assertSame( 640, $original_data['width'], 'Response width should be the sideloaded image width.' ); + $this->assertSame( 480, $original_data['height'], 'Response height should be the sideloaded image height.' ); + $this->assertGreaterThan( 0, $original_data['filesize'], 'Response filesize should be positive.' ); - // Sideload must not write metadata; that happens in finalize. - $metadata = wp_get_attachment_metadata( $attachment_id, true ); - $this->assertArrayNotHasKey( 'original_image', $metadata, 'Sideload should not write original_image metadata.' ); + // The attached file is repointed to the sideloaded original. + $attached_file_after = get_attached_file( $attachment_id, true ); + $this->assertSame( wp_basename( $original_data['file'] ), wp_basename( $attached_file_after ), 'Attached file should be the sideloaded original.' ); + $this->assertNotSame( $attached_file_before, $attached_file_after, 'Attached file should be replaced by the sideloaded original.' ); // Finalize with the collected original sub-size. $request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment_id}/finalize" ); @@ -4382,7 +4393,293 @@ public function test_finalize_writes_original_metadata(): void { $this->assertSame( 200, $response->get_status(), 'Finalize should succeed.' ); $metadata = wp_get_attachment_metadata( $attachment_id ); - $this->assertSame( 'canola-original.jpg', $metadata['original_image'], 'Finalize should record original_image from the sub-size.' ); + $this->assertSame( wp_basename( $attached_file_before ), $metadata['original_image'], 'Finalize should record the previous attached file as original_image.' ); + $this->assertSame( 640, $metadata['width'], 'Finalize should record the sideloaded image width.' ); + $this->assertSame( 480, $metadata['height'], 'Finalize should record the sideloaded image height.' ); + $this->assertSame( $original_data['file'], $metadata['file'], 'Finalize should record the sideloaded original as the main file.' ); + } + + /** + * Tests that sideloading the 'original' size accepts a rotated file whose + * dimensions are the transpose of the stored dimensions (EXIF orientations + * 5/6/7/8 swap width and height) and makes it the main file. + * + * A strict equality check would reject quarter-turn rotations with + * rest_upload_dimension_mismatch. + * + * @ticket 64798 + * @covers WP_REST_Attachments_Controller::sideload_item + * @covers WP_REST_Attachments_Controller::validate_image_dimensions + * @covers WP_REST_Attachments_Controller::finalize_item + * @requires function imagejpeg + */ + public function test_sideload_item_accepts_transposed_original_dimensions(): void { + if ( ! wp_image_editor_supports( array( 'methods' => array( 'rotate' ) ) ) ) { + $this->markTestSkipped( 'This test requires an image editor with rotation support.' ); + } + + $this->enable_client_side_media_processing(); + + wp_set_current_user( self::$author_id ); + + // Create a 640x480 attachment without generating sub-sizes server-side. + $request = new WP_REST_Request( 'POST', '/wp/v2/media' ); + $request->set_header( 'Content-Type', 'image/jpeg' ); + $request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' ); + $request->set_param( 'generate_sub_sizes', false ); + $request->set_body( (string) file_get_contents( self::$test_file ) ); + $response = rest_get_server()->dispatch( $request ); + $attachment_id = $response->get_data()['id']; + + $this->assertSame( 201, $response->get_status() ); + + $uploaded_basename = wp_basename( get_attached_file( $attachment_id, true ) ); + + // Build a rotated (transposed) version of the source: 640x480 -> 480x640. + $editor = wp_get_image_editor( self::$test_file ); + $this->assertNotWPError( $editor ); + $editor->rotate( 90 ); + $saved = $editor->save( wp_tempnam( 'rotated.jpg' ), 'image/jpeg' ); + $this->assertNotWPError( $saved ); + $rotated_path = $saved['path']; + + // Sideload the rotated file as the original. + $request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment_id}/sideload" ); + $request->set_header( 'Content-Type', 'image/jpeg' ); + $request->set_header( 'Content-Disposition', 'attachment; filename=canola-rotated.jpg' ); + $request->set_param( 'image_size', 'original' ); + $request->set_body( (string) file_get_contents( $rotated_path ) ); + $response = rest_get_server()->dispatch( $request ); + $original_data = $response->get_data(); + + unlink( $rotated_path ); + + // The transposed dimensions must be accepted, not rejected with a 400. + $this->assertSame( 200, $response->get_status(), 'Transposed original sideload should succeed.' ); + $this->assertSame( 480, $original_data['width'], 'Response width should be the transposed width.' ); + $this->assertSame( 640, $original_data['height'], 'Response height should be the transposed height.' ); + $this->assertSame( $uploaded_basename, $original_data['original_image'], 'Response original_image should be the basename of the uploaded file.' ); + + // Finalize and confirm the rotated dimensions replace the stored ones. + $request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment_id}/finalize" ); + $request->set_param( 'sub_sizes', array( $original_data ) ); + $response = rest_get_server()->dispatch( $request ); + $this->assertSame( 200, $response->get_status(), 'Finalize should succeed.' ); + + $metadata = wp_get_attachment_metadata( $attachment_id, true ); + $this->assertSame( 480, $metadata['width'], 'Finalize should record the transposed width.' ); + $this->assertSame( 640, $metadata['height'], 'Finalize should record the transposed height.' ); + $this->assertSame( $uploaded_basename, $metadata['original_image'], 'Finalize should keep the uploaded file as original_image.' ); + $this->assertSame( $original_data['file'], $metadata['file'], 'Finalize should record the rotated file as the main file.' ); + } + + /** + * Tests that the client-side 'original' sideload of an EXIF-rotated image + * produces the same attachment metadata as a normal server-side upload of + * the same file. + * + * Uses test-image-rotated-90ccw.jpg (1200x1800, EXIF orientation 6), a + * quarter turn that swaps width and height to 1800x1200. The browser + * rotates and strips the EXIF orientation; wp_get_image_editor() does the + * same here, so no JavaScript is required. + * + * @ticket 64798 + * @covers WP_REST_Attachments_Controller::sideload_item + * @covers WP_REST_Attachments_Controller::finalize_item + * @covers WP_REST_Attachments_Controller::validate_image_dimensions + * @requires function imagejpeg + * @requires extension exif + */ + public function test_original_sideload_matches_server_side_rotation(): void { + if ( ! wp_image_editor_supports( array( 'methods' => array( 'rotate' ) ) ) ) { + $this->markTestSkipped( 'This test requires an image editor with rotation support.' ); + } + + $this->enable_client_side_media_processing(); + + wp_set_current_user( self::$author_id ); + + $fixture = DIR_TESTDATA . '/images/test-image-rotated-90ccw.jpg'; + + /* + * Reference: a normal upload with server-side processing (the classic + * path). generate_sub_sizes defaults to true, so + * wp_create_image_subsizes() applies the EXIF rotation. + */ + $request = new WP_REST_Request( 'POST', '/wp/v2/media' ); + $request->set_header( 'Content-Type', 'image/jpeg' ); + $request->set_header( 'Content-Disposition', 'attachment; filename=reference.jpg' ); + $request->set_body( (string) file_get_contents( $fixture ) ); + $response = rest_get_server()->dispatch( $request ); + $this->assertSame( 201, $response->get_status() ); + $reference_meta = wp_get_attachment_metadata( $response->get_data()['id'], true ); + + // Sanity check that the reference actually rotated. + $this->assertSame( 1800, $reference_meta['width'], 'Server-side rotation should swap the dimensions.' ); + $this->assertSame( 1200, $reference_meta['height'], 'Server-side rotation should swap the dimensions.' ); + $this->assertNotEmpty( $reference_meta['original_image'], 'Server-side rotation should keep the original file.' ); + $this->assertSame( 1, (int) $reference_meta['image_meta']['orientation'], 'Server-side rotation should reset the stored orientation.' ); + + /* + * Client-side path: upload without server-side processing, so the + * stored dimensions stay at the un-rotated 1200x1800 and orientation + * stays 6. + */ + $request = new WP_REST_Request( 'POST', '/wp/v2/media' ); + $request->set_header( 'Content-Type', 'image/jpeg' ); + $request->set_header( 'Content-Disposition', 'attachment; filename=client.jpg' ); + $request->set_param( 'generate_sub_sizes', false ); + $request->set_body( (string) file_get_contents( $fixture ) ); + $response = rest_get_server()->dispatch( $request ); + $attachment_id = $response->get_data()['id']; + $this->assertSame( 201, $response->get_status() ); + + // Simulate the browser: apply the EXIF orientation and strip the tag. + $editor = wp_get_image_editor( $fixture ); + $this->assertNotWPError( $editor ); + $editor->maybe_exif_rotate(); + $saved = $editor->save( wp_tempnam( 'client-rotated.jpg' ), 'image/jpeg' ); + $this->assertNotWPError( $saved ); + + // Sideload the rotated file as the original, then finalize. + $request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment_id}/sideload" ); + $request->set_header( 'Content-Type', 'image/jpeg' ); + $request->set_header( 'Content-Disposition', 'attachment; filename=client-rotated.jpg' ); + $request->set_param( 'image_size', 'original' ); + $request->set_body( (string) file_get_contents( $saved['path'] ) ); + $response = rest_get_server()->dispatch( $request ); + $original_data = $response->get_data(); + + unlink( $saved['path'] ); + + $this->assertSame( 200, $response->get_status(), 'Sideloading the rotated original should succeed.' ); + + $request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment_id}/finalize" ); + $request->set_param( 'sub_sizes', array( $original_data ) ); + $response = rest_get_server()->dispatch( $request ); + $this->assertSame( 200, $response->get_status(), 'Finalize should succeed.' ); + + $client_meta = wp_get_attachment_metadata( $attachment_id, true ); + + /* + * The two paths should produce the same metadata. The filenames differ, + * so compare dimensions, orientation, and original_image instead of + * exact filenames. + */ + $this->assertSame( $reference_meta['width'], $client_meta['width'], 'Client-side rotation should record the same width as server-side rotation.' ); + $this->assertSame( $reference_meta['height'], $client_meta['height'], 'Client-side rotation should record the same height as server-side rotation.' ); + $this->assertSame( + (int) $reference_meta['image_meta']['orientation'], + (int) $client_meta['image_meta']['orientation'], + 'Client-side rotation should reset the stored orientation like server-side rotation.' + ); + $this->assertNotEmpty( $client_meta['original_image'], 'The original file must be preserved as original_image.' ); + + // original_image must resolve to the un-rotated 1200x1800 source. + $client_original = getimagesize( wp_get_original_image_path( $attachment_id ) ); + $this->assertSame( 1200, $client_original[0], 'original_image should be the un-rotated source width.' ); + $this->assertSame( 1800, $client_original[1], 'original_image should be the un-rotated source height.' ); + } + + /** + * Tests that finalize resets the stored EXIF orientation for 'scaled' + * sub-sizes. The client applies the EXIF rotation when scaling, so the + * stored orientation must be reset to 1 as wp_create_image_subsizes() + * does, or exif_orientation would keep reporting the pre-rotation value. + * + * @ticket 64798 + * @covers WP_REST_Attachments_Controller::finalize_item + * @requires function imagejpeg + */ + public function test_finalize_scaled_resets_orientation(): void { + $this->enable_client_side_media_processing(); + + wp_set_current_user( self::$author_id ); + + $request = new WP_REST_Request( 'POST', '/wp/v2/media' ); + $request->set_header( 'Content-Type', 'image/jpeg' ); + $request->set_header( 'Content-Disposition', 'attachment; filename=big-rotated-photo.jpg' ); + $request->set_param( 'generate_sub_sizes', false ); + $request->set_body( (string) file_get_contents( self::$test_file ) ); + $response = rest_get_server()->dispatch( $request ); + $attachment_id = $response->get_data()['id']; + + $this->assertSame( 201, $response->get_status() ); + + // Simulate an EXIF-rotated upload: canola.jpg carries no orientation + // tag, so store the pre-rotation value directly. + $metadata = wp_get_attachment_metadata( $attachment_id, true ); + $metadata['image_meta']['orientation'] = 6; + wp_update_attachment_metadata( $attachment_id, $metadata ); + + $request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment_id}/finalize" ); + $request->set_param( + 'sub_sizes', + array( + array( + 'image_size' => 'scaled', + 'width' => 1920, + 'height' => 2560, + 'file' => '2026/07/big-rotated-photo-scaled.jpg', + 'filesize' => 500000, + 'original_image' => 'big-rotated-photo.jpg', + ), + ) + ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertSame( 200, $response->get_status(), 'Finalize should succeed.' ); + + $metadata = wp_get_attachment_metadata( $attachment_id, true ); + $this->assertSame( 1, (int) $metadata['image_meta']['orientation'], 'Finalizing a scaled sub-size should reset the stored EXIF orientation.' ); + } + + /** + * Tests that finalize ignores an 'original'/'scaled' entry that is missing + * the file name, so a malformed payload cannot blank out the main file + * metadata. + * + * @ticket 64798 + * @covers WP_REST_Attachments_Controller::finalize_item + * @requires function imagejpeg + */ + public function test_finalize_ignores_main_file_entry_without_file(): void { + $this->enable_client_side_media_processing(); + + wp_set_current_user( self::$author_id ); + + $request = new WP_REST_Request( 'POST', '/wp/v2/media' ); + $request->set_header( 'Content-Type', 'image/jpeg' ); + $request->set_header( 'Content-Disposition', 'attachment; filename=guarded.jpg' ); + $request->set_param( 'generate_sub_sizes', false ); + $request->set_body( (string) file_get_contents( self::$test_file ) ); + $response = rest_get_server()->dispatch( $request ); + $attachment_id = $response->get_data()['id']; + + $this->assertSame( 201, $response->get_status() ); + + $metadata_before = wp_get_attachment_metadata( $attachment_id, true ); + + $request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment_id}/finalize" ); + $request->set_param( + 'sub_sizes', + array( + array( + 'image_size' => 'original', + 'width' => 9999, + 'height' => 9999, + ), + ) + ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertSame( 200, $response->get_status(), 'Finalize should succeed.' ); + + $metadata = wp_get_attachment_metadata( $attachment_id, true ); + $this->assertSame( $metadata_before['file'], $metadata['file'], 'The main file must not be blanked by an entry without a file.' ); + $this->assertSame( $metadata_before['width'], $metadata['width'], 'The width must not be changed by an entry without a file.' ); + $this->assertSame( $metadata_before['height'], $metadata['height'], 'The height must not be changed by an entry without a file.' ); + $this->assertArrayNotHasKey( 'original_image', $metadata, 'No original_image should be recorded from an entry without a file.' ); } /** From e26970bd4bf6170ceb16ceaa08fb2a8db564b2fd Mon Sep 17 00:00:00 2001 From: adamsilverstein Date: Wed, 15 Jul 2026 22:44:34 -0700 Subject: [PATCH 2/2] Reference ticket 65643 in the EXIF rotation sideload tests --- .../tests/rest-api/rest-attachments-controller.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/phpunit/tests/rest-api/rest-attachments-controller.php b/tests/phpunit/tests/rest-api/rest-attachments-controller.php index d59bfe5c14966..911676614754d 100644 --- a/tests/phpunit/tests/rest-api/rest-attachments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-attachments-controller.php @@ -4339,7 +4339,7 @@ public function test_finalize_writes_regular_sub_sizes(): void { * _wp_image_meta_replace_original() performs when the server rotates an * image on upload. * - * @ticket 64798 + * @ticket 65643 * @covers WP_REST_Attachments_Controller::sideload_item * @covers WP_REST_Attachments_Controller::finalize_item * @requires function imagejpeg @@ -4407,7 +4407,7 @@ public function test_finalize_writes_original_metadata(): void { * A strict equality check would reject quarter-turn rotations with * rest_upload_dimension_mismatch. * - * @ticket 64798 + * @ticket 65643 * @covers WP_REST_Attachments_Controller::sideload_item * @covers WP_REST_Attachments_Controller::validate_image_dimensions * @covers WP_REST_Attachments_Controller::finalize_item @@ -4483,7 +4483,7 @@ public function test_sideload_item_accepts_transposed_original_dimensions(): voi * rotates and strips the EXIF orientation; wp_get_image_editor() does the * same here, so no JavaScript is required. * - * @ticket 64798 + * @ticket 65643 * @covers WP_REST_Attachments_Controller::sideload_item * @covers WP_REST_Attachments_Controller::finalize_item * @covers WP_REST_Attachments_Controller::validate_image_dimensions @@ -4587,7 +4587,7 @@ public function test_original_sideload_matches_server_side_rotation(): void { * stored orientation must be reset to 1 as wp_create_image_subsizes() * does, or exif_orientation would keep reporting the pre-rotation value. * - * @ticket 64798 + * @ticket 65643 * @covers WP_REST_Attachments_Controller::finalize_item * @requires function imagejpeg */ @@ -4639,7 +4639,7 @@ public function test_finalize_scaled_resets_orientation(): void { * the file name, so a malformed payload cannot blank out the main file * metadata. * - * @ticket 64798 + * @ticket 65643 * @covers WP_REST_Attachments_Controller::finalize_item * @requires function imagejpeg */