Changeset 61809
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php
r61703 r61809 71 71 // Used for PDF thumbnails. 72 72 $valid_image_sizes[] = 'full'; 73 // Client-side big image threshold: sideload the scaled version. 74 $valid_image_sizes[] = 'scaled'; 73 75 74 76 register_rest_route( … … 2054 2056 if ( 'original' === $image_size ) { 2055 2057 $metadata['original_image'] = wp_basename( $path ); 2058 } elseif ( 'scaled' === $image_size ) { 2059 // The current attached file is the original; record it as original_image. 2060 $current_file = get_attached_file( $attachment_id, true ); 2061 2062 if ( ! $current_file ) { 2063 return new WP_Error( 2064 'rest_sideload_no_attached_file', 2065 __( 'Unable to retrieve the attached file for this attachment.' ), 2066 array( 'status' => 404 ) 2067 ); 2068 } 2069 2070 $metadata['original_image'] = wp_basename( $current_file ); 2071 2072 // Validate the scaled image before updating the attached file. 2073 $size = wp_getimagesize( $path ); 2074 $filesize = wp_filesize( $path ); 2075 2076 if ( ! $size || ! $filesize ) { 2077 return new WP_Error( 2078 'rest_sideload_invalid_image', 2079 __( 'Unable to read the scaled image file.' ), 2080 array( 'status' => 500 ) 2081 ); 2082 } 2083 2084 // Update the attached file to point to the scaled version. 2085 if ( 2086 get_attached_file( $attachment_id, true ) !== $path && 2087 ! update_attached_file( $attachment_id, $path ) 2088 ) { 2089 return new WP_Error( 2090 'rest_sideload_update_attached_file_failed', 2091 __( 'Unable to update the attached file for this attachment.' ), 2092 array( 'status' => 500 ) 2093 ); 2094 } 2095 2096 $metadata['width'] = $size[0]; 2097 $metadata['height'] = $size[1]; 2098 $metadata['filesize'] = $filesize; 2099 $metadata['file'] = _wp_relative_upload_path( $path ); 2056 2100 } else { 2057 2101 $metadata['sizes'] = $metadata['sizes'] ?? array(); … … 2111 2155 */ 2112 2156 private static function filter_wp_unique_filename( $filename, $dir, $number, $attachment_filename ) { 2113 if ( empty( $number ) || ! $attachment_filename ) {2157 if ( ! is_int( $number ) || ! $attachment_filename ) { 2114 2158 return $filename; 2115 2159 } … … 2124 2168 2125 2169 $matches = array(); 2126 if ( preg_match( '/(.*) (-\d+x\d+)-' . $number . '$/', $name, $matches ) ) {2127 $filename_without_suffix = $matches[1] . $matches[2] . ".$ext";2170 if ( preg_match( '/(.*)-(\d+x\d+|scaled)-' . $number . '$/', $name, $matches ) ) { 2171 $filename_without_suffix = $matches[1] . '-' . $matches[2] . ".$ext"; 2128 2172 if ( $matches[1] === $orig_name && ! file_exists( "$dir/$filename_without_suffix" ) ) { 2129 2173 return $filename_without_suffix; -
trunk/tests/phpunit/tests/rest-api/rest-attachments-controller.php
r61703 r61809 3155 3155 $this->assertIsArray( $captured_data, 'Data passed to wp_insert_attachment should be an array' ); 3156 3156 } 3157 3158 /** 3159 * Tests sideloading a scaled image for an existing attachment. 3160 * 3161 * @ticket 64737 3162 * @requires function imagejpeg 3163 */ 3164 public function test_sideload_scaled_image() { 3165 wp_set_current_user( self::$author_id ); 3166 3167 // First, create an attachment. 3168 $request = new WP_REST_Request( 'POST', '/wp/v2/media' ); 3169 $request->set_header( 'Content-Type', 'image/jpeg' ); 3170 $request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' ); 3171 $request->set_body( file_get_contents( self::$test_file ) ); 3172 $response = rest_get_server()->dispatch( $request ); 3173 $data = $response->get_data(); 3174 $attachment_id = $data['id']; 3175 3176 $this->assertSame( 201, $response->get_status() ); 3177 3178 $original_file = get_attached_file( $attachment_id, true ); 3179 3180 // Sideload a "scaled" version of the image. 3181 $request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment_id}/sideload" ); 3182 $request->set_header( 'Content-Type', 'image/jpeg' ); 3183 $request->set_header( 'Content-Disposition', 'attachment; filename=canola-scaled.jpg' ); 3184 $request->set_param( 'image_size', 'scaled' ); 3185 $request->set_body( file_get_contents( self::$test_file ) ); 3186 $response = rest_get_server()->dispatch( $request ); 3187 3188 $this->assertSame( 200, $response->get_status(), 'Sideloading scaled image should succeed.' ); 3189 3190 $metadata = wp_get_attachment_metadata( $attachment_id ); 3191 3192 // The original file should now be recorded as original_image. 3193 $this->assertArrayHasKey( 'original_image', $metadata, 'Metadata should contain original_image.' ); 3194 $this->assertSame( wp_basename( $original_file ), $metadata['original_image'], 'original_image should be the basename of the original attached file.' ); 3195 3196 // The attached file should now point to the scaled version. 3197 $new_file = get_attached_file( $attachment_id, true ); 3198 $this->assertStringContainsString( 'scaled', wp_basename( $new_file ), 'Attached file should now be the scaled version.' ); 3199 3200 // Metadata should have width, height, filesize, and file updated. 3201 $this->assertArrayHasKey( 'width', $metadata, 'Metadata should contain width.' ); 3202 $this->assertArrayHasKey( 'height', $metadata, 'Metadata should contain height.' ); 3203 $this->assertArrayHasKey( 'filesize', $metadata, 'Metadata should contain filesize.' ); 3204 $this->assertArrayHasKey( 'file', $metadata, 'Metadata should contain file.' ); 3205 $this->assertStringContainsString( 'scaled', $metadata['file'], 'Metadata file should reference the scaled version.' ); 3206 $this->assertGreaterThan( 0, $metadata['width'], 'Width should be positive.' ); 3207 $this->assertGreaterThan( 0, $metadata['height'], 'Height should be positive.' ); 3208 $this->assertGreaterThan( 0, $metadata['filesize'], 'Filesize should be positive.' ); 3209 } 3210 3211 /** 3212 * Tests that sideloading scaled image requires authentication. 3213 * 3214 * @ticket 64737 3215 * @requires function imagejpeg 3216 */ 3217 public function test_sideload_scaled_image_requires_auth() { 3218 wp_set_current_user( self::$author_id ); 3219 3220 // Create an attachment. 3221 $request = new WP_REST_Request( 'POST', '/wp/v2/media' ); 3222 $request->set_header( 'Content-Type', 'image/jpeg' ); 3223 $request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' ); 3224 $request->set_body( file_get_contents( self::$test_file ) ); 3225 $response = rest_get_server()->dispatch( $request ); 3226 $attachment_id = $response->get_data()['id']; 3227 3228 // Try sideloading without authentication. 3229 wp_set_current_user( 0 ); 3230 3231 $request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment_id}/sideload" ); 3232 $request->set_header( 'Content-Type', 'image/jpeg' ); 3233 $request->set_header( 'Content-Disposition', 'attachment; filename=canola-scaled.jpg' ); 3234 $request->set_param( 'image_size', 'scaled' ); 3235 $request->set_body( file_get_contents( self::$test_file ) ); 3236 $response = rest_get_server()->dispatch( $request ); 3237 3238 $this->assertErrorResponse( 'rest_cannot_edit_image', $response, 401 ); 3239 } 3240 3241 /** 3242 * Tests that the sideload endpoint includes 'scaled' in the image_size enum. 3243 * 3244 * @ticket 64737 3245 */ 3246 public function test_sideload_route_includes_scaled_enum() { 3247 $server = rest_get_server(); 3248 $routes = $server->get_routes(); 3249 3250 $endpoint = '/wp/v2/media/(?P<id>[\d]+)/sideload'; 3251 $this->assertArrayHasKey( $endpoint, $routes, 'Sideload route should exist.' ); 3252 3253 $route = $routes[ $endpoint ]; 3254 $endpoint = $route[0]; 3255 $args = $endpoint['args']; 3256 3257 $param_name = 'image_size'; 3258 $this->assertArrayHasKey( $param_name, $args, 'Route should have image_size arg.' ); 3259 $this->assertContains( 'scaled', $args[ $param_name ]['enum'], 'image_size enum should include scaled.' ); 3260 } 3261 3262 /** 3263 * Tests the filter_wp_unique_filename method handles the -scaled suffix. 3264 * 3265 * @ticket 64737 3266 * @requires function imagejpeg 3267 */ 3268 public function test_sideload_scaled_unique_filename() { 3269 wp_set_current_user( self::$author_id ); 3270 3271 // Create an attachment. 3272 $request = new WP_REST_Request( 'POST', '/wp/v2/media' ); 3273 $request->set_header( 'Content-Type', 'image/jpeg' ); 3274 $request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' ); 3275 $request->set_body( file_get_contents( self::$test_file ) ); 3276 $response = rest_get_server()->dispatch( $request ); 3277 $attachment_id = $response->get_data()['id']; 3278 3279 // Sideload with the -scaled suffix. 3280 $request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment_id}/sideload" ); 3281 $request->set_header( 'Content-Type', 'image/jpeg' ); 3282 $request->set_header( 'Content-Disposition', 'attachment; filename=canola-scaled.jpg' ); 3283 $request->set_param( 'image_size', 'scaled' ); 3284 $request->set_body( file_get_contents( self::$test_file ) ); 3285 $response = rest_get_server()->dispatch( $request ); 3286 3287 $this->assertSame( 200, $response->get_status(), 'Sideloading scaled image should succeed.' ); 3288 3289 // The filename should retain the -scaled suffix without numeric disambiguation. 3290 $new_file = get_attached_file( $attachment_id, true ); 3291 $basename = wp_basename( $new_file ); 3292 $this->assertMatchesRegularExpression( '/canola-scaled\.jpg$/', $basename, 'Scaled filename should not have numeric suffix appended.' ); 3293 } 3294 3295 /** 3296 * Tests that sideloading a scaled image for a different attachment retains the numeric suffix 3297 * when a file with the same name already exists on disk. 3298 * 3299 * @ticket 64737 3300 * @requires function imagejpeg 3301 */ 3302 public function test_sideload_scaled_unique_filename_conflict() { 3303 wp_set_current_user( self::$author_id ); 3304 3305 // Create the first attachment. 3306 $request = new WP_REST_Request( 'POST', '/wp/v2/media' ); 3307 $request->set_header( 'Content-Type', 'image/jpeg' ); 3308 $request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' ); 3309 $request->set_body( file_get_contents( self::$test_file ) ); 3310 $response = rest_get_server()->dispatch( $request ); 3311 $attachment_id_a = $response->get_data()['id']; 3312 3313 // Sideload a scaled image for attachment A, creating canola-scaled.jpg on disk. 3314 $request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment_id_a}/sideload" ); 3315 $request->set_header( 'Content-Type', 'image/jpeg' ); 3316 $request->set_header( 'Content-Disposition', 'attachment; filename=canola-scaled.jpg' ); 3317 $request->set_param( 'image_size', 'scaled' ); 3318 $request->set_body( file_get_contents( self::$test_file ) ); 3319 $response = rest_get_server()->dispatch( $request ); 3320 3321 $this->assertSame( 200, $response->get_status(), 'First sideload should succeed.' ); 3322 3323 // Create a second, different attachment. 3324 $request = new WP_REST_Request( 'POST', '/wp/v2/media' ); 3325 $request->set_header( 'Content-Type', 'image/jpeg' ); 3326 $request->set_header( 'Content-Disposition', 'attachment; filename=other.jpg' ); 3327 $request->set_body( file_get_contents( self::$test_file ) ); 3328 $response = rest_get_server()->dispatch( $request ); 3329 $attachment_id_b = $response->get_data()['id']; 3330 3331 // Sideload scaled for attachment B using the same filename that already exists on disk. 3332 $request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment_id_b}/sideload" ); 3333 $request->set_header( 'Content-Type', 'image/jpeg' ); 3334 $request->set_header( 'Content-Disposition', 'attachment; filename=canola-scaled.jpg' ); 3335 $request->set_param( 'image_size', 'scaled' ); 3336 $request->set_body( file_get_contents( self::$test_file ) ); 3337 $response = rest_get_server()->dispatch( $request ); 3338 3339 $this->assertSame( 200, $response->get_status(), 'Second sideload should succeed.' ); 3340 3341 // The filename should have a numeric suffix since the base name does not match this attachment. 3342 $new_file = get_attached_file( $attachment_id_b, true ); 3343 $basename = wp_basename( $new_file ); 3344 $this->assertMatchesRegularExpression( '/canola-scaled-\d+\.jpg$/', $basename, 'Scaled filename should have numeric suffix when file conflicts with a different attachment.' ); 3345 } 3157 3346 } -
trunk/tests/qunit/fixtures/wp-api-generated.js
r61749 r61809 3704 3704 "2048x2048", 3705 3705 "original", 3706 "full" 3706 "full", 3707 "scaled" 3707 3708 ], 3708 3709 "required": true
Note: See TracChangeset
for help on using the changeset viewer.