Ticket #55443: 55443.3.diff
File 55443.3.diff, 56.4 KB (added by , 3 years ago) |
---|
-
src/js/_enqueues/vendor/plupload/handlers.js
diff --git src/js/_enqueues/vendor/plupload/handlers.js src/js/_enqueues/vendor/plupload/handlers.js index fa602daf43..c7e3c253d3 100644
jQuery( document ).ready( function( $ ) { 486 486 487 487 times = tryAgainCount[ file.id ]; 488 488 489 if ( times && times > 4) {489 if ( times && times > 8 ) { 490 490 /* 491 491 * The file may have been uploaded and attachment post created, 492 492 * but post-processing and resizing failed... -
src/js/_enqueues/vendor/plupload/wp-plupload.js
diff --git src/js/_enqueues/vendor/plupload/wp-plupload.js src/js/_enqueues/vendor/plupload/wp-plupload.js index 0fdebf77d1..217b3c09e2 100644
window.wp = window.wp || {}; 138 138 139 139 times = tryAgainCount[ file.id ]; 140 140 141 if ( times && times > 4) {141 if ( times && times > 8 ) { 142 142 /* 143 143 * The file may have been uploaded and attachment post created, 144 144 * but post-processing and resizing failed... -
src/wp-admin/includes/image.php
diff --git src/wp-admin/includes/image.php src/wp-admin/includes/image.php index 2818b3dd5d..b20a509ccc 100644
function _wp_image_meta_replace_original( $saved_data, $original_file, $image_me 217 217 } 218 218 219 219 /** 220 * Creates image sub-sizes, adds the new data to the image meta `sizes` array, and updates the image metadata.220 * Creates image mime variations and sub-sizes, adds the new data to the image meta `sizes` array, and updates the image metadata. 221 221 * 222 222 * Intended for use after an image is uploaded. Saves/updates the image metadata after each 223 223 * sub-size is created. If there was an error, it is added to the returned image metadata array. 224 224 * 225 225 * @since 5.3.0 226 * @since 6.0.0 Generates sub-sizes in alternate mime types based on the `wp_image_mime_transforms` filter. 226 227 * 227 228 * @param string $file Full path to the image file. 228 229 * @param int $attachment_id Attachment ID to process. … … function wp_create_image_subsizes( $file, $attachment_id ) { 243 244 'file' => _wp_relative_upload_path( $file ), 244 245 'filesize' => wp_filesize( $file ), 245 246 'sizes' => array(), 247 'sources' => array(), 246 248 ); 247 249 248 250 // Fetch additional metadata from EXIF/IPTC. … … function wp_create_image_subsizes( $file, $attachment_id ) { 252 254 $image_meta['image_meta'] = $exif_meta; 253 255 } 254 256 255 // Do not scale (large) PNG images. May result in sub-sizes that have greater file size than the original. See #48736. 256 if ( 'image/png' !== $imagesize['mime'] ) { 257 /** 258 * Filters the "BIG image" threshold value. 259 * 260 * If the original image width or height is above the threshold, it will be scaled down. The threshold is 261 * used as max width and max height. The scaled down image will be used as the largest available size, including 262 * the `_wp_attached_file` post meta value. 263 * 264 * Returning `false` from the filter callback will disable the scaling. 265 * 266 * @since 5.3.0 267 * 268 * @param int $threshold The threshold value in pixels. Default 2560. 269 * @param array $imagesize { 270 * Indexed array of the image width and height in pixels. 271 * 272 * @type int $0 The image width. 273 * @type int $1 The image height. 274 * } 275 * @param string $file Full path to the uploaded image file. 276 * @param int $attachment_id Attachment post ID. 277 */ 278 $threshold = (int) apply_filters( 'big_image_size_threshold', 2560, $imagesize, $file, $attachment_id ); 257 279 258 /** 259 * Filters the "BIG image" threshold value. 260 * 261 * If the original image width or height is above the threshold, it will be scaled down. The threshold is 262 * used as max width and max height. The scaled down image will be used as the largest available size, including 263 * the `_wp_attached_file` post meta value. 264 * 265 * Returning `false` from the filter callback will disable the scaling. 266 * 267 * @since 5.3.0 268 * 269 * @param int $threshold The threshold value in pixels. Default 2560. 270 * @param array $imagesize { 271 * Indexed array of the image width and height in pixels. 272 * 273 * @type int $0 The image width. 274 * @type int $1 The image height. 275 * } 276 * @param string $file Full path to the uploaded image file. 277 * @param int $attachment_id Attachment post ID. 278 */ 279 $threshold = (int) apply_filters( 'big_image_size_threshold', 2560, $imagesize, $file, $attachment_id ); 280 $over_threshold = $threshold && ( $image_meta['width'] > $threshold || $image_meta['height'] > $threshold ); 280 281 281 // If the original image's dimensions are over the threshold, 282 // scale the image and use it as the "full" size. 283 if ( $threshold && ( $image_meta['width'] > $threshold || $image_meta['height'] > $threshold ) ) { 284 $editor = wp_get_image_editor( $file ); 282 // Calculate the primary (first) and additional mime types to generate. 283 $mime_types_to_generate = _wp_get_primary_and_additional_mime_types( $file, $attachment_id ); 284 foreach ( $mime_types_to_generate as $output_index => $output_mime_type ) { 285 // Populate the top level primary mime type data. 286 if ( 0 === $output_index ) { 287 $image_meta['sources'][ $output_mime_type ] = _wp_get_sources_from_meta( $image_meta ); 288 wp_update_attachment_metadata( $attachment_id, $image_meta ); 289 } 290 291 // Do not scale (large) PNG images. May result in sub-sizes that have greater file size than the original. See #48736. 292 if ( 'image/png' !== $imagesize['mime'] ) { 293 $editor = wp_get_image_editor( $file, array( 'mime_type' => $output_mime_type ) ); 285 294 286 295 if ( is_wp_error( $editor ) ) { 287 296 // This image cannot be edited. 288 return $image_meta;297 continue; 289 298 } 299 $editor->set_mime_type( $output_mime_type ); 290 300 291 // Resize the image. 292 $resized = $editor->resize( $threshold, $threshold ); 293 $rotated = null; 294 295 // If there is EXIF data, rotate according to EXIF Orientation. 296 if ( ! is_wp_error( $resized ) && is_array( $exif_meta ) ) { 297 $resized = $editor->maybe_exif_rotate(); 298 $rotated = $resized; 299 } 301 // If the original image's dimensions are over the threshold, 302 // scale the image and use it as the "full" size. 303 if ( $over_threshold ) { 300 304 301 if ( ! is_wp_error( $resized ) ) { 302 // Append "-scaled" to the image file name. It will look like "my_image-scaled.jpg". 303 // This doesn't affect the sub-sizes names as they are generated from the original image (for best quality). 304 $saved = $editor->save( $editor->generate_filename( 'scaled' ) ); 305 // Resize the image. 306 $resized = $editor->resize( $threshold, $threshold ); 307 $rotated = null; 305 308 306 if ( ! is_wp_error( $saved ) ) { 307 $image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id ); 309 // If there is EXIF data, rotate according to EXIF Orientation. 310 if ( ! is_wp_error( $resized ) && is_array( $exif_meta ) ) { 311 $resized = $editor->maybe_exif_rotate(); 312 $rotated = $resized; 313 } 308 314 309 // If the image was rotated update the stored EXIF data. 310 if ( true === $rotated && ! empty( $image_meta['image_meta']['orientation'] ) ) { 311 $image_meta['image_meta']['orientation'] = 1; 315 if ( ! is_wp_error( $resized ) ) { 316 // Append "-scaled" to the image file name. It will look like "my_image-scaled.jpg". 317 // This doesn't affect the sub-sizes names as they are generated from the original image (for best quality). 318 $saved = $editor->save( $editor->generate_filename( 'scaled' ), $output_mime_type ); 319 320 if ( ! is_wp_error( $saved ) ) { 321 if ( 0 === $output_index ) { 322 $image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id ); 323 } 324 // If the image was rotated update the stored EXIF data. 325 if ( true === $rotated && ! empty( $image_meta['image_meta']['orientation'] ) ) { 326 $image_meta['image_meta']['orientation'] = 1; 327 } 328 } else { 329 // TODO: Log errors. 312 330 } 313 331 } else { 314 332 // TODO: Log errors. 315 333 } 316 334 } else { 317 // TODO: Log errors. 318 } 319 } elseif ( ! empty( $exif_meta['orientation'] ) && 1 !== (int) $exif_meta['orientation'] ) { 320 // Rotate the whole original image if there is EXIF data and "orientation" is not 1. 335 // Generate additional full sized images. 336 if ( $output_index > 0 ) { 337 if ( empty( $image_meta['sources'][ $output_mime_type ] ) ) { 338 $extension = wp_get_default_extension_for_mime_type( $output_mime_type ); 339 $saved = $editor->save( $editor->generate_filename( '', null, $extension ), $output_mime_type ); 340 if ( ! is_wp_error( $saved ) ) { 341 $image_meta['sources'][ $output_mime_type ] = _wp_get_sources_from_meta( $saved ); 342 wp_update_attachment_metadata( $attachment_id, $image_meta ); 343 } 344 } 345 } 321 346 322 $editor = wp_get_image_editor( $file ); 347 if ( ! empty( $exif_meta['orientation'] ) && 1 !== (int) $exif_meta['orientation'] ) { 348 // Rotate the whole original image if there is EXIF data and "orientation" is not 1. 323 349 324 if ( is_wp_error( $editor ) ) { 325 // This image cannot be edited. 326 return $image_meta; 327 } 350 $editor = wp_get_image_editor( $file, array( 'mime_type' => $output_mime_type ) ); 328 351 329 // Rotate the image. 330 $rotated = $editor->maybe_exif_rotate(); 352 if ( is_wp_error( $editor ) ) { 353 // This image cannot be edited. 354 return $image_meta; 355 } 331 356 332 if ( true === $rotated ) { 333 // Append `-rotated` to the image file name. 334 $saved = $editor->save( $editor->generate_filename( 'rotated' ) ); 357 $editor->set_mime_type( $output_mime_type ); 335 358 336 if ( ! is_wp_error( $saved ) ) {337 $ image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id);359 // Rotate the image. 360 $rotated = $editor->maybe_exif_rotate(); 338 361 339 // Update the stored EXIF data. 340 if ( ! empty( $image_meta['image_meta']['orientation'] ) ) { 341 $image_meta['image_meta']['orientation'] = 1; 362 if ( true === $rotated ) { 363 // Append `-rotated` to the image file name. 364 $saved = $editor->save( $editor->generate_filename( 'rotated' ), $output_mime_type ); 365 366 if ( ! is_wp_error( $saved ) ) { 367 $image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id ); 368 369 // Update the stored EXIF data. 370 if ( ! empty( $image_meta['image_meta']['orientation'] ) ) { 371 $image_meta['image_meta']['orientation'] = 1; 372 } 373 } else { 374 // TODO: Log errors. 375 } 342 376 } 343 } else {344 // TODO: Log errors.345 377 } 346 378 } 347 379 } 348 380 } 349 381 350 382 /* 351 352 353 354 383 * Initial save of the new metadata. 384 * At this point the file was uploaded and moved to the uploads directory 385 * but the image sub-sizes haven't been created yet and the `sizes` array is empty. 386 */ 355 387 wp_update_attachment_metadata( $attachment_id, $image_meta ); 356 388 357 389 $new_sizes = wp_get_registered_image_subsizes(); … … function wp_create_image_subsizes( $file, $attachment_id ) { 372 404 return _wp_make_subsizes( $new_sizes, $file, $image_meta, $attachment_id ); 373 405 } 374 406 407 /** 408 * Gets a sources array element from a meta. 409 * 410 * @since 6.0.0 411 * @access private 412 * 413 * @param array $meta The meta to get the source from. 414 * @return array The source array element. 415 */ 416 function _wp_get_sources_from_meta( $meta ) { 417 return array( 418 'file' => wp_basename( $meta['file'] ), 419 'filesize' => isset( $meta['filesize'] ) ? $meta['filesize'] : wp_filesize( $meta['path'] ), 420 ); 421 } 422 375 423 /** 376 424 * Low-level function to create image sub-sizes. 377 425 * … … function wp_create_image_subsizes( $file, $attachment_id ) { 379 427 * Errors are stored in the returned image metadata array. 380 428 * 381 429 * @since 5.3.0 430 * @since 6.0.0 Support for generating multiple mime type sub-sizes was added. 382 431 * @access private 383 432 * 384 433 * @param array $new_sizes Array defining what sizes to create. … … function _wp_make_subsizes( $new_sizes, $file, $image_meta, $attachment_id ) { 392 441 // Not an image attachment. 393 442 return array(); 394 443 } 395 396 // Check if any of the new sizes already exist. 397 if ( isset( $image_meta['sizes'] ) && is_array( $image_meta['sizes'] ) ) { 398 foreach ( $image_meta['sizes'] as $size_name => $size_meta ) { 399 /* 400 * Only checks "size name" so we don't override existing images even if the dimensions 401 * don't match the currently defined size with the same name. 402 * To change the behavior, unset changed/mismatched sizes in the `sizes` array in image meta. 403 */ 404 if ( array_key_exists( $size_name, $new_sizes ) ) { 405 unset( $new_sizes[ $size_name ] ); 444 // Calculate the primary (first) and additional mime types to generate. 445 $mime_types_to_generate = _wp_get_primary_and_additional_mime_types( $file, $attachment_id ); 446 foreach ( $mime_types_to_generate as $output_index => $output_mime_type ) { 447 // For the primary image, check if any of the new sizes already exist. 448 if ( 0 === $output_index ) { 449 if ( isset( $image_meta['sizes'] ) && is_array( $image_meta['sizes'] ) ) { 450 foreach ( $image_meta['sizes'] as $size_name => $size_meta ) { 451 /* 452 * Only checks "size name" so we don't override existing images even if the dimensions 453 * don't match the currently defined size with the same name. 454 * To change the behavior, unset changed/mismatched sizes in the `sizes` array in image meta. 455 */ 456 if ( array_key_exists( $size_name, $new_sizes ) ) { 457 unset( $new_sizes[ $size_name ] ); 458 } 459 } 460 } else { 461 $image_meta['sizes'] = array(); 406 462 } 407 463 } 408 } else {409 $image_meta['sizes'] = array();410 }411 412 if ( empty( $new_sizes ) ) {413 // Nothing to do...414 return $image_meta;415 }416 417 /*418 * Sort the image sub-sizes in order of priority when creating them.419 * This ensures there is an appropriate sub-size the user can access immediately420 * even when there was an error and not all sub-sizes were created.421 */422 $priority = array(423 'medium' => null,424 'large' => null,425 'thumbnail' => null,426 'medium_large' => null,427 );428 464 429 $new_sizes = array_filter( array_merge( $priority, $new_sizes ) ); 465 if ( empty( $new_sizes ) ) { 466 // Nothing to do... 467 return $image_meta; 468 } 430 469 431 $editor = wp_get_image_editor( $file ); 470 /* 471 * Sort the image sub-sizes in order of priority when creating them. 472 * This ensures there is an appropriate sub-size the user can access immediately 473 * even when there was an error and not all sub-sizes were created. 474 */ 475 $priority = array( 476 'medium' => null, 477 'large' => null, 478 'thumbnail' => null, 479 'medium_large' => null, 480 ); 432 481 433 if ( is_wp_error( $editor ) ) { 434 // The image cannot be edited. 435 return $image_meta; 436 } 482 $new_sizes = array_filter( array_merge( $priority, $new_sizes ) ); 437 483 438 // If stored EXIF data exists, rotate the source image before creating sub-sizes. 439 if ( ! empty( $image_meta['image_meta'] ) ) { 440 $rotated = $editor->maybe_exif_rotate(); 484 $editor = wp_get_image_editor( $file, array( 'mime_type' => $output_mime_type ) ); 441 485 442 if ( is_wp_error( $rotated ) ) { 443 // TODO: Log errors. 486 if ( is_wp_error( $editor ) ) { 487 // The image cannot be edited. 488 return $image_meta; 444 489 } 445 }446 490 447 if ( method_exists( $editor, 'make_subsize' ) ) { 448 foreach ( $new_sizes as $new_size_name => $new_size_data ) { 449 $new_size_meta = $editor->make_subsize( $new_size_data ); 491 $editor->set_mime_type( $output_mime_type ); 450 492 451 if ( is_wp_error( $new_size_meta ) ) { 493 // If stored EXIF data exists, rotate the source image before creating sub-sizes. 494 if ( ! empty( $image_meta['image_meta'] ) ) { 495 $rotated = $editor->maybe_exif_rotate(); 496 497 if ( is_wp_error( $rotated ) ) { 452 498 // TODO: Log errors. 453 } else {454 // Save the size meta value.455 $image_meta['sizes'][ $new_size_name ] = $new_size_meta;456 wp_update_attachment_metadata( $attachment_id, $image_meta );457 499 } 458 500 } 459 } else {460 // Fall back to `$editor->multi_resize()`.461 $created_sizes = $editor->multi_resize( $new_sizes );462 501 463 if ( ! empty( $created_sizes ) ) { 464 $image_meta['sizes'] = array_merge( $image_meta['sizes'], $created_sizes ); 465 wp_update_attachment_metadata( $attachment_id, $image_meta ); 502 if ( method_exists( $editor, 'make_subsize' ) ) { 503 foreach ( $new_sizes as $new_size_name => $new_size_data ) { 504 $new_size_meta = $editor->make_subsize( $new_size_data ); 505 506 if ( is_wp_error( $new_size_meta ) ) { 507 // TODO: Log errors. 508 } else { 509 // Save the primary mime type sizes meta value. 510 if ( 0 === $output_index ) { 511 $image_meta['sizes'][ $new_size_name ] = $new_size_meta; 512 } 513 // Update the sources array with the new sub-size. 514 $image_meta['sizes'][ $new_size_name ]['sources'][ $output_mime_type ] = _wp_get_sources_from_meta( $new_size_meta ); 515 wp_update_attachment_metadata( $attachment_id, $image_meta ); 516 } 517 } 518 } else { 519 // Fall back to `$editor->multi_resize()`. 520 $created_sizes = $editor->multi_resize( $new_sizes ); 521 522 if ( ! empty( $created_sizes ) ) { 523 // Save the primary mime type sizes meta value. 524 if ( 0 === $output_index ) { 525 $image_meta['sizes'] = array_merge( $image_meta['sizes'], $created_sizes ); 526 } 527 // Update the sources array with the new sub-size. 528 $image_meta['sizes'][ $new_size_name ]['sources'][ $output_mime_type ] = _wp_get_sources_from_meta( $new_size_meta ); 529 wp_update_attachment_metadata( $attachment_id, $image_meta ); 530 } 466 531 } 467 532 } 468 533 … … function wp_generate_attachment_metadata( $attachment_id, $file ) { 651 716 */ 652 717 return apply_filters( 'wp_generate_attachment_metadata', $metadata, $attachment_id, 'create' ); 653 718 } 654 655 719 /** 656 720 * Convert a fraction string to a decimal. 657 721 * … … function _copy_image_file( $attachment_id ) { 1143 1207 1144 1208 return $dst_file; 1145 1209 } 1210 1211 /** 1212 * Returns an array with the list of valid mime types that a specific mime type should be converted into. 1213 * For example an `image/jpeg` should be converted into an `image/jpeg` and `image/webp`. The first type 1214 * is considered the primary output type for this image. 1215 * 1216 * @since 6.0.0 1217 * 1218 * @param $attachment_id int The attachment ID. 1219 * @return array<string, array<string>> An array of valid mime types, where the key is the source file mime type and the 1220 * value is one or more mime file types to generate. 1221 */ 1222 function wp_upload_image_mime_transforms( $attachment_id ) { 1223 $image_mime_transforms = array( 1224 'image/jpeg' => array( 'image/jpeg', 'image/webp' ), 1225 'image/webp' => array( 'image/webp', 'image/jpeg' ), 1226 ); 1227 1228 /** 1229 * Filter to the output mime types for a given input mime type. 1230 * 1231 * @since 6.0.0 1232 * 1233 * @param array $image_mime_transforms A map with the valid mime transforms where the key is the source file mime type 1234 * and the value is one or more mime file types to generate. 1235 * @param int $attachment_id The ID of the attachment where the hook was dispatched. 1236 */ 1237 return (array) apply_filters( 'wp_upload_image_mime_transforms', $image_mime_transforms, $attachment_id ); 1238 } 1239 1240 /** 1241 * Extract the primary and additional mime output types for an image from the $image_mime_transforms. 1242 * 1243 * @since 6.0.0 1244 * @access private 1245 * 1246 * @param string $file Full path to the image file. 1247 * @param int $attachment_id Attachment ID to process. 1248 * @return array<string, array<string>> An array with the primary mime type and the additional mime types. 1249 */ 1250 function _wp_get_primary_and_additional_mime_types( $file, $attachment_id ) { 1251 $image_mime_transforms = wp_upload_image_mime_transforms( $attachment_id ); 1252 $original_mime_type = wp_get_image_mime( $file ); 1253 $output_mime_types = isset( $image_mime_transforms[ $original_mime_type ] ) ? $image_mime_transforms[ $original_mime_type ] : array( $original_mime_type ); 1254 1255 // Exclude any output mime types that the system doesn't support. 1256 $output_mime_types = array_filter( 1257 $output_mime_types, 1258 function( $mime_type ) { 1259 return wp_image_editor_supports( 1260 array( 1261 'mime_type' => $mime_type, 1262 ) 1263 ); 1264 } 1265 ); 1266 1267 // Use original mime type as primary mime type, or alternatively the first one. 1268 $primary_mime_type_key = array_search( $original_mime_type, $output_mime_types, true ); 1269 if ( false === $primary_mime_type_key ) { 1270 $primary_mime_type_key = 0; 1271 } 1272 // Split output mime types into primary mime type and additional mime types. 1273 $additional_mime_types = $output_mime_types; 1274 list( $primary_mime_type ) = array_splice( $additional_mime_types, $primary_mime_type_key, 1 ); 1275 1276 // Ensure $primary_mime_type is set. 1277 if ( empty( $primary_mime_type ) ) { 1278 $primary_mime_type = $original_mime_type; 1279 } 1280 return array_merge( 1281 array( $primary_mime_type ), 1282 $additional_mime_types 1283 ); 1284 } -
src/wp-includes/class-wp-image-editor.php
diff --git src/wp-includes/class-wp-image-editor.php src/wp-includes/class-wp-image-editor.php index 823501eb46..b0a14a4800 100644
abstract class WP_Image_Editor { 15 15 protected $file = null; 16 16 protected $size = null; 17 17 protected $mime_type = null; 18 protected $mime_type_set = false; 18 19 protected $output_mime_type = null; 19 20 protected $default_mime_type = 'image/jpeg'; 20 21 protected $quality = false; … … abstract class WP_Image_Editor { 336 337 // If no file specified, grab editor's current extension and mime-type. 337 338 $file_ext = strtolower( pathinfo( $this->file, PATHINFO_EXTENSION ) ); 338 339 $file_mime = $this->mime_type; 340 // Favor the file mime extension. 341 $ext = $this->get_extension( $file_mime ); 342 if ( $this->mime_type_set && $ext !== $file_ext ) { 343 $new_ext = $ext; 344 $mime_type = $file_mime; 345 } 339 346 } 340 347 341 348 // Check to see if specified mime-type is the same as type implied by 342 349 // file extension. If so, prefer extension from file. 343 if ( ! $ mime_type || ( $file_mime == $mime_type) ) {350 if ( ! $this->mime_type_set && ( ! $mime_type || ( $file_mime == $mime_type ) ) ) { 344 351 $mime_type = $file_mime; 345 352 $new_ext = $file_ext; 346 353 } … … abstract class WP_Image_Editor { 418 425 * Builds an output filename based on current file, and adding proper suffix 419 426 * 420 427 * @since 3.5.0 428 * @since 6.0.0 Skips adding a suffix when set to an empty string. 421 429 * 422 * @param string $suffix 430 * @param string $suffix Optional. Suffix to add to the filename. Passing null 431 * will result in a 'widthxheight' suffix. Passing 432 * an empty string will result in no suffix. 423 433 * @param string $dest_path 424 434 * @param string $extension 425 435 * @return string filename 426 436 */ 427 437 public function generate_filename( $suffix = null, $dest_path = null, $extension = null ) { 428 438 // $suffix will be appended to the destination filename, just before the extension. 429 if ( !$suffix ) {439 if ( null === $suffix ) { 430 440 $suffix = $this->get_suffix(); 431 441 } 432 442 … … abstract class WP_Image_Editor { 447 457 } 448 458 } 449 459 460 if ( '' === $suffix ) { 461 return trailingslashit( $dir ) . "{$name}.{$new_ext}"; 462 } 463 450 464 return trailingslashit( $dir ) . "{$name}-{$suffix}.{$new_ext}"; 451 465 } 452 466 … … abstract class WP_Image_Editor { 627 641 628 642 return wp_get_default_extension_for_mime_type( $mime_type ); 629 643 } 630 }631 644 645 /** 646 * Set the editor mime type, useful when outputting alternate mime types. 647 * 648 * Track that the mime type is set with the mime type set flag. 649 * 650 * @since 6.0.0 651 * 652 * @param string $mime_type The mime type to set. 653 */ 654 public function set_mime_type( $mime_type ) { 655 $this->mime_type = $mime_type; 656 $this->mime_type_set = true; 657 } 658 659 /** 660 * Reset the mime type to the original file mime type. 661 * 662 * Reset the mime type set flag. 663 */ 664 public function reset_mime_type() { 665 $this->mime_type = wp_get_image_mime( $this->file ); 666 $this->mime_type_set = false; 667 } 668 } -
src/wp-includes/media.php
diff --git src/wp-includes/media.php src/wp-includes/media.php index a0e7ef9c6c..ab72f8fc8c 100644
function wp_filter_content_tags( $content, $context = null ) { 1843 1843 $filtered_image = wp_img_tag_add_loading_attr( $filtered_image, $context ); 1844 1844 } 1845 1845 1846 // Use alternate mime types when specified and available. 1847 if ( $attachment_id > 0 ) { 1848 $filtered_image = wp_image_use_alternate_mime_types( $filtered_image, $context, $attachment_id ); 1849 } 1850 1846 1851 if ( $filtered_image !== $match[0] ) { 1847 1852 $content = str_replace( $match[0], $filtered_image, $content ); 1848 1853 } … … function wp_filter_content_tags( $content, $context = null ) { 1866 1871 return $content; 1867 1872 } 1868 1873 1874 /** 1875 * Use alternate mime type images in the content output when available. 1876 * 1877 * @since 6.0.0 1878 * 1879 * @param string $image The HTML `img` tag where the attribute should be added. 1880 * @param string $context Additional context to pass to the filters. 1881 * @param int $attachment_id The attachment ID. 1882 * @return string Converted `img` tag with `loading` attribute added. 1883 */ 1884 function wp_image_use_alternate_mime_types( $image, $context, $attachment_id ) { 1885 $metadata = wp_get_attachment_metadata( $attachment_id ); 1886 if ( empty( $metadata['file'] ) ) { 1887 return $image; 1888 } 1889 1890 // Only alter images with a `sources` attribute 1891 if ( empty( $metadata['sources'] ) ) { 1892 return $image; 1893 }; 1894 1895 $target_mimes = array( 'image/webp', 'image/jpeg' ); 1896 1897 /** 1898 * Filter the content image mime type output selection and order. 1899 * 1900 * When outputting images in the content, the first mime type available will be used. 1901 * 1902 * @since 6.0.0 1903 * 1904 * @param array $target_mimes The image output mime type and order. Default is array( 'image/webp', 'image/jpeg' ). 1905 * @param int $attachment_id The attachment ID. 1906 * @param string $context Additional context to pass to the filters. 1907 * @return array The filtered output mime type and order. Return an empty array to skip mime type substitution. 1908 */ 1909 $target_mimes = apply_filters( 'wp_content_image_mimes', $target_mimes, $attachment_id, $context ); 1910 1911 if ( false === $target_mimes ) { 1912 return $image; 1913 } 1914 1915 // Find the appropriate size for the provided URL in the first available mime type. 1916 foreach ( $target_mimes as $target_mime ) { 1917 if ( ! isset( $metadata['sources'][ $target_mime ] ) || empty( $metadata['sources'][ $target_mime ]['file'] ) ) { 1918 continue; 1919 } 1920 1921 // Go through each image and replace with the first available mime type version. 1922 foreach ( $metadata['sizes'] as $name => $size_data ) { 1923 // Check if size has a file. 1924 if ( empty( $size_data['file'] ) ) { 1925 continue; 1926 } 1927 1928 // Check if size has a source in the desired mime type. 1929 if ( empty( $size_data['sources'][ $target_mime ]['file'] ) ) { 1930 continue; 1931 } 1932 $target_file = $size_data['sources'][ $target_mime ]['file']; 1933 1934 // Replace the existing output image for this size. 1935 $src_filename = wp_basename( $size_data['file'] ); 1936 1937 // This is the same as the file we want to replace nothing to do here. 1938 if ( $target_file === $src_filename ) { 1939 continue; 1940 } 1941 1942 // Found a match, replace with the new filename and stop searching. 1943 $image = str_replace( $src_filename, $size_data['sources'][ $target_mime ]['file'], $image ); 1944 continue; 1945 } 1946 1947 // Handle full size image replacement. 1948 $src_filename = wp_basename( $metadata['file'] ); 1949 1950 // This is the same as the file we want to replace nothing else to do here. 1951 if ( $metadata['sources'][ $target_mime ]['file'] === $src_filename ) { 1952 return $image; 1953 } 1954 1955 $image = str_replace( $src_filename, $metadata['sources'][ $target_mime ]['file'], $image ); 1956 } 1957 return $image; 1958 } 1959 1869 1960 /** 1870 1961 * Adds `loading` attribute to an `img` HTML tag. 1871 1962 * -
src/wp-includes/post.php
diff --git src/wp-includes/post.php src/wp-includes/post.php index 3906e21f7c..4c1aa0327b 100644
function wp_delete_attachment_files( $post_id, $meta, $backup_sizes, $file ) { 6480 6480 $deleted = false; 6481 6481 } 6482 6482 } 6483 // Check for alternate size mime types in the sizeinfo['sources'] array to delete. 6484 if ( isset( $sizeinfo['sources'] ) && is_array( $sizeinfo['sources'] ) && count( $sizeinfo['sources'] ) > 1 ) { 6485 $sources = $sizeinfo['sources']; 6486 array_shift( $sources ); 6487 foreach ( $sources as $mime => $properties ) { 6488 if ( ! is_array( $properties ) || empty( $properties['file'] ) ) { 6489 continue; 6490 } 6491 6492 $intermediate_file = str_replace( wp_basename( $file ), $properties['file'], $file ); 6493 if ( ! wp_delete_file_from_directory( $intermediate_file, $intermediate_dir ) ) { 6494 $deleted = false; 6495 } 6496 } 6497 } 6483 6498 } 6484 6499 } 6485 6500 … … function wp_delete_attachment_files( $post_id, $meta, $backup_sizes, $file ) { 6499 6514 } 6500 6515 } 6501 6516 6517 // Check for alternate full size mime types in the root sources array to delete. 6518 if ( isset( $meta['sources'] ) && is_array( $meta['sources'] ) ) { 6519 $sources = $meta['sources']; 6520 array_shift( $sources ); 6521 foreach ( $sources as $mime => $properties ) { 6522 if ( ! is_array( $properties ) || empty( $properties['file'] ) ) { 6523 continue; 6524 } 6525 6526 $intermediate_file = str_replace( wp_basename( $file ), $properties['file'], $file ); 6527 if ( ! wp_delete_file_from_directory( $intermediate_file, $intermediate_dir ) ) { 6528 $deleted = false; 6529 } 6530 } 6531 } 6532 6502 6533 if ( is_array( $backup_sizes ) ) { 6503 6534 $del_dir = path_join( $uploadpath['basedir'], dirname( $meta['file'] ) ); 6504 6535 -
tests/phpunit/tests/image/editor.php
diff --git tests/phpunit/data/images/test-image.jpeg tests/phpunit/data/images/test-image.jpeg new file mode 100644 index 0000000000..534aac1d6b Binary files /dev/null and tests/phpunit/data/images/test-image.jpeg differ diff --git tests/phpunit/tests/image/editor.php tests/phpunit/tests/image/editor.php index 487dad0664..06d31e83f1 100644
class Tests_Image_Editor extends WP_Image_UnitTestCase { 361 361 ), 362 362 ); 363 363 } 364 /** 365 * Create the original image mime type when the image is uploaded 366 * 367 * @dataProvider provider_image_with_default_behaviors_during_upload 368 * 369 * @since 6.0.0 370 */ 371 public function it_should_create_the_original_image_mime_type_when_the_image_is_uploaded( $file_location, $expected_mime, $targeted_mime ) { 372 $attachment_id = $this->factory->attachment->create_upload_object( $file_location ); 373 374 $metadata = wp_get_attachment_metadata( $attachment_id ); 375 376 $this->assertIsArray( $metadata ); 377 foreach ( $metadata['sizes'] as $size_name => $properties ) { 378 $this->assertArrayHasKey( 'sources', $properties ); 379 $this->assertIsArray( $properties['sources'] ); 380 $this->assertArrayHasKey( $expected_mime, $properties['sources'] ); 381 $this->assertArrayHasKey( 'filesize', $properties['sources'][ $expected_mime ] ); 382 $this->assertArrayHasKey( 'file', $properties['sources'][ $expected_mime ] ); 383 $this->assertArrayHasKey( $targeted_mime, $properties['sources'] ); 384 $this->assertArrayHasKey( 'filesize', $properties['sources'][ $targeted_mime ] ); 385 $this->assertArrayHasKey( 'file', $properties['sources'][ $targeted_mime ] ); 386 } 387 } 388 389 public function provider_image_with_default_behaviors_during_upload() { 390 yield 'JPEG image' => array( 391 DIR_TESTDATA . '/images/test-image.jpg', 392 'image/jpeg', 393 'image/webp', 394 ); 395 396 yield 'WebP image' => array( 397 DIR_TESTDATA . '/images/webp-lossy.webp', 398 'image/webp', 399 'image/jpeg', 400 ); 401 } 402 403 /** 404 * Not create the sources property if no transform is provided 405 * 406 * @since 6.0.0 407 */ 408 public function it_should_not_create_the_sources_property_if_no_transform_is_provided() { 409 add_filter( 'webp_uploads_supported_image_mime_transforms', '__return_empty_array' ); 410 411 $attachment_id = $this->factory->attachment->create_upload_object( 412 DIR_TESTDATA . '/images/test-image.jpg' 413 ); 414 415 $metadata = wp_get_attachment_metadata( $attachment_id ); 416 417 $this->assertIsArray( $metadata ); 418 foreach ( $metadata['sizes'] as $size_name => $properties ) { 419 $this->assertArrayNotHasKey( 'sources', $properties ); 420 } 421 } 422 423 /** 424 * Create the sources property when no transform is available 425 * 426 * @since 6.0.0 427 */ 428 public function it_should_create_the_sources_property_when_no_transform_is_available() { 429 add_filter( 430 'webp_uploads_supported_image_mime_transforms', 431 function () { 432 return array( 'image/jpeg' => array() ); 433 } 434 ); 435 436 $attachment_id = $this->factory->attachment->create_upload_object( 437 DIR_TESTDATA . '/images/test-image.jpg' 438 ); 439 440 $metadata = wp_get_attachment_metadata( $attachment_id ); 441 442 $this->assertIsArray( $metadata ); 443 foreach ( $metadata['sizes'] as $size_name => $properties ) { 444 $this->assertArrayHasKey( 'sources', $properties ); 445 $this->assertIsArray( $properties['sources'] ); 446 $this->assertArrayHasKey( 'image/jpeg', $properties['sources'] ); 447 $this->assertArrayHasKey( 'filesize', $properties['sources']['image/jpeg'] ); 448 $this->assertArrayHasKey( 'file', $properties['sources']['image/jpeg'] ); 449 $this->assertArrayNotHasKey( 'image/webp', $properties['sources'] ); 450 } 451 } 452 453 /** 454 * Not create the sources property if the mime is not specified on the transforms images 455 * 456 * @since 6.0.0 457 */ 458 public function it_should_not_create_the_sources_property_if_the_mime_is_not_specified_on_the_transforms_images() { 459 add_filter( 460 'webp_uploads_supported_image_mime_transforms', 461 function () { 462 return array( 'image/jpeg' => array() ); 463 } 464 ); 465 466 $attachment_id = $this->factory->attachment->create_upload_object( 467 DIR_TESTDATA . '/images/webp-lossy.webp' 468 ); 469 470 $metadata = wp_get_attachment_metadata( $attachment_id ); 471 472 $this->assertIsArray( $metadata ); 473 foreach ( $metadata['sizes'] as $size_name => $properties ) { 474 $this->assertArrayNotHasKey( 'sources', $properties ); 475 } 476 } 477 478 /** 479 * Create a WebP version with all the required properties 480 * 481 * @since 6.0.0 482 */ 483 public function it_should_create_a_webp_version_with_all_the_required_properties() { 484 $attachment_id = $this->factory->attachment->create_upload_object( 485 DIR_TESTDATA . '/images/test-image.jpg' 486 ); 487 488 $metadata = wp_get_attachment_metadata( $attachment_id ); 489 $this->assertArrayHasKey( 'sources', $metadata['sizes']['thumbnail'] ); 490 $this->assertArrayHasKey( 'image/jpeg', $metadata['sizes']['thumbnail']['sources'] ); 491 $this->assertArrayHasKey( 'filesize', $metadata['sizes']['thumbnail']['sources']['image/jpeg'] ); 492 $this->assertArrayHasKey( 'file', $metadata['sizes']['thumbnail']['sources']['image/jpeg'] ); 493 $this->assertArrayHasKey( 'image/webp', $metadata['sizes']['thumbnail']['sources'] ); 494 $this->assertArrayHasKey( 'filesize', $metadata['sizes']['thumbnail']['sources']['image/webp'] ); 495 $this->assertArrayHasKey( 'file', $metadata['sizes']['thumbnail']['sources']['image/webp'] ); 496 $this->assertStringEndsNotWith( '.jpeg', $metadata['sizes']['thumbnail']['sources']['image/webp']['file'] ); 497 $this->assertStringEndsWith( '.webp', $metadata['sizes']['thumbnail']['sources']['image/webp']['file'] ); 498 } 499 500 /** 501 * Remove `scaled` suffix from the generated filename 502 * 503 * @since 6.0.0 504 */ 505 public function it_should_remove_scaled_suffix_from_the_generated_filename() { 506 // The leafs image is 1080 pixels wide with this filter we ensure a -scaled version is created. 507 add_filter( 508 'big_image_size_threshold', 509 function () { 510 return 850; 511 } 512 ); 513 514 $attachment_id = $this->factory->attachment->create_upload_object( 515 DIR_TESTDATA . '/images/test-image.jpg' 516 ); 517 $metadata = wp_get_attachment_metadata( $attachment_id ); 518 $this->assertStringEndsWith( '-scaled.jpg', get_attached_file( $attachment_id ) ); 519 $this->assertArrayHasKey( 'image/webp', $metadata['sizes']['medium']['sources'] ); 520 $this->assertStringEndsNotWith( '-scaled.webp', $metadata['sizes']['medium']['sources']['image/webp']['file'] ); 521 $this->assertStringEndsWith( '-300x200.webp', $metadata['sizes']['medium']['sources']['image/webp']['file'] ); 522 } 523 524 /** 525 * Remove the generated webp images when the attachment is deleted 526 * 527 * @since 6.0.0 528 */ 529 public function it_should_remove_the_generated_webp_images_when_the_attachment_is_deleted() { 530 // Make sure no editor is available. 531 $attachment_id = $this->factory->attachment->create_upload_object( 532 DIR_TESTDATA . '/images/test-image.jpg' 533 ); 534 535 $file = get_attached_file( $attachment_id, true ); 536 $dirname = pathinfo( $file, PATHINFO_DIRNAME ); 537 538 $this->assertIsString( $file ); 539 $this->assertFileExists( $file ); 540 541 $metadata = wp_get_attachment_metadata( $attachment_id ); 542 $sizes = array( 'thumbnail', 'medium' ); 543 544 foreach ( $sizes as $size_name ) { 545 $this->assertArrayHasKey( 'image/webp', $metadata['sizes'][ $size_name ]['sources'] ); 546 $this->assertArrayHasKey( 'file', $metadata['sizes'][ $size_name ]['sources']['image/webp'] ); 547 $this->assertFileExists( 548 path_join( $dirname, $metadata['sizes'][ $size_name ]['sources']['image/webp']['file'] ) 549 ); 550 } 551 552 wp_delete_attachment( $attachment_id ); 553 554 foreach ( $sizes as $size_name ) { 555 $this->assertFileDoesNotExist( 556 path_join( $dirname, $metadata['sizes'][ $size_name ]['sources']['image/webp']['file'] ) 557 ); 558 } 559 } 560 561 /** 562 * Remove the attached WebP version if the attachment is force deleted but empty trash day is not defined 563 * 564 * @since 6.0.0 565 */ 566 public function it_should_remove_the_attached_webp_version_if_the_attachment_is_force_deleted_but_empty_trash_day_is_not_defined() { 567 // Make sure no editor is available. 568 $attachment_id = $this->factory->attachment->create_upload_object( 569 DIR_TESTDATA . '/images/test-image.jpg' 570 ); 571 572 $file = get_attached_file( $attachment_id, true ); 573 $dirname = pathinfo( $file, PATHINFO_DIRNAME ); 574 575 $this->assertIsString( $file ); 576 $this->assertFileExists( $file ); 577 578 $metadata = wp_get_attachment_metadata( $attachment_id ); 579 580 $this->assertFileExists( 581 path_join( $dirname, $metadata['sizes']['thumbnail']['sources']['image/webp']['file'] ) 582 ); 583 584 wp_delete_attachment( $attachment_id, true ); 585 586 $this->assertFileDoesNotExist( 587 path_join( $dirname, $metadata['sizes']['thumbnail']['sources']['image/webp']['file'] ) 588 ); 589 } 590 591 /** 592 * Remove the WebP version of the image if the image is force deleted and empty trash days is set to zero 593 * 594 * @since 6.0.0 595 */ 596 public function it_should_remove_the_webp_version_of_the_image_if_the_image_is_force_deleted_and_empty_trash_days_is_set_to_zero() { 597 // Make sure no editor is available. 598 $attachment_id = $this->factory->attachment->create_upload_object( 599 DIR_TESTDATA . '/images/test-image.jpg' 600 ); 601 602 $file = get_attached_file( $attachment_id, true ); 603 $dirname = pathinfo( $file, PATHINFO_DIRNAME ); 604 605 $this->assertIsString( $file ); 606 $this->assertFileExists( $file ); 607 608 $metadata = wp_get_attachment_metadata( $attachment_id ); 609 610 $this->assertFileExists( 611 path_join( $dirname, $metadata['sizes']['thumbnail']['sources']['image/webp']['file'] ) 612 ); 613 614 define( 'EMPTY_TRASH_DAYS', 0 ); 615 616 wp_delete_attachment( $attachment_id, true ); 617 618 $this->assertFileDoesNotExist( 619 path_join( $dirname, $metadata['sizes']['thumbnail']['sources']['image/webp']['file'] ) 620 ); 621 } 622 623 /** 624 * Avoid the change of URLs of images that are not part of the media library 625 * 626 * @group webp_uploads_update_image_references 627 * 628 * @since 6.0.0 629 */ 630 public function it_should_avoid_the_change_of_urls_of_images_that_are_not_part_of_the_media_library() { 631 $paragraph = '<p>Donec accumsan, sapien et <img src="https://ia600200.us.archive.org/16/items/SPD-SLRSY-1867/hubblesite_2001_06.jpg">, id commodo nisi sapien et est. Mauris nisl odio, iaculis vitae pellentesque nec.</p>'; 632 633 $this->assertSame( $paragraph, webp_uploads_update_image_references( $paragraph ) ); 634 } 635 636 /** 637 * Avoid replacing not existing attachment IDs 638 * 639 * @group webp_uploads_update_image_references 640 * 641 * @since 6.0.0 642 */ 643 public function it_should_avoid_replacing_not_existing_attachment_i_ds() { 644 $paragraph = '<p>Donec accumsan, sapien et <img class="wp-image-0" src="https://ia600200.us.archive.org/16/items/SPD-SLRSY-1867/hubblesite_2001_06.jpg">, id commodo nisi sapien et est. Mauris nisl odio, iaculis vitae pellentesque nec.</p>'; 645 646 $this->assertSame( $paragraph, webp_uploads_update_image_references( $paragraph ) ); 647 } 648 649 /** 650 * Prevent replacing a WebP image 651 * 652 * @group webp_uploads_update_image_references 653 * 654 * @since 6.0.0 655 */ 656 public function it_should_prevent_replacing_a_webp_image() { 657 $attachment_id = $this->factory->attachment->create_upload_object( 658 DIR_TESTDATA . '/images/webp-lossy.webp' 659 ); 660 661 $tag = wp_get_attachment_image( $attachment_id, 'medium', false, array( 'class' => "wp-image-{$attachment_id}" ) ); 662 663 $this->assertSame( $tag, webp_uploads_img_tag_update_mime_type( $tag, 'the_content', $attachment_id ) ); 664 } 665 666 /** 667 * Prevent replacing a jpg image if the image does not have the target class name 668 * 669 * @since 6.0.0 670 */ 671 public function it_should_prevent_replacing_a_jpg_image_if_the_image_does_not_have_the_target_class_name() { 672 $attachment_id = $this->factory->attachment->create_upload_object( 673 DIR_TESTDATA . '/images/test-image.jpg' 674 ); 675 676 $tag = wp_get_attachment_image( $attachment_id, 'medium' ); 677 678 $this->assertSame( $tag, webp_uploads_update_image_references( $tag ) ); 679 } 680 681 /** 682 * Replace the references to a JPG image to a WebP version 683 * 684 * @dataProvider provider_replace_images_with_different_extensions 685 * @group webp_uploads_update_image_references 686 * 687 * @since 6.0.0 688 */ 689 public function it_should_replace_the_references_to_a_jpg_image_to_a_webp_version( $image_path ) { 690 $attachment_id = $this->factory->attachment->create_upload_object( $image_path ); 691 692 $tag = wp_get_attachment_image( $attachment_id, 'medium', false, array( 'class' => "wp-image-{$attachment_id}" ) ); 693 $expected_tag = $tag; 694 $metadata = wp_get_attachment_metadata( $attachment_id ); 695 foreach ( $metadata['sizes'] as $size => $properties ) { 696 $expected_tag = str_replace( $properties['sources']['image/jpeg']['file'], $properties['sources']['image/webp']['file'], $expected_tag ); 697 } 698 699 $this->assertNotEmpty( $expected_tag ); 700 $this->assertNotSame( $tag, $expected_tag ); 701 $this->assertSame( $expected_tag, webp_uploads_img_tag_update_mime_type( $tag, 'the_content', $attachment_id ) ); 702 } 703 704 public function provider_replace_images_with_different_extensions() { 705 yield 'An image with a .jpg extension' => array( DIR_TESTDATA . '/images/test-image.jpg' ); 706 yield 'An image with a .jpeg extension' => array( DIR_TESTDATA . '/images/test-image.jpeg' ); 707 } 708 709 /** 710 * Contain the full image size from the original mime 711 * 712 * @group webp_uploads_update_image_references 713 * 714 * @since 6.0.0 715 */ 716 public function it_should_contain_the_full_image_size_from_the_original_mime() { 717 $attachment_id = $this->factory->attachment->create_upload_object( 718 DIR_TESTDATA . '/images/test-image.jpg' 719 ); 720 721 $tag = wp_get_attachment_image( $attachment_id, 'full', false, array( 'class' => "wp-image-{$attachment_id}" ) ); 722 723 $expected = array( 724 'ext' => 'jpg', 725 'type' => 'image/jpeg', 726 ); 727 $this->assertSame( $expected, wp_check_filetype( get_attached_file( $attachment_id ) ) ); 728 $this->assertContains( wp_basename( get_attached_file( $attachment_id ) ), webp_uploads_img_tag_update_mime_type( $tag, 'the_content', $attachment_id ) ); 729 } 730 731 /** 732 * Prevent replacing an image with no available sources 733 * 734 * @group webp_uploads_update_image_references 735 * 736 * @since 6.0.0 737 */ 738 public function it_should_prevent_replacing_an_image_with_no_available_sources() { 739 add_filter( 'webp_uploads_supported_image_mime_transforms', '__return_empty_array' ); 740 741 $attachment_id = $this->factory->attachment->create_upload_object( DIR_TESTDATA . '/images/test-image.jpg' ); 742 743 $tag = wp_get_attachment_image( $attachment_id, 'full', false, array( 'class' => "wp-image-{$attachment_id}" ) ); 744 $this->assertSame( $tag, webp_uploads_img_tag_update_mime_type( $tag, 'the_content', $attachment_id ) ); 745 } 746 747 /** 748 * Prevent update not supported images with no available sources 749 * 750 * @dataProvider data_provider_not_supported_webp_images 751 * @group webp_uploads_update_image_references 752 * 753 * @since 6.0.0 754 */ 755 public function it_should_prevent_update_not_supported_images_with_no_available_sources( $image_path ) { 756 $attachment_id = $this->factory->attachment->create_upload_object( $image_path ); 757 758 $this->assertIsNumeric( $attachment_id ); 759 $tag = wp_get_attachment_image( $attachment_id, 'full', false, array( 'class' => "wp-image-{$attachment_id}" ) ); 760 761 $this->assertSame( $tag, webp_uploads_img_tag_update_mime_type( $tag, 'the_content', $attachment_id ) ); 762 } 763 764 public function data_provider_not_supported_webp_images() { 765 yield 'PNG image' => array( DIR_TESTDATA . '/images/test-image.png' ); 766 yield 'GIFT image' => array( DIR_TESTDATA . '/images/test-image.gif' ); 767 } 768 769 364 770 365 771 } -
tests/phpunit/tests/image/functions.php
diff --git tests/phpunit/tests/image/functions.php tests/phpunit/tests/image/functions.php index c02862b3e7..b9c96c8721 100644
class Tests_Image_Functions extends WP_UnitTestCase { 460 460 $this->markTestSkipped( 'Rendering PDFs is not supported on this system.' ); 461 461 } 462 462 463 // Use legacy JPEG output. 464 add_filter( 'wp_upload_image_mime_transforms', '__return_empty_array' ); 465 463 466 $orig_file = DIR_TESTDATA . '/images/wordpress-gsoc-flyer.pdf'; 464 467 $test_file = get_temp_dir() . 'wordpress-gsoc-flyer.pdf'; 465 468 copy( $orig_file, $test_file ); … … class Tests_Image_Functions extends WP_UnitTestCase { 480 483 $this->assertNotEmpty( $attachment_id ); 481 484 482 485 $temp_dir = get_temp_dir(); 483 484 486 $metadata = wp_generate_attachment_metadata( $attachment_id, $test_file ); 485 487 486 488 $expected = array( … … class Tests_Image_Functions extends WP_UnitTestCase { 498 500 'height' => 300, 499 501 'mime-type' => 'image/jpeg', 500 502 'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-232x300.jpg' ), 503 'sources' => array( 504 'image/jpeg' => array( 505 'file' => 'wordpress-gsoc-flyer-pdf-232x300.jpg', 506 'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-232x300.jpg' ), 507 508 ), 509 ), 501 510 ), 502 511 'large' => array( 503 512 'file' => 'wordpress-gsoc-flyer-pdf-791x1024.jpg', … … class Tests_Image_Functions extends WP_UnitTestCase { 505 514 'height' => 1024, 506 515 'mime-type' => 'image/jpeg', 507 516 'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-791x1024.jpg' ), 517 'sources' => array( 518 'image/jpeg' => array( 519 'file' => 'wordpress-gsoc-flyer-pdf-791x1024.jpg', 520 'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-791x1024.jpg' ), 521 ), 522 ), 508 523 ), 509 524 'thumbnail' => array( 510 525 'file' => 'wordpress-gsoc-flyer-pdf-116x150.jpg', … … class Tests_Image_Functions extends WP_UnitTestCase { 512 527 'height' => 150, 513 528 'mime-type' => 'image/jpeg', 514 529 'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-116x150.jpg' ), 530 'sources' => array( 531 'image/jpeg' => array( 532 'file' => 'wordpress-gsoc-flyer-pdf-116x150.jpg', 533 'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-116x150.jpg' ), 534 ), 535 ), 515 536 ), 516 537 ), 517 538 'filesize' => wp_filesize( $test_file ), … … class Tests_Image_Functions extends WP_UnitTestCase { 523 544 foreach ( $metadata['sizes'] as $size ) { 524 545 unlink( $temp_dir . $size['file'] ); 525 546 } 547 remove_filter( 'wp_upload_image_mime_transforms', '__return_empty_array' ); 526 548 } 527 549 528 550 /** … … class Tests_Image_Functions extends WP_UnitTestCase { 537 559 538 560 update_option( 'medium_crop', 1 ); 539 561 562 // Use legacy JPEG output. 563 add_filter( 'wp_upload_image_mime_transforms', '__return_empty_array' ); 564 540 565 $orig_file = DIR_TESTDATA . '/images/wordpress-gsoc-flyer.pdf'; 541 566 $test_file = get_temp_dir() . 'wordpress-gsoc-flyer.pdf'; 542 567 copy( $orig_file, $test_file ); … … class Tests_Image_Functions extends WP_UnitTestCase { 557 582 $this->assertNotEmpty( $attachment_id ); 558 583 559 584 $temp_dir = get_temp_dir(); 560 561 585 $metadata = wp_generate_attachment_metadata( $attachment_id, $test_file ); 562 586 563 587 $expected = array( … … class Tests_Image_Functions extends WP_UnitTestCase { 575 599 'height' => 300, 576 600 'mime-type' => 'image/jpeg', 577 601 'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-300x300.jpg' ), 602 'sources' => array( 603 'image/jpeg' => array( 604 'file' => 'wordpress-gsoc-flyer-pdf-300x300.jpg', 605 'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-300x300.jpg' ), 606 ), 607 ), 578 608 ), 579 609 'large' => array( 580 610 'file' => 'wordpress-gsoc-flyer-pdf-791x1024.jpg', … … class Tests_Image_Functions extends WP_UnitTestCase { 582 612 'height' => 1024, 583 613 'mime-type' => 'image/jpeg', 584 614 'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-791x1024.jpg' ), 615 'sources' => array( 616 'image/jpeg' => array( 617 'file' => 'wordpress-gsoc-flyer-pdf-791x1024.jpg', 618 'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-791x1024.jpg' ), 619 ), 620 ), 621 585 622 ), 586 623 'thumbnail' => array( 587 624 'file' => 'wordpress-gsoc-flyer-pdf-116x150.jpg', … … class Tests_Image_Functions extends WP_UnitTestCase { 589 626 'height' => 150, 590 627 'mime-type' => 'image/jpeg', 591 628 'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-116x150.jpg' ), 629 'sources' => array( 630 'image/jpeg' => array( 631 'file' => 'wordpress-gsoc-flyer-pdf-116x150.jpg', 632 'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-116x150.jpg' ), 633 ), 634 ), 592 635 ), 593 636 ), 594 637 'filesize' => wp_filesize( $test_file ), … … class Tests_Image_Functions extends WP_UnitTestCase { 600 643 foreach ( $metadata['sizes'] as $size ) { 601 644 unlink( $temp_dir . $size['file'] ); 602 645 } 646 remove_filter( 'wp_upload_image_mime_transforms', '__return_empty_array' ); 647 603 648 } 604 649 605 650 /** … … class Tests_Image_Functions extends WP_UnitTestCase { 610 655 $this->markTestSkipped( 'Rendering PDFs is not supported on this system.' ); 611 656 } 612 657 658 // Use legacy JPEG output. 659 add_filter( 'wp_upload_image_mime_transforms', '__return_empty_array' ); 660 613 661 $orig_file = DIR_TESTDATA . '/images/wordpress-gsoc-flyer.pdf'; 614 662 $test_file = get_temp_dir() . 'wordpress-gsoc-flyer.pdf'; 615 663 copy( $orig_file, $test_file ); … … class Tests_Image_Functions extends WP_UnitTestCase { 642 690 'height' => 100, 643 691 'mime-type' => 'image/jpeg', 644 692 'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-77x100.jpg' ), 693 'sources' => array( 694 'image/jpeg' => array( 695 'file' => 'wordpress-gsoc-flyer-pdf-77x100.jpg', 696 'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-77x100.jpg' ), 697 ), 698 ), 645 699 ); 646 700 647 701 // Different environments produce slightly different filesize results. … … class Tests_Image_Functions extends WP_UnitTestCase { 657 711 foreach ( $metadata['sizes'] as $size ) { 658 712 unlink( $temp_dir . $size['file'] ); 659 713 } 714 remove_filter( 'wp_upload_image_mime_transforms', '__return_empty_array' ); 660 715 } 661 716 662 717 public function filter_fallback_intermediate_image_sizes( $fallback_sizes, $metadata ) { -
tests/phpunit/tests/media.php
diff --git tests/phpunit/tests/media.php tests/phpunit/tests/media.php index 5d92d9718b..2e9e2173bc 100644
EOF; 2252 2252 // Do not add width, height, and loading. 2253 2253 add_filter( 'wp_img_tag_add_width_and_height_attr', '__return_false' ); 2254 2254 add_filter( 'wp_img_tag_add_loading_attr', '__return_false' ); 2255 add_filter( 'wp_content_image_mimes', '__return_empty_array' ); 2255 2256 2256 2257 $this->assertSame( $content_filtered, wp_filter_content_tags( $content_unfiltered ) ); 2257 2258 2258 2259 remove_filter( 'wp_img_tag_add_width_and_height_attr', '__return_false' ); 2259 2260 remove_filter( 'wp_img_tag_add_loading_attr', '__return_false' ); 2261 remove_filter( 'wp_content_image_mimes', '__return_empty_array' ); 2262 2260 2263 } 2261 2264 2262 2265 /** … … EOF; 2288 2291 $img = get_image_tag( self::$large_id, '', '', '', 'medium' ); 2289 2292 $img = wp_img_tag_add_loading_attr( $img, 'test' ); 2290 2293 $img = preg_replace( '|<img ([^>]+) />|', '<img $1 ' . 'srcset="image2x.jpg 2x" />', $img ); 2294 add_filter( 'wp_content_image_mimes', '__return_empty_array' ); 2291 2295 2292 2296 // The content filter should return the image unchanged. 2293 2297 $this->assertSame( $img, wp_filter_content_tags( $img ) ); 2298 2299 remove_filter( 'wp_content_image_mimes', '__return_empty_array' ); 2294 2300 } 2295 2301 2296 2302 /** … … EOF; 2343 2349 * @requires function imagejpeg 2344 2350 */ 2345 2351 public function test_wp_filter_content_tags_schemes() { 2352 add_filter( 'wp_content_image_mimes', '__return_empty_array' ); 2346 2353 $image_meta = wp_get_attachment_metadata( self::$large_id ); 2347 2354 $size_array = $this->get_image_size_array_from_meta( $image_meta, 'medium' ); 2348 2355 … … EOF; 2387 2394 $actual = wp_filter_content_tags( $unfiltered ); 2388 2395 2389 2396 $this->assertSame( $expected, $actual ); 2397 remove_filter( 'wp_content_image_mimes', '__return_empty_array' ); 2390 2398 } 2391 2399 2392 2400 /** … … EOF; 2804 2812 * @requires function imagejpeg 2805 2813 */ 2806 2814 public function test_wp_filter_content_tags_width_height() { 2815 add_filter( 'wp_content_image_mimes', '__return_empty_array' ); 2816 2807 2817 $image_meta = wp_get_attachment_metadata( self::$large_id ); 2808 2818 $size_array = $this->get_image_size_array_from_meta( $image_meta, 'medium' ); 2809 2819 … … EOF; 2837 2847 // Do not add loading, srcset, and sizes. 2838 2848 add_filter( 'wp_img_tag_add_loading_attr', '__return_false' ); 2839 2849 add_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' ); 2850 add_filter( 'wp_content_image_mimes', '__return_empty_array' ); 2840 2851 2841 2852 $this->assertSame( $content_filtered, wp_filter_content_tags( $content_unfiltered ) ); 2842 2853 2843 2854 remove_filter( 'wp_img_tag_add_loading_attr', '__return_false' ); 2844 2855 remove_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' ); 2856 remove_filter( 'wp_content_image_mimes', '__return_empty_array' ); 2845 2857 } 2846 2858 2847 2859 /** … … EOF; 2895 2907 // Do not add width, height, srcset, and sizes. 2896 2908 add_filter( 'wp_img_tag_add_width_and_height_attr', '__return_false' ); 2897 2909 add_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' ); 2910 add_filter( 'wp_content_image_mimes', '__return_empty_array' ); 2898 2911 2899 2912 $this->assertSame( $content_filtered, wp_filter_content_tags( $content_unfiltered ) ); 2900 2913 2901 2914 remove_filter( 'wp_img_tag_add_width_and_height_attr', '__return_false' ); 2902 2915 remove_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' ); 2916 remove_filter( 'wp_content_image_mimes', '__return_empty_array' ); 2903 2917 } 2904 2918 2905 2919 /** … … EOF; 2927 2941 // Enable globally for all tags. 2928 2942 add_filter( 'wp_lazy_loading_enabled', '__return_true' ); 2929 2943 2944 add_filter( 'wp_content_image_mimes', '__return_empty_array' ); 2945 2930 2946 $this->assertSame( $content_filtered, wp_filter_content_tags( $content_unfiltered ) ); 2931 2947 remove_filter( 'wp_lazy_loading_enabled', '__return_true' ); 2932 2948 remove_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' ); 2949 remove_filter( 'wp_content_image_mimes', '__return_empty_array' ); 2950 2933 2951 } 2934 2952 2935 2953 /** … … EOF; 2953 2971 // Disable globally for all tags. 2954 2972 add_filter( 'wp_lazy_loading_enabled', '__return_false' ); 2955 2973 2974 add_filter( 'wp_content_image_mimes', '__return_empty_array' ); 2975 2956 2976 $this->assertSame( $content, wp_filter_content_tags( $content ) ); 2957 2977 remove_filter( 'wp_lazy_loading_enabled', '__return_false' ); 2958 2978 remove_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' ); 2979 remove_filter( 'wp_content_image_mimes', '__return_empty_array' ); 2959 2980 } 2960 2981 2961 2982 /** … … EOF; 3381 3402 */ 3382 3403 function test_wp_filter_content_tags_with_wp_get_loading_attr_default() { 3383 3404 global $wp_query, $wp_the_query; 3405 add_filter( 'wp_content_image_mimes', '__return_empty_array' ); 3384 3406 3385 3407 $img1 = get_image_tag( self::$large_id, '', '', '', 'large' ); 3386 3408 $iframe1 = '<iframe src="https://www.example.com" width="640" height="360"></iframe>'; … … EOF; 3415 3437 $content_filtered = wp_filter_content_tags( $content_unfiltered, 'the_content' ); 3416 3438 remove_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' ); 3417 3439 } 3440 remove_filter( 'wp_content_image_mimes', '__return_empty_array' ); 3418 3441 3419 3442 // After filtering, the first image should not be lazy-loaded while the other ones should be. 3420 3443 $this->assertSame( $content_expected, $content_filtered );