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
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,10 @@ public function create_item( $request ) {
// Disable server-side EXIF rotation so the client can handle it.
// This preserves the original orientation value in the metadata.
add_filter( 'wp_image_maybe_exif_rotate', '__return_false', 100 );
// Disable server-side "big image" downscaling; the client supplies its
// own scaled version via the sideload endpoint. Scaling here would
// create a conflicting "-scaled" file and orphan the full-size upload.
add_filter( 'big_image_size_threshold', '__return_false', 100 );
}

// Handle convert_format parameter.
Expand Down Expand Up @@ -691,6 +695,7 @@ private function remove_client_side_media_processing_filters(): void {
remove_filter( 'fallback_intermediate_image_sizes', '__return_empty_array', 100 );
remove_filter( 'wp_image_maybe_exif_rotate', '__return_false', 100 );
remove_filter( 'image_editor_output_format', '__return_empty_array', 100 );
remove_filter( 'big_image_size_threshold', '__return_false', 100 );
}

/**
Expand Down
65 changes: 65 additions & 0 deletions tests/phpunit/tests/rest-api/rest-attachments-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -3875,6 +3875,71 @@ public function test_sideload_scaled_image() {
$this->assertGreaterThan( 0, $metadata['filesize'], 'Filesize should be positive.' );
}

/**
* When the client generates sub-sizes (generate_sub_sizes is false), the
* server must not perform its own "big image" downscaling on upload.
*
* Otherwise the server creates a `-scaled` file and records the upload as
* `original_image`. The client's subsequent scaled sideload then collides
* with that `-scaled` file and is renamed `-scaled-1`, the thumbnails
* inherit the numbered name, and the server-generated full-size file is
* left orphaned on disk.
*
* @ticket 65708
* @requires function imagejpeg
*/
public function test_create_item_skips_big_image_scaling_when_client_generates_sub_sizes() {
$this->enable_client_side_media_processing();

wp_set_current_user( self::$author_id );

// Force the threshold below the image's dimensions so scaling would be
// triggered were it not suppressed for client-side processing.
add_filter(
'big_image_size_threshold',
static function () {
return 1000;
}
);

// Upload a large image with the client handling sub-size generation.
$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
$request->set_header( 'Content-Type', 'image/jpeg' );
$request->set_header( 'Content-Disposition', 'attachment; filename=33772.jpg' );
$request->set_param( 'generate_sub_sizes', false );
$request->set_body( file_get_contents( DIR_TESTDATA . '/images/33772.jpg' ) );
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$attachment_id = $data['id'];

$this->assertSame( 201, $response->get_status(), 'Uploading the image should succeed.' );

// The uploaded full-size image should be stored untouched: no
// server-side "-scaled" file and no original_image swap.
$original_file = get_attached_file( $attachment_id, true );
$original_basename = wp_basename( $original_file );
$original_name_stem = pathinfo( $original_basename, PATHINFO_FILENAME );
$this->assertStringNotContainsString( '-scaled', $original_basename, 'The server should not create a -scaled file when the client generates sub-sizes.' );

$metadata = wp_get_attachment_metadata( $attachment_id );
$this->assertArrayNotHasKey( 'original_image', $metadata, 'The server should not record an original_image when it does not scale the upload.' );

// The client's scaled sideload should now record the untouched upload as
// original_image and keep the -scaled name without a numeric suffix.
$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={$original_name_stem}-scaled.jpg" );
$request->set_param( 'image_size', 'scaled' );
$request->set_body( file_get_contents( DIR_TESTDATA . '/images/33772.jpg' ) );
$response = rest_get_server()->dispatch( $request );

$this->assertSame( 200, $response->get_status(), 'Sideloading the scaled image should succeed.' );

$sub_size = $response->get_data();
$this->assertSame( $original_basename, $sub_size['original_image'], 'The untouched upload should be recorded as original_image.' );
$this->assertSame( "{$original_name_stem}-scaled.jpg", wp_basename( $sub_size['file'] ), 'The scaled sideload should keep the -scaled name without a numeric collision suffix.' );
}

/**
* Tests that sideloading scaled image requires authentication.
*
Expand Down
Loading