EWWW Image Optimizer - Version 6.5.2

Version Description

  • added: automatic optimization for Crop Thumbnails plugin
  • added: filters to adjust sharpening parameters for core WP (ImageMagick) image resizing
  • changed: Easy IO WebP quality can be defined separately from the JPG quality used for resizing operations
  • fixed: Picture WebP rewriting disabled on embeds
  • fixed: Lazy Load integration with WooCommerce Product Recommendations handling AJAX output incorrectly
  • fixed: PHP notice when checking for presence of mod_rewrite/mod_headers
Download this release

Release Info

Developer nosilver4u
Plugin Icon 128x128 EWWW Image Optimizer
Version 6.5.2
Comparing to
See all releases

Code changes from version 6.5.1 to 6.5.2

bulk.php CHANGED
@@ -2033,6 +2033,10 @@ function ewww_image_optimizer_bulk_loop( $hook = '', $delay = 0 ) {
2033
  // Do metadata update after full-size is processed, usually because of conversion or resizing.
2034
  if ( 'full' === $image->resize && $image->attachment_id ) {
2035
  if ( $meta && is_array( $meta ) ) {
 
 
 
 
2036
  $meta_saved = wp_update_attachment_metadata( $image->attachment_id, $meta );
2037
  if ( ! $meta_saved ) {
2038
  ewwwio_debug_message( 'failed to save meta' );
@@ -2154,6 +2158,8 @@ function ewww_image_optimizer_bulk_update_meta() {
2154
  $attachment_id = (int) $_REQUEST['attachment_id'];
2155
  ewwwio_debug_message( "saving attachment meta for $attachment_id" );
2156
  $meta = wp_get_attachment_metadata( $attachment_id );
 
 
2157
  if ( class_exists( 'S3_Uploads' ) || class_exists( 'S3_Uploads\Plugin' ) ) {
2158
  ewwwio_debug_message( 're-uploading to S3(_Uploads)' );
2159
  ewww_image_optimizer_remote_push( $meta, $attachment_id );
2033
  // Do metadata update after full-size is processed, usually because of conversion or resizing.
2034
  if ( 'full' === $image->resize && $image->attachment_id ) {
2035
  if ( $meta && is_array( $meta ) ) {
2036
+ clearstatcache();
2037
+ if ( ! empty( $image->file ) && is_file( $image->file ) ) {
2038
+ $meta['filesize'] = filesize( $image->file );
2039
+ }
2040
  $meta_saved = wp_update_attachment_metadata( $image->attachment_id, $meta );
2041
  if ( ! $meta_saved ) {
2042
  ewwwio_debug_message( 'failed to save meta' );
2158
  $attachment_id = (int) $_REQUEST['attachment_id'];
2159
  ewwwio_debug_message( "saving attachment meta for $attachment_id" );
2160
  $meta = wp_get_attachment_metadata( $attachment_id );
2161
+ $meta = ewww_image_optimizer_update_filesize_metadata( $meta, $attachment_id );
2162
+ remove_filter( 'wp_update_attachment_metadata', 'ewww_image_optimizer_update_filesize_metadata', 9 );
2163
  if ( class_exists( 'S3_Uploads' ) || class_exists( 'S3_Uploads\Plugin' ) ) {
2164
  ewwwio_debug_message( 're-uploading to S3(_Uploads)' );
2165
  ewww_image_optimizer_remote_push( $meta, $attachment_id );
changelog.txt CHANGED
@@ -1,3 +1,11 @@
 
 
 
 
 
 
 
 
1
  = 6.5.1 =
2
  * fixed: LQIP option not available on sub-domain multisite install unless Easy IO is active on site 1
3
  * fixed: API quota function doesn't handle expired status correctly
1
+ = 6.5.2 =
2
+ * added: automatic optimization for Crop Thumbnails plugin
3
+ * added: filters to adjust sharpening parameters for core WP (ImageMagick) image resizing
4
+ * changed: Easy IO WebP quality can be defined separately from the JPG quality used for resizing operations
5
+ * fixed: Picture WebP rewriting disabled on embeds
6
+ * fixed: Lazy Load integration with WooCommerce Product Recommendations handling AJAX output incorrectly
7
+ * fixed: PHP notice when checking for presence of mod_rewrite/mod_headers
8
+
9
  = 6.5.1 =
10
  * fixed: LQIP option not available on sub-domain multisite install unless Easy IO is active on site 1
11
  * fixed: API quota function doesn't handle expired status correctly
classes/class-eio-lazy-load.php CHANGED
@@ -121,7 +121,7 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
121
  }
122
 
123
  add_filter( 'vc_get_vc_grid_data_response', array( $this, 'filter_page_output' ) );
124
- add_filter( 'woocommerce_prl_ajax_response_html', array( $this, 'filter_page_output' ) );
125
 
126
  // Filter for FacetWP JSON responses.
127
  add_filter( 'facetwp_render_output', array( $this, 'filter_facetwp_json_output' ) );
@@ -789,6 +789,40 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
789
  return $element;
790
  }
791
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
792
  /**
793
  * Parse template data from FacetWP that will be included in JSON response.
794
  * https://facetwp.com/documentation/developers/output/facetwp_render_output/
121
  }
122
 
123
  add_filter( 'vc_get_vc_grid_data_response', array( $this, 'filter_page_output' ) );
124
+ add_filter( 'woocommerce_prl_ajax_response_html', array( $this, 'filter_html_array' ) );
125
 
126
  // Filter for FacetWP JSON responses.
127
  add_filter( 'facetwp_render_output', array( $this, 'filter_facetwp_json_output' ) );
789
  return $element;
790
  }
791
 
792
+ /**
793
+ * Parse an array of potential HTML strings.
794
+ *
795
+ * @param array $output An array of HTML strings.
796
+ * @return array The output data with lazy loaded images.
797
+ */
798
+ function filter_html_array( $output ) {
799
+ $this->debug_message( '<b>' . __METHOD__ . '()</b>' );
800
+ if ( $this->is_iterable( $output ) ) {
801
+ foreach ( $output as $index => $html ) {
802
+ if ( is_array( $html ) ) {
803
+ $output[ $index ] = $this->filter_html_array( $html );
804
+ }
805
+ if ( ! is_string( $html ) ) {
806
+ $this->debug_message( "skipped $index, not a string" );
807
+ continue;
808
+ }
809
+ if ( strlen( $html ) < 100 ) {
810
+ $this->debug_message( "skipped $index, too short? $html" );
811
+ continue;
812
+ }
813
+ if ( false === strpos( $html, '<img ' ) ) {
814
+ $this->debug_message( "skipped $index, no img tags found" );
815
+ continue;
816
+ }
817
+ $new_html = $this->filter_page_output( $html );
818
+ if ( $new_html !== $html ) {
819
+ $output[ $index ] = $new_html;
820
+ }
821
+ }
822
+ }
823
+ return $output;
824
+ }
825
+
826
  /**
827
  * Parse template data from FacetWP that will be included in JSON response.
828
  * https://facetwp.com/documentation/developers/output/facetwp_render_output/
classes/class-eio-picture-webp.php CHANGED
@@ -180,10 +180,6 @@ class EIO_Picture_Webp extends EIO_Page_Parser {
180
  if ( $this->is_amp() ) {
181
  return false;
182
  }
183
- if ( is_embed() ) {
184
- $this->debug_message( 'is_embed' );
185
- return false;
186
- }
187
  if ( is_feed() ) {
188
  $this->debug_message( 'is_feed' );
189
  return false;
180
  if ( $this->is_amp() ) {
181
  return false;
182
  }
 
 
 
 
183
  if ( is_feed() ) {
184
  $this->debug_message( 'is_feed' );
185
  return false;
classes/class-ewwwio-imagick-editor.php CHANGED
@@ -344,6 +344,153 @@ if ( class_exists( 'WP_Thumb_Image_Editor_Imagick' ) ) {
344
  return $resize_result;
345
  }
346
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
347
  /**
348
  * Resize multiple images from a single source.
349
  *
344
  return $resize_result;
345
  }
346
 
347
+ /**
348
+ * Efficiently resize the current image
349
+ *
350
+ * This is a WordPress specific implementation of Imagick::thumbnailImage(),
351
+ * which resizes an image to given dimensions and removes any associated profiles.
352
+ *
353
+ * @since 4.5.0
354
+ *
355
+ * @param int $dst_w The destination width.
356
+ * @param int $dst_h The destination height.
357
+ * @param string $filter_name Optional. The Imagick filter to use when resizing. Default 'FILTER_TRIANGLE'.
358
+ * @param bool $strip_meta Optional. Strip all profiles, excluding color profiles, from the image. Default true.
359
+ * @return void|WP_Error
360
+ */
361
+ protected function thumbnail_image( $dst_w, $dst_h, $filter_name = 'FILTER_TRIANGLE', $strip_meta = true ) {
362
+ ewwwio_debug_message( '<b>wp_image_editor_imagick::' . __FUNCTION__ . '()</b>' );
363
+ $allowed_filters = array(
364
+ 'FILTER_POINT',
365
+ 'FILTER_BOX',
366
+ 'FILTER_TRIANGLE',
367
+ 'FILTER_HERMITE',
368
+ 'FILTER_HANNING',
369
+ 'FILTER_HAMMING',
370
+ 'FILTER_BLACKMAN',
371
+ 'FILTER_GAUSSIAN',
372
+ 'FILTER_QUADRATIC',
373
+ 'FILTER_CUBIC',
374
+ 'FILTER_CATROM',
375
+ 'FILTER_MITCHELL',
376
+ 'FILTER_LANCZOS',
377
+ 'FILTER_BESSEL',
378
+ 'FILTER_SINC',
379
+ );
380
+
381
+ $filter_name = apply_filters( 'eio_image_resize_filter', $filter_name, $dst_w, $dst_h );
382
+ ewwwio_debug_message( "using resize filter $filter_name" );
383
+ /**
384
+ * Set the filter value if '$filter_name' name is in the allowed list and the related
385
+ * Imagick constant is defined or fall back to the default filter.
386
+ */
387
+ if ( in_array( $filter_name, $allowed_filters, true ) && defined( 'Imagick::' . $filter_name ) ) {
388
+ $filter = constant( 'Imagick::' . $filter_name );
389
+ } else {
390
+ $filter = defined( 'Imagick::FILTER_TRIANGLE' ) ? Imagick::FILTER_TRIANGLE : false;
391
+ }
392
+
393
+ /**
394
+ * Filters whether to strip metadata from images when they're resized.
395
+ *
396
+ * This filter only applies when resizing using the Imagick editor since GD
397
+ * always strips profiles by default.
398
+ *
399
+ * @since 4.5.0
400
+ *
401
+ * @param bool $strip_meta Whether to strip image metadata during resizing. Default true.
402
+ */
403
+ if ( apply_filters( 'image_strip_meta', $strip_meta ) ) {
404
+ $this->strip_meta(); // Fail silently if not supported.
405
+ }
406
+
407
+ try {
408
+ /*
409
+ * To be more efficient, resample large images to 5x the destination size before resizing
410
+ * whenever the output size is less that 1/3 of the original image size (1/3^2 ~= .111),
411
+ * unless we would be resampling to a scale smaller than 128x128.
412
+ */
413
+ if ( is_callable( array( $this->image, 'sampleImage' ) ) ) {
414
+ $resize_ratio = ( $dst_w / $this->size['width'] ) * ( $dst_h / $this->size['height'] );
415
+ $sample_factor = 5;
416
+
417
+ if ( $resize_ratio < .111 && ( $dst_w * $sample_factor > 128 && $dst_h * $sample_factor > 128 ) ) {
418
+ $this->image->sampleImage( $dst_w * $sample_factor, $dst_h * $sample_factor );
419
+ }
420
+ }
421
+
422
+ /*
423
+ * Use resizeImage() when it's available and a valid filter value is set.
424
+ * Otherwise, fall back to the scaleImage() method for resizing, which
425
+ * results in better image quality over resizeImage() with default filter
426
+ * settings and retains backward compatibility with pre 4.5 functionality.
427
+ */
428
+ if ( is_callable( array( $this->image, 'resizeImage' ) ) && $filter ) {
429
+ $this->image->setOption( 'filter:support', '2.0' );
430
+ $this->image->resizeImage( $dst_w, $dst_h, $filter, 1 );
431
+ } else {
432
+ $this->image->scaleImage( $dst_w, $dst_h );
433
+ }
434
+
435
+ // Set appropriate quality settings after resizing.
436
+ if ( 'image/jpeg' === $this->mime_type ) {
437
+ if ( apply_filters( 'eio_use_adaptive_sharpen', false, $dst_w, $dst_h ) && is_callable( array( $this->image, 'adaptiveSharpenImage' ) ) ) {
438
+ $radius = apply_filters( 'eio_adaptive_sharpen_radius', 0, $dst_w, $dst_h );
439
+ $sigma = apply_filters( 'eio_adaptive_sharpen_sigma', 1, $dst_w, $dst_h );
440
+ ewwwio_debug_message( "running adaptiveSharpenImage( $radius, $sigma )" );
441
+ $this->image->adaptiveSharpenImage( $radius, $sigma );
442
+ } elseif ( is_callable( array( $this->image, 'unsharpMaskImage' ) ) ) {
443
+ $radius = apply_filters( 'eio_sharpen_radius', 0.25, $dst_w, $dst_h );
444
+ $sigma = apply_filters( 'eio_sharpen_sigma', 0.25, $dst_w, $dst_h );
445
+ $amount = apply_filters( 'eio_sharpen_amount', 8, $dst_w, $dst_h );
446
+ $threshold = apply_filters( 'eio_sharpen_threshold', 0.065, $dst_w, $dst_h );
447
+ ewwwio_debug_message( "running unsharpMaskImage( $radius, $sigma, $amount, $threshold )" );
448
+ $this->image->unsharpMaskImage( $radius, $sigma, $amount, $threshold );
449
+ // $this->image->unsharpMaskImage( 0.25, 0.25, 8, 0.065 ); // core WP defaults.
450
+ // $this->image->unsharpMaskImage( 0, 0.4, 1.2, 0.01 ); // values from the Better Images plugin.
451
+ }
452
+
453
+ $this->image->setOption( 'jpeg:fancy-upsampling', 'off' );
454
+ }
455
+
456
+ if ( 'image/png' === $this->mime_type ) {
457
+ $this->image->setOption( 'png:compression-filter', '5' );
458
+ $this->image->setOption( 'png:compression-level', '9' );
459
+ $this->image->setOption( 'png:compression-strategy', '1' );
460
+ $this->image->setOption( 'png:exclude-chunk', 'all' );
461
+ }
462
+
463
+ /*
464
+ * If alpha channel is not defined, set it opaque.
465
+ *
466
+ * Note that Imagick::getImageAlphaChannel() is only available if Imagick
467
+ * has been compiled against ImageMagick version 6.4.0 or newer.
468
+ */
469
+ if ( is_callable( array( $this->image, 'getImageAlphaChannel' ) )
470
+ && is_callable( array( $this->image, 'setImageAlphaChannel' ) )
471
+ && defined( 'Imagick::ALPHACHANNEL_UNDEFINED' )
472
+ && defined( 'Imagick::ALPHACHANNEL_OPAQUE' )
473
+ ) {
474
+ if ( $this->image->getImageAlphaChannel() === Imagick::ALPHACHANNEL_UNDEFINED ) {
475
+ $this->image->setImageAlphaChannel( Imagick::ALPHACHANNEL_OPAQUE );
476
+ }
477
+ }
478
+
479
+ // Limit the bit depth of resized images to 8 bits per channel.
480
+ if ( is_callable( array( $this->image, 'getImageDepth' ) ) && is_callable( array( $this->image, 'setImageDepth' ) ) ) {
481
+ if ( 8 < $this->image->getImageDepth() ) {
482
+ $this->image->setImageDepth( 8 );
483
+ }
484
+ }
485
+
486
+ if ( is_callable( array( $this->image, 'setInterlaceScheme' ) ) && defined( 'Imagick::INTERLACE_NO' ) ) {
487
+ $this->image->setInterlaceScheme( Imagick::INTERLACE_NO );
488
+ }
489
+ } catch ( Exception $e ) {
490
+ return new WP_Error( 'image_resize_error', $e->getMessage() );
491
+ }
492
+ }
493
+
494
  /**
495
  * Resize multiple images from a single source.
496
  *
classes/class-exactdn.php CHANGED
@@ -1506,10 +1506,10 @@ if ( ! class_exists( 'ExactDN' ) ) {
1506
  // Replace original tag with modified version.
1507
  $content = str_replace( $images['img_tag'][ $index ], $new_tag, $content );
1508
  }
1509
- }
1510
- }
1511
- } // End foreach().
1512
- } // End if();
1513
 
1514
  // Process <a> elements in the page for image URLs.
1515
  $content = $this->filter_image_links( $content );
@@ -3319,6 +3319,7 @@ if ( ! class_exists( 'ExactDN' ) ) {
3319
 
3320
  $jpg_quality = apply_filters( 'jpeg_quality', null, 'image_resize' );
3321
  $webp_quality = apply_filters( 'webp_quality', 75, 'image/webp' );
 
3322
 
3323
  $more_args = array();
3324
  if ( false === strpos( $image_url, 'strip=all' ) && $this->get_option( $this->prefix . 'metadata_remove' ) ) {
@@ -3332,13 +3333,16 @@ if ( ! class_exists( 'ExactDN' ) ) {
3332
  } elseif ( false === strpos( $image_url, 'lossy=' ) && ! $this->get_option( 'exactdn_lossy' ) ) {
3333
  $more_args['lossy'] = 0;
3334
  } elseif ( false === strpos( $image_url, 'lossy=' ) && $this->get_option( 'exactdn_lossy' ) ) {
3335
- $more_args['lossy'] = is_numeric( $this->get_option( 'exactdn_lossy' ) ) ? (int) $this->get_option( 'exactdn_lossy' ) : 80;
3336
  }
3337
  if ( false === strpos( $image_url, 'quality=' ) && ! is_null( $jpg_quality ) && 82 !== (int) $jpg_quality ) {
3338
  $more_args['quality'] = $jpg_quality;
3339
  }
3340
- if ( false === strpos( $image_url, 'quality=' ) && 75 !== (int) $webp_quality && $webp_quality < $jpg_quality ) {
3341
- $more_args['quality'] = $webp_quality;
 
 
 
3342
  }
3343
  if ( defined( 'EIO_WEBP_SHARP_YUV' ) && EIO_WEBP_SHARP_YUV ) {
3344
  $more_args['sharp'] = 1;
1506
  // Replace original tag with modified version.
1507
  $content = str_replace( $images['img_tag'][ $index ], $new_tag, $content );
1508
  }
1509
+ } // End if() -- no srcset or sizes attributes found.
1510
+ } // End if() -- not a feed and EIO_SRCSET_FILL enabled.
1511
+ } // End foreach() -- of all images found in the page.
1512
+ } // End if() -- we found images in the page at all.
1513
 
1514
  // Process <a> elements in the page for image URLs.
1515
  $content = $this->filter_image_links( $content );
3319
 
3320
  $jpg_quality = apply_filters( 'jpeg_quality', null, 'image_resize' );
3321
  $webp_quality = apply_filters( 'webp_quality', 75, 'image/webp' );
3322
+ $avif_quality = apply_filters( 'avif_quality', 45, 'image/avif' );
3323
 
3324
  $more_args = array();
3325
  if ( false === strpos( $image_url, 'strip=all' ) && $this->get_option( $this->prefix . 'metadata_remove' ) ) {
3333
  } elseif ( false === strpos( $image_url, 'lossy=' ) && ! $this->get_option( 'exactdn_lossy' ) ) {
3334
  $more_args['lossy'] = 0;
3335
  } elseif ( false === strpos( $image_url, 'lossy=' ) && $this->get_option( 'exactdn_lossy' ) ) {
3336
+ $more_args['lossy'] = is_numeric( $this->get_option( 'exactdn_lossy' ) ) ? (int) $this->get_option( 'exactdn_lossy' ) : 1;
3337
  }
3338
  if ( false === strpos( $image_url, 'quality=' ) && ! is_null( $jpg_quality ) && 82 !== (int) $jpg_quality ) {
3339
  $more_args['quality'] = $jpg_quality;
3340
  }
3341
+ if ( false === strpos( $image_url, 'webp=' ) && 75 !== (int) $webp_quality ) {
3342
+ $more_args['webp'] = $webp_quality;
3343
+ }
3344
+ if ( false === strpos( $image_url, 'avif=' ) && 45 !== (int) $avif_quality ) {
3345
+ $more_args['avif'] = $avif_quality;
3346
  }
3347
  if ( defined( 'EIO_WEBP_SHARP_YUV' ) && EIO_WEBP_SHARP_YUV ) {
3348
  $more_args['sharp'] = 1;
common.php CHANGED
@@ -14,7 +14,7 @@ if ( ! defined( 'ABSPATH' ) ) {
14
  exit;
15
  }
16
 
17
- define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '651' );
18
 
19
  // Initialize a couple globals.
20
  $eio_debug = '';
@@ -84,9 +84,13 @@ if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_noauto' ) ) {
84
  add_filter( 'mpp_generate_metadata', 'ewww_image_optimizer_resize_from_meta_data', 15, 2 );
85
  // Processes an attachment after IRSC has done a thumb regen.
86
  add_filter( 'sirsc_attachment_images_ready', 'ewww_image_optimizer_resize_from_meta_data', 15, 2 );
 
 
87
  // Process BuddyPress uploads from Vikinger theme.
88
  add_action( 'vikinger_file_uploaded', 'ewww_image_optimizer' );
89
  }
 
 
90
  // Skips resizing for images with 'noresize' in the filename.
91
  add_filter( 'ewww_image_optimizer_resize_dimensions', 'ewww_image_optimizer_noresize', 10, 2 );
92
  // Makes sure the optimizer never optimizes it's own testing images.
@@ -4229,7 +4233,8 @@ function ewww_image_optimizer_restore_from_meta_data( $meta, $id ) {
4229
  }
4230
  }
4231
  $ewww_image = new EWWW_Image( $id, 'media', ewww_image_optimizer_absolutize_path( $db_image['path'] ) );
4232
- return $ewww_image->restore_with_meta( $meta );
 
4233
  }
4234
 
4235
  /**
@@ -4266,6 +4271,8 @@ function ewww_image_optimizer_cloud_restore_from_meta_data( $id, $gallery = 'med
4266
  }
4267
  }
4268
  }
 
 
4269
  if ( class_exists( 'S3_Uploads' ) || class_exists( 'S3_uploads\Plugin' ) ) {
4270
  ewww_image_optimizer_remote_push( $meta, $id );
4271
  ewwwio_debug_message( 're-uploading to S3(_Uploads)' );
@@ -8610,6 +8617,9 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
8610
  }
8611
  $fullsize_opt_size = ewww_image_optimizer_filesize( $file );
8612
 
 
 
 
8613
  // Done optimizing, do whatever you need with the attachment from here.
8614
  do_action( 'ewww_image_optimizer_after_optimize_attachment', $id, $meta );
8615
 
@@ -8952,6 +8962,73 @@ function ewww_image_optimizer_update_attachment( $meta, $id ) {
8952
  return $meta;
8953
  }
8954
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8955
  /**
8956
  * Retrieves the path of an attachment via the $id and the $meta.
8957
  *
@@ -13080,6 +13157,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
13080
  $webp_rewrite_verify = false;
13081
  // Only check the rules for problems if WebP is enabled, otherwise this is a blank slate.
13082
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) ) :
 
13083
  if ( defined( 'PHP_SAPI' ) && false === strpos( PHP_SAPI, 'apache' ) && false === strpos( PHP_SAPI, 'litespeed' ) ) {
13084
  $false_positive_headers = esc_html( 'This may be a false positive. If so, the warning should go away once you implement the rewrite rules.' );
13085
  }
14
  exit;
15
  }
16
 
17
+ define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '652' );
18
 
19
  // Initialize a couple globals.
20
  $eio_debug = '';
84
  add_filter( 'mpp_generate_metadata', 'ewww_image_optimizer_resize_from_meta_data', 15, 2 );
85
  // Processes an attachment after IRSC has done a thumb regen.
86
  add_filter( 'sirsc_attachment_images_ready', 'ewww_image_optimizer_resize_from_meta_data', 15, 2 );
87
+ // Processes an attachment after Crop Thumbnails plugin has modified the images.
88
+ add_filter( 'crop_thumbnails_before_update_metadata', 'ewww_image_optimizer_resize_from_meta_data', 15, 2 );
89
  // Process BuddyPress uploads from Vikinger theme.
90
  add_action( 'vikinger_file_uploaded', 'ewww_image_optimizer' );
91
  }
92
+ // Ensures we update the filesize data in the meta.
93
+ // add_filter( 'wp_update_attachment_metadata', 'ewww_image_optimizer_update_filesize_metadata', 9, 2 );
94
  // Skips resizing for images with 'noresize' in the filename.
95
  add_filter( 'ewww_image_optimizer_resize_dimensions', 'ewww_image_optimizer_noresize', 10, 2 );
96
  // Makes sure the optimizer never optimizes it's own testing images.
4233
  }
4234
  }
4235
  $ewww_image = new EWWW_Image( $id, 'media', ewww_image_optimizer_absolutize_path( $db_image['path'] ) );
4236
+ remove_filter( 'wp_update_attachment_metadata', 'ewww_image_optimizer_update_filesize_metadata', 9 );
4237
+ return ewww_image_optimizer_update_filesize_metadata( $ewww_image->restore_with_meta( $meta ), $id, $ewww_image->file );
4238
  }
4239
 
4240
  /**
4271
  }
4272
  }
4273
  }
4274
+ remove_filter( 'wp_update_attachment_metadata', 'ewww_image_optimizer_update_filesize_metadata', 9 );
4275
+ $meta = ewww_image_optimizer_update_filesize_metadata( $meta, $id );
4276
  if ( class_exists( 'S3_Uploads' ) || class_exists( 'S3_uploads\Plugin' ) ) {
4277
  ewww_image_optimizer_remote_push( $meta, $id );
4278
  ewwwio_debug_message( 're-uploading to S3(_Uploads)' );
8617
  }
8618
  $fullsize_opt_size = ewww_image_optimizer_filesize( $file );
8619
 
8620
+ remove_filter( 'wp_update_attachment_metadata', 'ewww_image_optimizer_update_filesize_metadata', 9 );
8621
+ $meta = ewww_image_optimizer_update_filesize_metadata( $meta, $id, $file );
8622
+
8623
  // Done optimizing, do whatever you need with the attachment from here.
8624
  do_action( 'ewww_image_optimizer_after_optimize_attachment', $id, $meta );
8625
 
8962
  return $meta;
8963
  }
8964
 
8965
+ /**
8966
+ * Update file sizes for an attachment and all thumbs.
8967
+ *
8968
+ * @param array $meta Attachment metadata.
8969
+ * @param int $id Attachment ID number.
8970
+ * @param string $file_path Optional. The full path to the full-size image.
8971
+ * @return array The updated attachment metadata.
8972
+ */
8973
+ function ewww_image_optimizer_update_filesize_metadata( $meta, $id, $file_path = false ) {
8974
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
8975
+ global $wpdb;
8976
+ if ( ! $file_path || ! is_string( $file_path ) ) {
8977
+ list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
8978
+ }
8979
+ if ( ! $file_path ) {
8980
+ return $meta;
8981
+ }
8982
+ $use_db = false;
8983
+ if ( ewww_image_optimizer_stream_wrapped( $file_path ) || ! ewwwio_is_file( $file_path ) ) {
8984
+ $use_db = true;
8985
+ }
8986
+ if ( $use_db ) {
8987
+ $full_filesize = $wpdb->get_var( $wpdb->prepare( "SELECT image_size FROM $wpdb->ewwwio_images WHERE attachment_id = %d AND gallery = 'media' AND resize = %s", $id, 'full' ) );
8988
+ if ( empty( $full_filesize ) ) {
8989
+ return $meta;
8990
+ }
8991
+ } else {
8992
+ $full_filesize = ewww_image_optimizer_filesize( $file_path );
8993
+ }
8994
+ if ( $full_filesize ) {
8995
+ ewwwio_debug_message( "updating full to $full_filesize" );
8996
+ $meta['filesize'] = (int) $full_filesize;
8997
+ }
8998
+ if ( isset( $meta['sizes'] ) && ewww_image_optimizer_iterable( $meta['sizes'] ) ) {
8999
+ foreach ( $meta['sizes'] as $size => $data ) {
9000
+ if ( $use_db && ! empty( $size ) ) {
9001
+ $scaled_filesize = $wpdb->get_var( $wpdb->prepare( "SELECT image_size FROM $wpdb->ewwwio_images WHERE attachment_id = %d AND gallery = 'media' AND resize = %s", $id, $size ) );
9002
+ if ( ! $scaled_filesize ) {
9003
+ ewwwio_debug_message( 'checking other thumbs for filesize' );
9004
+ // Check through all the other sizes.
9005
+ foreach ( $meta['sizes'] as $index => $item ) {
9006
+ // If a different resize had identical dimensions.
9007
+ if (
9008
+ $item['height'] === $data['height'] &&
9009
+ $item['width'] === $data['width'] &&
9010
+ ! empty( $item['filesize'] ) &&
9011
+ ( ! isset( $data['filesize'] ) || (int) $item['filesize'] !== (int) $data['filesize'] )
9012
+ ) {
9013
+ ewwwio_debug_message( "using $index filesize for $size" );
9014
+ $scaled_filesize = $item['filesize'];
9015
+ break;
9016
+ }
9017
+ }
9018
+ }
9019
+ } else {
9020
+ $resize_path = path_join( dirname( $file_path ), $data['file'] );
9021
+ $scaled_filesize = ewww_image_optimizer_filesize( $resize_path );
9022
+ }
9023
+ if ( $scaled_filesize ) {
9024
+ ewwwio_debug_message( "updating $size to $full_filesize" );
9025
+ $meta['sizes'][ $size ]['filesize'] = $scaled_filesize;
9026
+ }
9027
+ }
9028
+ }
9029
+ return $meta;
9030
+ }
9031
+
9032
  /**
9033
  * Retrieves the path of an attachment via the $id and the $meta.
9034
  *
13157
  $webp_rewrite_verify = false;
13158
  // Only check the rules for problems if WebP is enabled, otherwise this is a blank slate.
13159
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) ) :
13160
+ $false_positive_headers = '';
13161
  if ( defined( 'PHP_SAPI' ) && false === strpos( PHP_SAPI, 'apache' ) && false === strpos( PHP_SAPI, 'litespeed' ) ) {
13162
  $false_positive_headers = esc_html( 'This may be a false positive. If so, the warning should go away once you implement the rewrite rules.' );
13163
  }
ewww-image-optimizer.php CHANGED
@@ -11,10 +11,10 @@
11
  /*
12
  Plugin Name: EWWW Image Optimizer
13
  Plugin URI: https://wordpress.org/plugins/ewww-image-optimizer/
14
- Description: Reduce file sizes for images within WordPress including NextGEN Gallery and GRAND FlAGallery. Uses jpegtran, optipng/pngout, and gifsicle.
15
  Author: Exactly WWW
16
- Version: 6.5.1
17
- Requires at least: 5.6
18
  Requires PHP: 7.2
19
  Author URI: https://ewww.io/
20
  License: GPLv3
@@ -80,7 +80,7 @@ if ( ! defined( 'PHP_VERSION_ID' ) || PHP_VERSION_ID < 70200 ) {
80
  /**
81
  * The folder where we store debug logs (among other things) - MUST have a trailing slash.
82
  *
83
- * @var string EWWW_IMAGE_OPTIMIZER_TOOL_PATH
84
  */
85
  define( 'EWWWIO_CONTENT_DIR', $ewwwio_content_dir );
86
  }
11
  /*
12
  Plugin Name: EWWW Image Optimizer
13
  Plugin URI: https://wordpress.org/plugins/ewww-image-optimizer/
14
+ Description: Smaller Images, Faster Sites, Happier Visitors. Comprehensive image optimization that doesn't require a degree in rocket science.
15
  Author: Exactly WWW
16
+ Version: 6.5.2
17
+ Requires at least: 5.7
18
  Requires PHP: 7.2
19
  Author URI: https://ewww.io/
20
  License: GPLv3
80
  /**
81
  * The folder where we store debug logs (among other things) - MUST have a trailing slash.
82
  *
83
+ * @var string EWWWIO_CONTENT_DIR
84
  */
85
  define( 'EWWWIO_CONTENT_DIR', $ewwwio_content_dir );
86
  }
readme.txt CHANGED
@@ -2,10 +2,10 @@
2
  Contributors: nosilver4u
3
  Donate link: https://ewww.io/donate/
4
  Tags: optimize, image, convert, webp, resize, compress, lazy load, optimization, lossless, lossy, seo, scale
5
- Requires at least: 5.6
6
- Tested up to: 5.9
7
  Requires PHP: 7.2
8
- Stable tag: 6.5.1
9
  License: GPLv3
10
 
11
  Smaller Images, Faster Sites, Happier Visitors. Comprehensive image optimization that doesn't require a degree in rocket science.
@@ -137,6 +137,14 @@ That's not a question, but since I made it up, I'll answer it. See this resource
137
  * Feature requests can be viewed and submitted on our [feedback portal](https://feedback.ewww.io/b/features)
138
  * If you would like to help translate this plugin in your language, [join the team](https://translate.wordpress.org/projects/wp-plugins/ewww-image-optimizer/)
139
 
 
 
 
 
 
 
 
 
140
  = 6.5.1 =
141
  * fixed: LQIP option not available on sub-domain multisite install unless Easy IO is active on site 1
142
  * fixed: API quota function doesn't handle expired status correctly
@@ -149,111 +157,6 @@ That's not a question, but since I made it up, I'll answer it. See this resource
149
  * fixed: LQIP and SVG placeholder options not auto-loaded correctly
150
  * fixed: regression in legacy translation loader
151
 
152
- = 6.4.2 =
153
- * added: JS/Picture WebP rewriters support FacetWP AJAX responses
154
- * fixed: errors from posix_getpwuid() and posix_getgrgid() not handled correctly
155
- * fixed: PNGOUT download URLs were moved, causing auto-install to fail
156
- * fixed: Easy IO was adding srcset markup for SVG images
157
-
158
- = 6.4.1 =
159
- * added: use decoding=async to prevent images from blocking text render
160
- * fixed: database upgrade fails on MySQL 8.0.x
161
- * fixed: Auto-scale incorrectly handles Divi parallax background images
162
- * fixed: native lazy loading used on inline PNG placeholders
163
- * fixed: WebP rewriters not recognizing WP Offload Media Path (object prefix) setting
164
-
165
- = 6.4.0 =
166
- * added: free API-based WebP generation for servers that cannot generate WebP images locally
167
- * added: detection for Jetpack Boost lazy load function
168
- * added: JS WebP handling for WooCommerce product variations
169
- * changed: SVG placeholder setting removed from UI as PNG placeholders can now provide the same benefits (and better).
170
- * changed: Lazy Load no longer excludes first image in a page due to potential CLS issues and auto-scaling suppression
171
- * fixed: PNG thumbnails skipped from WebP conversion when using exec-free mode
172
- * fixed: SVG placeholders broken when existing img src is single-quoted
173
- * fixed: Lazy Loader incorrectly parses fall-back iframe from Google Tag Manager, triggering 403 errors in some WAF systems
174
- * fixed: error when disabling Easy IO
175
- * fixed: Easy IO misses some image URLs on multi-site when using domain-mapping
176
- * fixed: SVG level cannot be set when using API if svgcleaner was not installed previously
177
- * fixed: Easy IO URL rewriter changing links if they matched a custom upload folder
178
- * fixed: Easy IO incompatible with Toolset Blocks
179
- * fixed: Easy IO incorrectly sizing wide/full width cover blocks
180
- * fixed: SWIS CDN compat called too early in some cases
181
- * updated: PHP EXIF library dependency updated to 0.9.9
182
- * removed: PHP 7.1 is no longer supported
183
-
184
- = 6.3.0 =
185
- * added: EIO_LAZY_FOLD override to configure number of images above-the-fold that will be skipped by Lazy Load
186
- * added: Easy IO URLs for custom (non-WP) srcset markup
187
- * added: Easy IO support for CSS background images with relative URLs
188
- * changed: Lazy Load excludes first image in a page as above-the-fold
189
- * fixed: Easy IO scaling not working on full-size images without srcset/responsive markup
190
- * fixed: WebP and Lazy Load function skip images dynamically created by Brizy builder
191
- * fixed: Easy IO conflict on Elementor preview pages
192
- * fixed: EXACTDN_CONTENT_WIDTH not effective at overriding $content_width during image_downsize filter
193
-
194
- = 6.2.5 =
195
- * added: Easy IO and Lazy Load support for AJAX responses from FacetWP
196
- * changed: Vimeo videos excluded from iframe lazy load
197
- * changed: use 'bg-image-crop' class on elements with CSS background images that need to be cropped by auto-scaling
198
- * fixed: sub-folder multi-site installs which use separate domains could not activate Easy IO, define EXACTDN_SUB_FOLDER to override
199
- * fixed: Lazy Load PNG placeholders cannot be cached if the WP_CONTENT_DIR location is read-only (notably on Pantheon servers)
200
- * fixed: is_amp() called too early
201
- * fixed: Fusion Builder (Avada) does not load when Lazy Load, WebP, or Easy IO options are enabled
202
- * fixed: png_alpha() check uses more memory than is available, causing some uploads to fail
203
-
204
- = 6.2.4 =
205
- * added: Multi-site domain-based installs can activate/register sites en masse, and directly upon site creation
206
- * changed: improved db upgrade routine for updated column
207
- * changed: JS WebP script moved back to page head
208
- * fixed: local PNG placeholders enabled with Easy IO when placeholder folder is not writable
209
- * fixed: WebP Rewriters not detecting upload URL correctly for CDN support
210
- * fixed: iframe lazy loading breaks Gravity Forms and FacetWP when parsing JSON
211
- * fixed: SQL error when running "wp-cli ewwwio optimize media" - props @komsitr
212
- * fixed: local savings query sometimes returns no results
213
- * fixed: PHP warnings when local tools are disabled
214
-
215
- = 6.2.3 =
216
- * fixed: db error when MariaDB 10.1 does not permit ALTER for setting default column value
217
- * fixed: Lazy Load missing placeholder folder when Easy IO is enabled
218
-
219
- = 6.2.2 =
220
- * added: disable Easy IO's "deep" integration with image_downsize filter via EIO_DISABLE_DEEP_INTEGRATION override
221
- * added: integration with JSON/AJAX respones from Spotlight Social Media Feeds plugin
222
- * changed: PNG placeholders are now inlined for less HTTP requests and better auto-scaling
223
- * changed: Bulk Optimizer processes images from oldest to newest for the Media Library
224
- * changed: Resize Detection uses minified JS and console logging suppressed unless using SCRIPT_DEBUG
225
- * fixed: Easy IO does not rewrite image (href) links if image_downsize integration has rewritten the img tag
226
- * fixed: Lazy Load throws error when ewww_webp_supported not defined in edge cases
227
- * fixed: front-end scripts loading for page builders when they shouldn't be
228
- * fixed: when using WP/LR Sync, EWWWIO_WPLR_AUTO does not trigger optimization for new images
229
- * fixed: img element search parsing JSON incorrectly
230
- * fixed: WebP uploads not resized to max dimensions
231
-
232
- = 6.2.1 =
233
- * fixed: Lazy Load regression prevents above-the-fold CSS background images from loading
234
- * fixed: WebP Conversion for CMYK images leaves empty color profile attached
235
-
236
- = 6.2.0 =
237
- * added: PHP-based WebP Conversion via GD/Imagick in free mode when exec() is disabled
238
- * added: enable -sharp_yuv option for WebP conversion with the EIO_WEBP_SHARP_YUV override
239
- * added: WebP Conversion for CMYK images
240
- * added: webp-supported conditional class added to body tag when JS WebP is active
241
- * added: WP-CLI command can be run with --webp-only option
242
- * added: Lazy Load for iframes, add 'iframe' in exclusions to disable
243
- * added: compatibility with S3 Uploads 3.x
244
- * added: preserve metadata and apply lossless compression to linked versions of images via Easy IO with EIO_PRESERVE_LINKED_IMAGES constant
245
- * added: Easy IO rewrites URLs in existing picture elements
246
- * changed: JS WebP scripts moved to beginning of page footer
247
- * changed: native lazy loading is now enabled for right-sized PNG placeholders, override with EIO_DISABLE_NATIVE_LAZY constant
248
- * changed: add resume ability to Delete Originals tool
249
- * changed: move Easy IO check-in to wp_cron
250
- * fixed: empty .webp images sometimes produced when cwebp encounters an error
251
- * fixed: Bulk Optimizer for NextGEN loading incorrect script
252
- * fixed: Bulk Optimizer for NextGEN fails to verify nonce for selective optimization
253
- * fixed: Last Optimized times for Optimized Images table were incorrect
254
- * fixed: Add Missing Dimensions overwrites smaller width/height attribute if only one is set
255
- * fixed: replacing an existing attribute (like width) with a numeric value is broken
256
-
257
  = Earlier versions =
258
  Please refer to the separate changelog.txt file.
259
 
2
  Contributors: nosilver4u
3
  Donate link: https://ewww.io/donate/
4
  Tags: optimize, image, convert, webp, resize, compress, lazy load, optimization, lossless, lossy, seo, scale
5
+ Requires at least: 5.7
6
+ Tested up to: 6.0
7
  Requires PHP: 7.2
8
+ Stable tag: 6.5.2
9
  License: GPLv3
10
 
11
  Smaller Images, Faster Sites, Happier Visitors. Comprehensive image optimization that doesn't require a degree in rocket science.
137
  * Feature requests can be viewed and submitted on our [feedback portal](https://feedback.ewww.io/b/features)
138
  * If you would like to help translate this plugin in your language, [join the team](https://translate.wordpress.org/projects/wp-plugins/ewww-image-optimizer/)
139
 
140
+ = 6.5.2 =
141
+ * added: automatic optimization for Crop Thumbnails plugin
142
+ * added: filters to adjust sharpening parameters for core WP (ImageMagick) image resizing
143
+ * changed: Easy IO WebP quality can be defined separately from the JPG quality used for resizing operations
144
+ * fixed: Picture WebP rewriting disabled on embeds
145
+ * fixed: Lazy Load integration with WooCommerce Product Recommendations handling AJAX output incorrectly
146
+ * fixed: PHP notice when checking for presence of mod_rewrite/mod_headers
147
+
148
  = 6.5.1 =
149
  * fixed: LQIP option not available on sub-domain multisite install unless Easy IO is active on site 1
150
  * fixed: API quota function doesn't handle expired status correctly
157
  * fixed: LQIP and SVG placeholder options not auto-loaded correctly
158
  * fixed: regression in legacy translation loader
159
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  = Earlier versions =
161
  Please refer to the separate changelog.txt file.
162