EWWW Image Optimizer - Version 4.8.0

Version Description

  • added: ability to resize images outside media library via scheduled or bulk optimization
  • added: compatibility with WP Stateless for GSC
  • added: use ewww_image_optimizer_autoconvert_threshold filter to modify conversion threshold (default of 300kb)
  • changed: Lazy Load without ExactDN uses blank PNG placeholders for better srcset auto-sizing
  • changed: API backups taken prior to resizing/scaling rather than just before compression
  • changed: ExactDN + Lazy Load uses scaling rather than cropping by default
  • changed: prevent NextGEN backup images from being optimized
  • fixed: bulk optimizer not resuming when non-media library images remain in queue
  • fixed: notices when a user-selected admin theme is unavailable
  • fixed: privacy policy function triggers notices in WP-CLI
  • fixed: background-image attributes with single-quotes now supported by ExactDN, Lazy Load, and JS WebP
  • fixed: background-image attributes getting extra arguments with lazy load
  • fixed: On multi-site installs, site admins could add folders to optimize outside of the uploads folder
  • fixed: LQIP with SVG files results in duplicate requests
  • fixed: image optimization results in media library report file missing when using WP Stateless
  • fixed: plugin checking for 'nice' on Windows servers
Download this release

Release Info

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

Code changes from version 4.7.4 to 4.8.0

aux-optimize.php CHANGED
@@ -416,7 +416,7 @@ function ewww_image_optimizer_get_queued_attachments( $gallery, $limit = 100 ) {
416
  $selected_ids = $wpdb->get_col( $wpdb->prepare( "SELECT attachment_id FROM $wpdb->ewwwio_queue WHERE gallery = %s AND scanned = 1 LIMIT %d", $gallery, $limit ) );
417
  if ( empty( $selected_ids ) ) {
418
  ewwwio_debug_message( 'no attachments found in queue' );
419
- return array();
420
  }
421
  array_walk( $selected_ids, 'intval' );
422
  ewwwio_debug_message( 'selected items: ' . count( $selected_ids ) );
@@ -804,6 +804,9 @@ function ewww_image_optimizer_aux_images_script( $hook = '' ) {
804
  if ( defined( 'WPS_CORE_PLUGINS' ) ) {
805
  ewww_image_optimizer_image_scan( WP_CONTENT_DIR . '/wps-pro-content', $started );
806
  }
 
 
 
807
  if ( is_plugin_active( 'ml-slider/ml-slider.php' ) || is_plugin_active_for_network( 'ml-slider/ml-slider.php' ) ) {
808
  global $wpdb;
809
  $slide_paths = array();
416
  $selected_ids = $wpdb->get_col( $wpdb->prepare( "SELECT attachment_id FROM $wpdb->ewwwio_queue WHERE gallery = %s AND scanned = 1 LIMIT %d", $gallery, $limit ) );
417
  if ( empty( $selected_ids ) ) {
418
  ewwwio_debug_message( 'no attachments found in queue' );
419
+ return array( 0 );
420
  }
421
  array_walk( $selected_ids, 'intval' );
422
  ewwwio_debug_message( 'selected items: ' . count( $selected_ids ) );
804
  if ( defined( 'WPS_CORE_PLUGINS' ) ) {
805
  ewww_image_optimizer_image_scan( WP_CONTENT_DIR . '/wps-pro-content', $started );
806
  }
807
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_lazy_load' ) ) {
808
+ ewww_image_optimizer_image_scan( WP_CONTENT_DIR . '/ewww/lazy/', $started );
809
+ }
810
  if ( is_plugin_active( 'ml-slider/ml-slider.php' ) || is_plugin_active_for_network( 'ml-slider/ml-slider.php' ) ) {
811
  global $wpdb;
812
  $slide_paths = array();
bulk.php CHANGED
@@ -383,6 +383,9 @@ function ewww_image_optimizer_bulk_script( $hook ) {
383
  // Check the 'bulk resume' option.
384
  $resume = get_option( 'ewww_image_optimizer_bulk_resume' );
385
  $scanning = get_option( 'ewww_image_optimizer_aux_resume' );
 
 
 
386
  if ( ! $resume && ! $scanning ) {
387
  ewwwio_debug_message( 'not resuming/scanning, so clearing any pending images in both tables' );
388
  ewww_image_optimizer_delete_queue_images();
@@ -437,11 +440,10 @@ function ewww_image_optimizer_bulk_script( $hook ) {
437
  ewwwio_debug_message( 'loading attachments into queue table' );
438
  ewww_image_optimizer_insert_unscanned( $attachments );
439
  $attachment_count = count( $attachments );
440
- /* update_option( 'ewww_image_optimizer_scanning_attachments', $attachments, false ); */
441
  } else {
442
  $attachment_count = ewww_image_optimizer_count_unscanned_attachments();
443
  }
444
- if ( empty( $attachment_count ) && ! ewww_image_optimizer_count_attachments() ) {
445
  update_option( 'ewww_image_optimizer_bulk_resume', '' );
446
  update_option( 'ewww_image_optimizer_aux_resume', '' );
447
  }
@@ -804,26 +806,6 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
804
  ewwwio_debug_message( "missing mime for $selected_id" );
805
  }
806
 
807
- if ( 'application/pdf' !== $mime // NOT a pdf...
808
- && ( // AND...
809
- empty( $meta ) // metadata is empty...
810
- || ( is_string( $meta ) && 'processing' === $meta ) // OR the string 'processing'...
811
- || ( is_array( $meta ) && ! empty( $meta[0] ) && 'processing' === $meta[0] ) // OR array( 'processing' ).
812
- )
813
- ) {
814
- // Attempt to rebuild the metadata.
815
- ewwwio_debug_message( "attempting to rebuild attachment meta for $selected_id" );
816
- set_transient( 'ewww_image_optimizer_rebuilding_attachment', $selected_id, 5 * MINUTE_IN_SECONDS );
817
- ewww_image_optimizer_debug_log();
818
- $new_meta = ewww_image_optimizer_rebuild_meta( $selected_id );
819
- delete_transient( 'ewww_image_optimizer_rebuilding_attachment' );
820
- if ( is_array( $new_meta ) ) {
821
- $meta = $new_meta;
822
- } else {
823
- $meta = array();
824
- }
825
- }
826
-
827
  if ( ! in_array( $mime, $enabled_types, true ) ) {
828
  $skipped_ids[] = $selected_id;
829
  continue;
@@ -839,7 +821,14 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
839
  ewww_image_optimizer_check_table_as3cf( $meta, $selected_id, $file_path );
840
  }
841
  ewww_image_optimizer_debug_log();
842
- if ( ( ewww_image_optimizer_stream_wrapped( $file_path ) || ! is_file( $file_path ) ) && ( class_exists( 'WindowsAzureStorageUtil' ) || class_exists( 'Amazon_S3_And_CloudFront' ) ) ) {
 
 
 
 
 
 
 
843
  // Construct a $file_path and proceed IF a supported CDN plugin is installed.
844
  ewwwio_debug_message( 'Azure or S3 detected and no local file found' );
845
  $file_path = get_attached_file( $selected_id );
@@ -1238,6 +1227,7 @@ function ewww_image_optimizer_bulk_quota_update() {
1238
  * Called via AJAX to start the bulk operation and get the name of the first image in the queue.
1239
  */
1240
  function ewww_image_optimizer_bulk_initialize() {
 
1241
  // Verify that an authorized user has made the request.
1242
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
1243
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
@@ -1249,7 +1239,6 @@ function ewww_image_optimizer_bulk_initialize() {
1249
 
1250
  // Update the 'bulk resume' option to show that an operation is in progress.
1251
  update_option( 'ewww_image_optimizer_bulk_resume', 'true' );
1252
- // $attachment = (int) array_shift( $attachments );
1253
  list( $attachment ) = ewww_image_optimizer_get_queued_attachments( 'media', 1 );
1254
  ewwwio_debug_message( "first image: $attachment" );
1255
  $first_image = new EWWW_Image( $attachment, 'media' );
@@ -1509,15 +1498,13 @@ function ewww_image_optimizer_bulk_loop( $hook = '', $delay = 0 ) {
1509
  }
1510
  }
1511
  }
1512
- // If a resize is missing, see if it should (and can) be regenerated.
1513
- if ( $image->resize && 'full' !== $image->resize && ! is_file( $image->file ) ) {
1514
- // TODO: Make sure this is optional, because of CDN offloading: resized image does not exist, regenerate it.
1515
- }
1516
  $countermeasures = ewww_image_optimizer_bulk_counter_measures( $image );
1517
  if ( $countermeasures ) {
1518
  $batch_image_limit = 1;
1519
  }
1520
  set_transient( 'ewww_image_optimizer_bulk_current_image', $image->file, 600 );
 
 
1521
  if ( 'full' === $image->resize && ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' ) && ! function_exists( 'imsanity_get_max_width_height' ) ) {
1522
  if ( ! $meta || ! is_array( $meta ) ) {
1523
  $meta = wp_get_attachment_metadata( $image->attachment_id );
@@ -1527,6 +1514,8 @@ function ewww_image_optimizer_bulk_loop( $hook = '', $delay = 0 ) {
1527
  $meta['width'] = $new_dimensions[0];
1528
  $meta['height'] = $new_dimensions[1];
1529
  }
 
 
1530
  }
1531
  list( $file, $msg, $converted, $original ) = ewww_image_optimizer( $image->file, 1, false, false, 'full' === $image->resize );
1532
  // Gotta make sure we don't delete a pending record if the license is exceeded, so the license check goes first.
@@ -1586,7 +1575,8 @@ function ewww_image_optimizer_bulk_loop( $hook = '', $delay = 0 ) {
1586
 
1587
  // When we finish all the sizes, we want to fire off any filters for plugins that might need to take action when an image is updated.
1588
  if ( $attachment && (int) $attachment !== (int) $next_image->attachment_id ) {
1589
- $meta = apply_filters( 'wp_update_attachment_metadata', wp_get_attachment_metadata( $image->attachment_id ), $image->attachment_id );
 
1590
  }
1591
  // When an image (attachment) is done, pull the next attachment ID off the stack.
1592
  if ( ( 'full' === $next_image->resize || empty( $next_image->resize ) ) && ! empty( $attachment ) && (int) $attachment !== (int) $next_image->attachment_id ) {
383
  // Check the 'bulk resume' option.
384
  $resume = get_option( 'ewww_image_optimizer_bulk_resume' );
385
  $scanning = get_option( 'ewww_image_optimizer_aux_resume' );
386
+ if ( 'scanning' !== $scanning && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_auto' ) ) {
387
+ $scanning = false;
388
+ }
389
  if ( ! $resume && ! $scanning ) {
390
  ewwwio_debug_message( 'not resuming/scanning, so clearing any pending images in both tables' );
391
  ewww_image_optimizer_delete_queue_images();
440
  ewwwio_debug_message( 'loading attachments into queue table' );
441
  ewww_image_optimizer_insert_unscanned( $attachments );
442
  $attachment_count = count( $attachments );
 
443
  } else {
444
  $attachment_count = ewww_image_optimizer_count_unscanned_attachments();
445
  }
446
+ if ( empty( $attachment_count ) && ! ewww_image_optimizer_count_attachments() && ! ewww_image_optimizer_aux_images_table_count_pending() ) {
447
  update_option( 'ewww_image_optimizer_bulk_resume', '' );
448
  update_option( 'ewww_image_optimizer_aux_resume', '' );
449
  }
806
  ewwwio_debug_message( "missing mime for $selected_id" );
807
  }
808
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
809
  if ( ! in_array( $mime, $enabled_types, true ) ) {
810
  $skipped_ids[] = $selected_id;
811
  continue;
821
  ewww_image_optimizer_check_table_as3cf( $meta, $selected_id, $file_path );
822
  }
823
  ewww_image_optimizer_debug_log();
824
+ if (
825
+ ( ewww_image_optimizer_stream_wrapped( $file_path ) || ! is_file( $file_path ) ) &&
826
+ (
827
+ class_exists( 'WindowsAzureStorageUtil' ) ||
828
+ class_exists( 'Amazon_S3_And_CloudFront' ) ||
829
+ class_exists( 'wpCloud\StatelessMedia\EWWW' )
830
+ )
831
+ ) {
832
  // Construct a $file_path and proceed IF a supported CDN plugin is installed.
833
  ewwwio_debug_message( 'Azure or S3 detected and no local file found' );
834
  $file_path = get_attached_file( $selected_id );
1227
  * Called via AJAX to start the bulk operation and get the name of the first image in the queue.
1228
  */
1229
  function ewww_image_optimizer_bulk_initialize() {
1230
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1231
  // Verify that an authorized user has made the request.
1232
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
1233
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
1239
 
1240
  // Update the 'bulk resume' option to show that an operation is in progress.
1241
  update_option( 'ewww_image_optimizer_bulk_resume', 'true' );
 
1242
  list( $attachment ) = ewww_image_optimizer_get_queued_attachments( 'media', 1 );
1243
  ewwwio_debug_message( "first image: $attachment" );
1244
  $first_image = new EWWW_Image( $attachment, 'media' );
1498
  }
1499
  }
1500
  }
 
 
 
 
1501
  $countermeasures = ewww_image_optimizer_bulk_counter_measures( $image );
1502
  if ( $countermeasures ) {
1503
  $batch_image_limit = 1;
1504
  }
1505
  set_transient( 'ewww_image_optimizer_bulk_current_image', $image->file, 600 );
1506
+ global $ewww_image;
1507
+ $ewww_image = $image;
1508
  if ( 'full' === $image->resize && ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' ) && ! function_exists( 'imsanity_get_max_width_height' ) ) {
1509
  if ( ! $meta || ! is_array( $meta ) ) {
1510
  $meta = wp_get_attachment_metadata( $image->attachment_id );
1514
  $meta['width'] = $new_dimensions[0];
1515
  $meta['height'] = $new_dimensions[1];
1516
  }
1517
+ } elseif ( empty( $image->resize ) && ewww_image_optimizer_should_resize_other_image( $image->file ) ) {
1518
+ $new_dimensions = ewww_image_optimizer_resize_upload( $image->file );
1519
  }
1520
  list( $file, $msg, $converted, $original ) = ewww_image_optimizer( $image->file, 1, false, false, 'full' === $image->resize );
1521
  // Gotta make sure we don't delete a pending record if the license is exceeded, so the license check goes first.
1575
 
1576
  // When we finish all the sizes, we want to fire off any filters for plugins that might need to take action when an image is updated.
1577
  if ( $attachment && (int) $attachment !== (int) $next_image->attachment_id ) {
1578
+ wp_update_attachment_metadata( $image->attachment_id, wp_get_attachment_metadata( $image->attachment_id ) );
1579
+ /* $meta = apply_filters( 'wp_update_attachment_metadata', wp_get_attachment_metadata( $image->attachment_id ), $image->attachment_id ); */
1580
  }
1581
  // When an image (attachment) is done, pull the next attachment ID off the stack.
1582
  if ( ( 'full' === $next_image->resize || empty( $next_image->resize ) ) && ! empty( $attachment ) && (int) $attachment !== (int) $next_image->attachment_id ) {
changelog.txt CHANGED
@@ -1,3 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  = 4.7.4 =
2
  * fixed: ExactDN modifies Autoptimize CDN setting even when Include All Resources is disabled
3
  * fixed: noscript elements with newlines being parsed incorrectly by Lazy Load and JS WebP
1
+ = 4.8.0 =
2
+ * added: ability to resize images outside media library via scheduled or bulk optimization
3
+ * added: compatibility with WP Stateless for GSC
4
+ * added: use ewww_image_optimizer_autoconvert_threshold filter to modify conversion threshold (default of 300kb)
5
+ * changed: Lazy Load without ExactDN uses blank PNG placeholders for better srcset auto-sizing
6
+ * changed: API backups taken prior to resizing/scaling rather than just before compression
7
+ * changed: ExactDN + Lazy Load uses scaling rather than cropping by default
8
+ * changed: prevent NextGEN backup images from being optimized
9
+ * fixed: bulk optimizer not resuming when non-media library images remain in queue
10
+ * fixed: notices when a user-selected admin theme is unavailable
11
+ * fixed: privacy policy function triggers notices in WP-CLI
12
+ * fixed: background-image attributes with single-quotes now supported by ExactDN, Lazy Load, and JS WebP
13
+ * fixed: background-image attributes getting extra arguments with lazy load
14
+ * fixed: On multi-site installs, site admins could add folders to optimize outside of the uploads folder
15
+ * fixed: LQIP with SVG files results in duplicate requests
16
+ * fixed: image optimization results in media library report file missing when using WP Stateless
17
+ * fixed: plugin checking for 'nice' on Windows servers
18
+
19
  = 4.7.4 =
20
  * fixed: ExactDN modifies Autoptimize CDN setting even when Include All Resources is disabled
21
  * fixed: noscript elements with newlines being parsed incorrectly by Lazy Load and JS WebP
classes/class-ewww-image.php CHANGED
@@ -137,7 +137,7 @@ class EWWW_Image {
137
  if ( $id && empty( $new_image['attachment_id'] ) ) {
138
  $new_image['attachment_id'] = (int) $id;
139
  }
140
- if ( $gallery && empty( $new_image['gallery'] ) ) {
141
  $new_image['gallery'] = $gallery;
142
  }
143
  }
@@ -179,7 +179,7 @@ class EWWW_Image {
179
  $this->orig_size = (int) $new_image['orig_size'];
180
  $this->resize = $new_image['resize'];
181
  $this->converted = ewww_image_optimizer_absolutize_path( $new_image['converted'] );
182
- $this->gallery = ( empty( $gallery ) ? $new_image['gallery'] : $gallery );
183
  $this->backup = $new_image['backup'];
184
  $this->level = (int) $new_image['level'];
185
  $this->record = $new_image;
137
  if ( $id && empty( $new_image['attachment_id'] ) ) {
138
  $new_image['attachment_id'] = (int) $id;
139
  }
140
+ if ( $gallery && empty( $new_image['gallery'] ) && ! empty( $new_image['attachment_id'] ) ) {
141
  $new_image['gallery'] = $gallery;
142
  }
143
  }
179
  $this->orig_size = (int) $new_image['orig_size'];
180
  $this->resize = $new_image['resize'];
181
  $this->converted = ewww_image_optimizer_absolutize_path( $new_image['converted'] );
182
+ $this->gallery = ( empty( $gallery ) || empty( $new_image['attachment_id'] ) ? $new_image['gallery'] : $gallery );
183
  $this->backup = $new_image['backup'];
184
  $this->level = (int) $new_image['level'];
185
  $this->record = $new_image;
classes/class-ewww-nextgen.php CHANGED
@@ -114,7 +114,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
114
  function maybe_get_more_sizes( $sizes, $meta ) {
115
  if ( 2 === count( $sizes ) && ewww_image_optimizer_iterable( $meta ) ) {
116
  foreach ( $meta as $meta_key => $meta_val ) {
117
- if ( is_array( $meta_val ) && isset( $meta_val['width'] ) ) {
118
  $sizes[] = $meta_key;
119
  }
120
  }
@@ -194,6 +194,9 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
194
  } else {
195
  $full_size = false;
196
  }
 
 
 
197
  // Get the absolute path.
198
  $file_path = $storage->get_image_abspath( $image, $size );
199
  ewwwio_debug_message( "optimizing (nextgen) $size: $file_path" );
@@ -487,6 +490,8 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
487
  foreach ( $sizes as $size ) {
488
  if ( 'full' === $size ) {
489
  $full_size = true;
 
 
490
  } else {
491
  $file_path = $storage->get_image_abspath( $image, $size );
492
  $full_size = false;
@@ -907,7 +912,9 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
907
  $sizes = $this->maybe_get_more_sizes( $sizes, $image->meta_data );
908
  if ( ewww_image_optimizer_iterable( $sizes ) ) {
909
  foreach ( $sizes as $size ) {
910
- if ( 'full' === $size ) {
 
 
911
  /* Translators: %s: The compression results/savings */
912
  $output['results'] .= sprintf( esc_html__( 'Full size - %s', 'ewww-image-optimizer' ) . '<br>', esc_html( $image->meta_data['ewww_image_optimizer'] ) );
913
  } elseif ( 'thumbnail' === $size ) {
114
  function maybe_get_more_sizes( $sizes, $meta ) {
115
  if ( 2 === count( $sizes ) && ewww_image_optimizer_iterable( $meta ) ) {
116
  foreach ( $meta as $meta_key => $meta_val ) {
117
+ if ( 'backup' !== $meta_key && is_array( $meta_val ) && isset( $meta_val['width'] ) ) {
118
  $sizes[] = $meta_key;
119
  }
120
  }
194
  } else {
195
  $full_size = false;
196
  }
197
+ if ( 'backup' === $size ) {
198
+ continue;
199
+ }
200
  // Get the absolute path.
201
  $file_path = $storage->get_image_abspath( $image, $size );
202
  ewwwio_debug_message( "optimizing (nextgen) $size: $file_path" );
490
  foreach ( $sizes as $size ) {
491
  if ( 'full' === $size ) {
492
  $full_size = true;
493
+ } elseif ( 'backup' === $size ) {
494
+ continue;
495
  } else {
496
  $file_path = $storage->get_image_abspath( $image, $size );
497
  $full_size = false;
912
  $sizes = $this->maybe_get_more_sizes( $sizes, $image->meta_data );
913
  if ( ewww_image_optimizer_iterable( $sizes ) ) {
914
  foreach ( $sizes as $size ) {
915
+ if ( 'backup' === $size ) {
916
+ continue;
917
+ } elseif ( 'full' === $size ) {
918
  /* Translators: %s: The compression results/savings */
919
  $output['results'] .= sprintf( esc_html__( 'Full size - %s', 'ewww-image-optimizer' ) . '<br>', esc_html( $image->meta_data['ewww_image_optimizer'] ) );
920
  } elseif ( 'thumbnail' === $size ) {
classes/class-ewwwio-alt-webp.php CHANGED
@@ -753,6 +753,9 @@ class EWWWIO_Alt_Webp extends EWWWIO_Page_Parser {
753
  * Load full webp script when SCRIPT_DEBUG is enabled.
754
  */
755
  function debug_script() {
 
 
 
756
  if ( ! ewww_image_optimizer_ce_webp_enabled() ) {
757
  wp_enqueue_script( 'ewww-webp-load-script', plugins_url( '/includes/load_webp.js', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ), array(), EWWW_IMAGE_OPTIMIZER_VERSION );
758
  }
@@ -762,20 +765,26 @@ class EWWWIO_Alt_Webp extends EWWWIO_Page_Parser {
762
  * Load minified webp script when EWWW_IMAGE_OPTIMIZER_WEBP_EXTERNAL_SCRIPT is set.
763
  */
764
  function min_external_script() {
 
 
 
765
  if ( ! ewww_image_optimizer_ce_webp_enabled() ) {
766
  wp_enqueue_script( 'ewww-webp-load-script', plugins_url( '/includes/load_webp.min.js', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ), array(), EWWW_IMAGE_OPTIMIZER_VERSION );
767
  }
768
  }
769
 
770
  /**
771
- * Load minified inline version of webp script (from jscompress.com).
772
  */
773
  function inline_script() {
774
  if ( defined( 'EWWW_IMAGE_OPTIMIZER_NO_JS' ) && EWWW_IMAGE_OPTIMIZER_NO_JS ) {
775
  return;
776
  }
 
 
 
777
  ewwwio_debug_message( 'loading webp script without wp_add_inline_script' );
778
- echo "<script>$this->inline_script</script>";
779
  }
780
  }
781
 
753
  * Load full webp script when SCRIPT_DEBUG is enabled.
754
  */
755
  function debug_script() {
756
+ if ( ewww_image_optimizer_is_amp() ) {
757
+ return;
758
+ }
759
  if ( ! ewww_image_optimizer_ce_webp_enabled() ) {
760
  wp_enqueue_script( 'ewww-webp-load-script', plugins_url( '/includes/load_webp.js', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ), array(), EWWW_IMAGE_OPTIMIZER_VERSION );
761
  }
765
  * Load minified webp script when EWWW_IMAGE_OPTIMIZER_WEBP_EXTERNAL_SCRIPT is set.
766
  */
767
  function min_external_script() {
768
+ if ( ewww_image_optimizer_is_amp() ) {
769
+ return;
770
+ }
771
  if ( ! ewww_image_optimizer_ce_webp_enabled() ) {
772
  wp_enqueue_script( 'ewww-webp-load-script', plugins_url( '/includes/load_webp.min.js', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ), array(), EWWW_IMAGE_OPTIMIZER_VERSION );
773
  }
774
  }
775
 
776
  /**
777
+ * Load minified (jscompress.com) inline version of webp script.
778
  */
779
  function inline_script() {
780
  if ( defined( 'EWWW_IMAGE_OPTIMIZER_NO_JS' ) && EWWW_IMAGE_OPTIMIZER_NO_JS ) {
781
  return;
782
  }
783
+ if ( ewww_image_optimizer_is_amp() ) {
784
+ return;
785
+ }
786
  ewwwio_debug_message( 'loading webp script without wp_add_inline_script' );
787
+ echo '<script type="text/javascript">' . $this->inline_script . '</script>';
788
  }
789
  }
790
 
classes/class-ewwwio-lazy-load.php CHANGED
@@ -31,6 +31,22 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
31
  */
32
  protected $parsing_exactdn = false;
33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  /**
35
  * Register (once) actions and filters for Lazy Load.
36
  */
@@ -54,10 +70,20 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
54
  }
55
  }
56
 
 
 
 
 
 
 
57
  // Filter early, so that others at the default priority take precendence.
58
  add_filter( 'ewww_image_optimizer_use_lqip', array( $this, 'maybe_lqip' ), 9 );
 
59
  add_filter( 'ewww_image_optimizer_use_siip', array( $this, 'maybe_siip' ), 9 );
60
 
 
 
 
61
  // Load the appropriate JS.
62
  if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
63
  // Load the non-minified and separate versions of the lazy load scripts.
@@ -68,7 +94,6 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
68
  }
69
  }
70
 
71
-
72
  /**
73
  * Starts an output buffer and registers the callback function to do WebP replacement.
74
  */
@@ -94,13 +119,26 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
94
  */
95
  function filter_page_output( $buffer ) {
96
  ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
 
 
 
 
 
 
 
 
 
 
 
 
97
  // Don't lazy load in these cases...
98
  $uri = $_SERVER['REQUEST_URI'];
99
  if (
100
  empty( $buffer ) ||
101
- is_admin() ||
102
  ! empty( $_GET['cornerstone'] ) ||
103
  strpos( $uri, 'cornerstone-endpoint' ) !== false ||
 
 
104
  ! empty( $_GET['et_fb'] ) ||
105
  ! empty( $_GET['tatsu'] ) ||
106
  ( ! empty( $_POST['action'] ) && 'tatsu_get_concepts' === $_POST['action'] ) ||
@@ -114,12 +152,15 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
114
  if ( empty( $buffer ) ) {
115
  ewwwio_debug_message( 'empty buffer' );
116
  }
117
- if ( is_admin() ) {
118
- ewwwio_debug_message( 'is_admin' );
119
- }
120
  if ( ! empty( $_GET['cornerstone'] ) || strpos( $uri, 'cornerstone-endpoint' ) !== false ) {
121
  ewwwio_debug_message( 'cornerstone editor' );
122
  }
 
 
 
 
 
 
123
  if ( ! empty( $_GET['et_fb'] ) ) {
124
  ewwwio_debug_message( 'et_fb' );
125
  }
@@ -170,22 +211,40 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
170
  $srcset = $this->get_attribute( $image, 'srcset' );
171
 
172
  $placeholder_src = $this->placeholder_src;
173
- if ( false === strpos( $file, 'nggid' ) && apply_filters( 'ewww_image_optimizer_use_lqip', true ) && $this->parsing_exactdn && strpos( $file, $this->exactdn_domain ) ) {
 
174
  $placeholder_src = add_query_arg( array( 'lazy' => 1 ), $file );
175
- ewwwio_debug_message( "current placeholder is $placeholder_src" );
176
- } elseif ( apply_filters( 'ewww_image_optimizer_use_siip', true ) ) {
177
- // Get image dimensions for inline SVG placeholder.
178
  list( $width, $height ) = $this->get_dimensions_from_filename( $file );
179
 
180
  $width_attr = $this->get_attribute( $image, 'width' );
181
  $height_attr = $this->get_attribute( $image, 'height' );
182
 
 
 
 
 
 
 
183
  if ( false === $width || false === $height ) {
184
- ewwwio_debug_message( "dimensions not found in $file, using attrs" );
185
  $width = $width_attr;
186
  $height = $height_attr;
187
  }
188
 
 
 
 
 
 
 
 
 
 
 
 
 
189
  // Can't use a relative width or height, so unset the dimensions in favor of not breaking things.
190
  if ( false !== strpos( $width, '%' ) || false !== strpos( $height, '%' ) ) {
191
  $width = false;
@@ -197,14 +256,9 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
197
  $height = $height ? (int) $height : false;
198
  if ( $width && $height ) {
199
  $placeholder_src = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 $width $height'%3E%3C/svg%3E";
200
- if ( empty( $width_attr ) ) {
201
- $this->set_attribute( $image, 'width', $width );
202
- }
203
- if ( empty( $height_attr ) ) {
204
- $this->set_attribute( $image, 'height', $height );
205
- }
206
  }
207
  }
 
208
 
209
  if ( $srcset ) {
210
  $placeholder_src = apply_filters( 'ewww_image_optimizer_lazy_placeholder', $placeholder_src, $image );
@@ -303,9 +357,11 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
303
  if ( false === strpos( $element, 'background:' ) && false === strpos( $element, 'background-image:' ) ) {
304
  continue;
305
  }
 
306
  if ( ! $this->validate_bgimage_tag( $element ) ) {
307
  continue;
308
  }
 
309
  $style = $this->get_attribute( $element, 'style' );
310
  if ( empty( $style ) ) {
311
  continue;
@@ -313,14 +369,17 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
313
  ewwwio_debug_message( "checking style attr for background-image: $style" );
314
  $bg_image_url = $this->get_background_image_url( $style );
315
  if ( $bg_image_url ) {
 
316
  $new_style = $this->remove_background_image( $style );
317
  if ( $style !== $new_style ) {
 
318
  $this->set_attribute( $element, 'class', $this->get_attribute( $element, 'class' ) . ' lazyload', true );
319
  $this->set_attribute( $element, 'data-bg', $bg_image_url );
320
  $element = str_replace( $style, $new_style, $element );
321
  }
322
  }
323
  if ( $element !== $elements[ $index ] ) {
 
324
  $buffer = str_replace( $elements[ $index ], $element, $buffer );
325
  }
326
  }
@@ -382,6 +441,7 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
382
  'fullurl=',
383
  'gazette-featured-content-thumbnail',
384
  'lazy-slider-img=',
 
385
  'skip-lazy',
386
  'timthumb.php?',
387
  'wpcf7_captcha/',
@@ -408,6 +468,7 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
408
  'ewww_image_optimizer_lazy_bg_image_exclusions',
409
  array(
410
  'data-no-lazy=',
 
411
  'lazyload',
412
  'skip-lazy',
413
  ),
@@ -421,6 +482,55 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
421
  return true;
422
  }
423
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
424
  /**
425
  * Check if LQIP should be used, but allow filters to alter the option.
426
  *
@@ -434,6 +544,19 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
434
  return $use_lqip;
435
  }
436
 
 
 
 
 
 
 
 
 
 
 
 
 
 
437
  /**
438
  * Check if SIIP should be used, but allow filters to alter the option.
439
  *
@@ -459,6 +582,9 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
459
  */
460
  function debug_script() {
461
  ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
 
 
 
462
  wp_enqueue_script( 'ewww-lazy-load-pre', plugins_url( '/includes/lazysizes-pre.js', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ), array(), EWWW_IMAGE_OPTIMIZER_VERSION );
463
  wp_enqueue_script( 'ewww-lazy-load', plugins_url( '/includes/lazysizes.js', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ), array(), EWWW_IMAGE_OPTIMIZER_VERSION );
464
  wp_enqueue_script( 'ewww-lazy-load-post', plugins_url( '/includes/lazysizes-post.js', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ), array(), EWWW_IMAGE_OPTIMIZER_VERSION );
@@ -477,6 +603,9 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
477
  */
478
  function min_script() {
479
  ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
 
 
 
480
  wp_enqueue_script( 'ewww-lazy-load', plugins_url( '/includes/lazysizes.min.js', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ), array(), EWWW_IMAGE_OPTIMIZER_VERSION );
481
  wp_localize_script(
482
  'ewww-lazy-load',
31
  */
32
  protected $parsing_exactdn = false;
33
 
34
+ /**
35
+ * The folder to store any PIIPs.
36
+ *
37
+ * @access protected
38
+ * @var string $piip_folder
39
+ */
40
+ protected $piip_folder = WP_CONTENT_DIR . '/ewww/lazy/';
41
+
42
+ /**
43
+ * Whether to allow PIIPs.
44
+ *
45
+ * @access public
46
+ * @var bool $allow_piip
47
+ */
48
+ public $allow_piip = true;
49
+
50
  /**
51
  * Register (once) actions and filters for Lazy Load.
52
  */
70
  }
71
  }
72
 
73
+ if ( ! is_dir( $this->piip_folder ) ) {
74
+ $this->allow_piip = wp_mkdir_p( $this->piip_folder ) && ewww_image_optimizer_gd_support();
75
+ } else {
76
+ $this->allow_piip = is_writable( $this->piip_folder ) && ewww_image_optimizer_gd_support();
77
+ }
78
+
79
  // Filter early, so that others at the default priority take precendence.
80
  add_filter( 'ewww_image_optimizer_use_lqip', array( $this, 'maybe_lqip' ), 9 );
81
+ add_filter( 'ewww_image_optimizer_use_piip', array( $this, 'maybe_piip' ), 9 );
82
  add_filter( 'ewww_image_optimizer_use_siip', array( $this, 'maybe_siip' ), 9 );
83
 
84
+ // Overrides for admin-ajax images.
85
+ add_filter( 'ewww_image_optimizer_admin_allow_lazyload', array( $this, 'allow_admin_lazyload' ) );
86
+
87
  // Load the appropriate JS.
88
  if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
89
  // Load the non-minified and separate versions of the lazy load scripts.
94
  }
95
  }
96
 
 
97
  /**
98
  * Starts an output buffer and registers the callback function to do WebP replacement.
99
  */
119
  */
120
  function filter_page_output( $buffer ) {
121
  ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
122
+ // Don't foul up the admin side of things, unless a plugin needs to.
123
+ if ( is_admin() &&
124
+ /**
125
+ * Provide plugins a way of running Lazy Load for images in the WordPress Dashboard (wp-admin).
126
+ *
127
+ * @param bool false Allow Lazy Load to run on the Dashboard. Default to false.
128
+ */
129
+ false === apply_filters( 'ewww_image_optimizer_admin_allow_lazyload', false )
130
+ ) {
131
+ ewwwio_debug_message( 'is_admin' );
132
+ return $buffer;
133
+ }
134
  // Don't lazy load in these cases...
135
  $uri = $_SERVER['REQUEST_URI'];
136
  if (
137
  empty( $buffer ) ||
 
138
  ! empty( $_GET['cornerstone'] ) ||
139
  strpos( $uri, 'cornerstone-endpoint' ) !== false ||
140
+ ! empty( $_GET['ct_builder'] ) ||
141
+ ! empty( $_GET['elementor-preview'] ) ||
142
  ! empty( $_GET['et_fb'] ) ||
143
  ! empty( $_GET['tatsu'] ) ||
144
  ( ! empty( $_POST['action'] ) && 'tatsu_get_concepts' === $_POST['action'] ) ||
152
  if ( empty( $buffer ) ) {
153
  ewwwio_debug_message( 'empty buffer' );
154
  }
 
 
 
155
  if ( ! empty( $_GET['cornerstone'] ) || strpos( $uri, 'cornerstone-endpoint' ) !== false ) {
156
  ewwwio_debug_message( 'cornerstone editor' );
157
  }
158
+ if ( ! empty( $_GET['ct_builder'] ) ) {
159
+ ewwwio_debug_message( 'oxygen builder' );
160
+ }
161
+ if ( ! empty( $_GET['elementor-preview'] ) ) {
162
+ ewwwio_debug_message( 'elementor preview' );
163
+ }
164
  if ( ! empty( $_GET['et_fb'] ) ) {
165
  ewwwio_debug_message( 'et_fb' );
166
  }
211
  $srcset = $this->get_attribute( $image, 'srcset' );
212
 
213
  $placeholder_src = $this->placeholder_src;
214
+ if ( false === strpos( $file, 'nggid' ) && ! preg_match( '#\.svg(\?|$)#', $file ) && apply_filters( 'ewww_image_optimizer_use_lqip', true ) && $this->parsing_exactdn && strpos( $file, $this->exactdn_domain ) ) {
215
+ ewwwio_debug_message( 'using lqip' );
216
  $placeholder_src = add_query_arg( array( 'lazy' => 1 ), $file );
217
+ } elseif ( $this->allow_piip && $srcset && apply_filters( 'ewww_image_optimizer_use_piip', true ) ) {
218
+ ewwwio_debug_message( 'trying piip' );
219
+ // Get image dimensions for PNG placeholder.
220
  list( $width, $height ) = $this->get_dimensions_from_filename( $file );
221
 
222
  $width_attr = $this->get_attribute( $image, 'width' );
223
  $height_attr = $this->get_attribute( $image, 'height' );
224
 
225
+ // Can't use a relative width or height, so unset the dimensions in favor of not breaking things.
226
+ if ( false !== strpos( $width_attr, '%' ) || false !== strpos( $height_attr, '%' ) ) {
227
+ $width_attr = false;
228
+ $height_attr = false;
229
+ }
230
+
231
  if ( false === $width || false === $height ) {
 
232
  $width = $width_attr;
233
  $height = $height_attr;
234
  }
235
 
236
+ // Falsify them if empty.
237
+ $width = $width ? (int) $width : false;
238
+ $height = $height ? (int) $height : false;
239
+ if ( $width && $height ) {
240
+ ewwwio_debug_message( "creating piip of $width x $height" );
241
+ $placeholder_src = $this->create_piip( $width, $height );
242
+ }
243
+ } elseif ( apply_filters( 'ewww_image_optimizer_use_siip', true ) ) {
244
+ ewwwio_debug_message( 'trying siip' );
245
+ $width = $this->get_attribute( $image, 'width' );
246
+ $height = $this->get_attribute( $image, 'height' );
247
+
248
  // Can't use a relative width or height, so unset the dimensions in favor of not breaking things.
249
  if ( false !== strpos( $width, '%' ) || false !== strpos( $height, '%' ) ) {
250
  $width = false;
256
  $height = $height ? (int) $height : false;
257
  if ( $width && $height ) {
258
  $placeholder_src = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 $width $height'%3E%3C/svg%3E";
 
 
 
 
 
 
259
  }
260
  }
261
+ ewwwio_debug_message( "current placeholder is $placeholder_src" );
262
 
263
  if ( $srcset ) {
264
  $placeholder_src = apply_filters( 'ewww_image_optimizer_lazy_placeholder', $placeholder_src, $image );
357
  if ( false === strpos( $element, 'background:' ) && false === strpos( $element, 'background-image:' ) ) {
358
  continue;
359
  }
360
+ ewwwio_debug_message( 'element contains background/background-image:' );
361
  if ( ! $this->validate_bgimage_tag( $element ) ) {
362
  continue;
363
  }
364
+ ewwwio_debug_message( 'element is valid' );
365
  $style = $this->get_attribute( $element, 'style' );
366
  if ( empty( $style ) ) {
367
  continue;
369
  ewwwio_debug_message( "checking style attr for background-image: $style" );
370
  $bg_image_url = $this->get_background_image_url( $style );
371
  if ( $bg_image_url ) {
372
+ ewwwio_debug_message( 'bg-image url found' );
373
  $new_style = $this->remove_background_image( $style );
374
  if ( $style !== $new_style ) {
375
+ ewwwio_debug_message( 'style modified, continuing' );
376
  $this->set_attribute( $element, 'class', $this->get_attribute( $element, 'class' ) . ' lazyload', true );
377
  $this->set_attribute( $element, 'data-bg', $bg_image_url );
378
  $element = str_replace( $style, $new_style, $element );
379
  }
380
  }
381
  if ( $element !== $elements[ $index ] ) {
382
+ ewwwio_debug_message( "$tag_type modified, replacing in html source" );
383
  $buffer = str_replace( $elements[ $index ], $element, $buffer );
384
  }
385
  }
441
  'fullurl=',
442
  'gazette-featured-content-thumbnail',
443
  'lazy-slider-img=',
444
+ 'mgl-lazy',
445
  'skip-lazy',
446
  'timthumb.php?',
447
  'wpcf7_captcha/',
468
  'ewww_image_optimizer_lazy_bg_image_exclusions',
469
  array(
470
  'data-no-lazy=',
471
+ 'header-gallery-wrapper ',
472
  'lazyload',
473
  'skip-lazy',
474
  ),
482
  return true;
483
  }
484
 
485
+ /**
486
+ * Build a PNG inline image placeholder.
487
+ *
488
+ * @param int $width The width of the placeholder image.
489
+ * @param int $height The height of the placeholder image.
490
+ * @return string The PNG placeholder link.
491
+ */
492
+ function create_piip( $width = 1, $height = 1 ) {
493
+ $width = (int) $width;
494
+ $height = (int) $height;
495
+ if ( 1 === $width && 1 === $height ) {
496
+ return $this->placeholder_src;
497
+ }
498
+
499
+ $piip_path = $this->piip_folder . 'placeholder-' . $width . 'x' . $height . '.png';
500
+ if ( ! is_file( $piip_path ) ) {
501
+ $img = imagecreatetruecolor( $width, $height );
502
+ $color = imagecolorallocatealpha( $img, 0, 0, 0, 127 );
503
+ imagefill( $img, 0, 0, $color );
504
+ imagesavealpha( $img, true );
505
+ imagecolortransparent( $img, imagecolorat( $img, 0, 0 ) );
506
+ imagetruecolortopalette( $img, false, 1 );
507
+ imagepng( $img, $piip_path, 9 );
508
+ }
509
+ if ( is_file( $piip_path ) ) {
510
+ return content_url( 'ewww/lazy/placeholder-' . $width . 'x' . $height . '.png' );
511
+ }
512
+ return $this->placeholder_src;
513
+ }
514
+ /**
515
+ * Allow lazy loading of images for some admin-ajax requests.
516
+ *
517
+ * @param bool $allow Will normally be false, unless already modified by another function.
518
+ * @return bool True if it's an allowable admin-ajax request, false for all other admin requests.
519
+ */
520
+ function allow_admin_lazyload( $allow ) {
521
+ if ( ! wp_doing_ajax() ) {
522
+ return $allow;
523
+ }
524
+ if ( ! empty( $_POST['action'] ) && 'vc_get_vc_grid_data' === $_POST['action'] ) {
525
+ ewwwio_debug_message( 'allowing lazy on vc grid' );
526
+ return true;
527
+ }
528
+ if ( ! empty( $_POST['action'] ) && 'Essential_Grid_Front_request_ajax' === $_POST['action'] ) {
529
+ /* return true; */
530
+ }
531
+ return $allow;
532
+ }
533
+
534
  /**
535
  * Check if LQIP should be used, but allow filters to alter the option.
536
  *
544
  return $use_lqip;
545
  }
546
 
547
+ /**
548
+ * Check if PIIP should be used, but allow filters to alter the option.
549
+ *
550
+ * @param bool $use_piip Whether LL should use PNG inline image placeholders.
551
+ * @return bool True to use PIIP, false to skip them.
552
+ */
553
+ function maybe_piip( $use_piip ) {
554
+ if ( defined( 'EWWW_IMAGE_OPTIMIZER_USE_PIIP' ) && ! EWWW_IMAGE_OPTIMIZER_USE_PIIP ) {
555
+ return false;
556
+ }
557
+ return $use_piip;
558
+ }
559
+
560
  /**
561
  * Check if SIIP should be used, but allow filters to alter the option.
562
  *
582
  */
583
  function debug_script() {
584
  ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
585
+ if ( ewww_image_optimizer_is_amp() ) {
586
+ return;
587
+ }
588
  wp_enqueue_script( 'ewww-lazy-load-pre', plugins_url( '/includes/lazysizes-pre.js', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ), array(), EWWW_IMAGE_OPTIMIZER_VERSION );
589
  wp_enqueue_script( 'ewww-lazy-load', plugins_url( '/includes/lazysizes.js', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ), array(), EWWW_IMAGE_OPTIMIZER_VERSION );
590
  wp_enqueue_script( 'ewww-lazy-load-post', plugins_url( '/includes/lazysizes-post.js', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ), array(), EWWW_IMAGE_OPTIMIZER_VERSION );
603
  */
604
  function min_script() {
605
  ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
606
+ if ( ewww_image_optimizer_is_amp() ) {
607
+ return;
608
+ }
609
  wp_enqueue_script( 'ewww-lazy-load', plugins_url( '/includes/lazysizes.min.js', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ), array(), EWWW_IMAGE_OPTIMIZER_VERSION );
610
  wp_localize_script(
611
  'ewww-lazy-load',
classes/class-ewwwio-media-background-process.php CHANGED
@@ -71,7 +71,12 @@ class EWWWIO_Media_Background_Process extends EWWWIO_Background_Process {
71
  'image/gif',
72
  );
73
 
74
- $meta = wp_get_attachment_metadata( $id, true );
 
 
 
 
 
75
  if ( in_array( $type, $image_types, true ) && empty( $meta ) && $item['attempts'] < $max_attempts ) {
76
  $item['attempts']++;
77
  sleep( 4 );
@@ -91,7 +96,11 @@ class EWWWIO_Media_Background_Process extends EWWWIO_Background_Process {
91
  ewww_image_optimizer_debug_log();
92
  return $item;
93
  }
94
- wp_update_attachment_metadata( $id, $meta );
 
 
 
 
95
  ewww_image_optimizer_debug_log();
96
  delete_transient( 'ewwwio-background-in-progress-' . $id );
97
  return false;
71
  'image/gif',
72
  );
73
 
74
+ if ( in_array( $type, $image_types, true ) && $item['new'] && class_exists( 'wpCloud\StatelessMedia\EWWW' ) ) {
75
+ $meta = wp_get_attachment_metadata( $id );
76
+ } else {
77
+ // This is unfiltered for performance, because we don't often need filtered meta.
78
+ $meta = wp_get_attachment_metadata( $id, true );
79
+ }
80
  if ( in_array( $type, $image_types, true ) && empty( $meta ) && $item['attempts'] < $max_attempts ) {
81
  $item['attempts']++;
82
  sleep( 4 );
96
  ewww_image_optimizer_debug_log();
97
  return $item;
98
  }
99
+ if ( class_exists( 'wpCloud\StatelessMedia\EWWW' ) ) {
100
+ $meta = apply_filters( 'wp_update_attachment_metadata', wp_get_attachment_metadata( $image->attachment_id ), $image->attachment_id );
101
+ } else {
102
+ wp_update_attachment_metadata( $id, $meta );
103
+ }
104
  ewww_image_optimizer_debug_log();
105
  delete_transient( 'ewwwio-background-in-progress-' . $id );
106
  return false;
classes/class-ewwwio-page-parser.php CHANGED
@@ -205,13 +205,13 @@ class EWWWIO_Page_Parser {
205
  */
206
  function get_attribute( $element, $name ) {
207
  // Don't forget, back references cannot be used in character classes.
208
- if ( preg_match( '#[\s]' . $name . '\s*=\s*(["\'])([^"\']+?)\1#is', $element, $attr_matches ) ) {
209
  if ( ! empty( $attr_matches[2] ) ) {
210
  return $attr_matches[2];
211
  }
212
  }
213
  // If there were not any matches with quotes, look for unquoted attributes, no spaces or quotes allowed.
214
- if ( preg_match( '#[\s]' . $name . '\s*=\s*([^"\'][^\s>]+)#is', $element, $attr_matches ) ) {
215
  if ( ! empty( $attr_matches[1] ) ) {
216
  return $attr_matches[1];
217
  }
@@ -249,7 +249,7 @@ class EWWWIO_Page_Parser {
249
  $value = trim( $value );
250
  if ( $replace ) {
251
  // Don't forget, back references cannot be used in character classes.
252
- $new_element = preg_replace( '#\s' . $name . '\s*=\s*(["\'])[^"\']*?\1#is', " $name=$1$value$1", $element );
253
  if ( strpos( $new_element, "$name=" ) ) {
254
  $element = $new_element;
255
  return;
@@ -275,7 +275,7 @@ class EWWWIO_Page_Parser {
275
  */
276
  function remove_attribute( &$element, $name ) {
277
  // Don't forget, back references cannot be used in character classes.
278
- $element = preg_replace( '#\s' . $name . '\s*=\s*(["\'])[^"\']+?\1#is', ' ', $element );
279
  $element = preg_replace( '#\s' . $name . '\s*=\s*[^"\'][^\s>]+#is', ' ', $element );
280
  }
281
 
205
  */
206
  function get_attribute( $element, $name ) {
207
  // Don't forget, back references cannot be used in character classes.
208
+ if ( preg_match( '#\s' . $name . '\s*=\s*("|\')((?!\1).+?)\1#is', $element, $attr_matches ) ) {
209
  if ( ! empty( $attr_matches[2] ) ) {
210
  return $attr_matches[2];
211
  }
212
  }
213
  // If there were not any matches with quotes, look for unquoted attributes, no spaces or quotes allowed.
214
+ if ( preg_match( '#\s' . $name . '\s*=\s*([^"\'][^\s>]+)#is', $element, $attr_matches ) ) {
215
  if ( ! empty( $attr_matches[1] ) ) {
216
  return $attr_matches[1];
217
  }
249
  $value = trim( $value );
250
  if ( $replace ) {
251
  // Don't forget, back references cannot be used in character classes.
252
+ $new_element = preg_replace( '#\s' . $name . '\s*=\s*("|\')(?!\1).*?\1#is', " $name=$1$value$1", $element );
253
  if ( strpos( $new_element, "$name=" ) ) {
254
  $element = $new_element;
255
  return;
275
  */
276
  function remove_attribute( &$element, $name ) {
277
  // Don't forget, back references cannot be used in character classes.
278
+ $element = preg_replace( '#\s' . $name . '\s*=\s*("|\')(?!\1).+?\1#is', ' ', $element );
279
  $element = preg_replace( '#\s' . $name . '\s*=\s*[^"\'][^\s>]+#is', ' ', $element );
280
  }
281
 
classes/class-exactdn.php CHANGED
@@ -1098,7 +1098,7 @@ class ExactDN extends EWWWIO_Page_Parser {
1098
  if ( ! empty( $exactdn_url ) ) {
1099
  $src = $exactdn_url;
1100
  }
1101
- if ( $srcset_fill && ! ewww_image_optimizer_get_option( 'exactdn_prevent_srcset_fill' ) && false !== strpos( $src, $this->exactdn_domain ) ) {
1102
  if ( ! $this->get_attribute( $images['img_tag'][ $index ], $this->srcset_attr ) && ! $this->get_attribute( $images['img_tag'][ $index ], 'sizes' ) ) {
1103
  ewwwio_debug_message( "srcset filling with $src" );
1104
  $zoom = false;
1098
  if ( ! empty( $exactdn_url ) ) {
1099
  $src = $exactdn_url;
1100
  }
1101
+ if ( $srcset_fill && ( ! defined( 'EXACTDN_PREVENT_SRCSET_FILL' ) || ! EXACTDN_PREVENT_SRCSET_FILL ) && false !== strpos( $src, $this->exactdn_domain ) ) {
1102
  if ( ! $this->get_attribute( $images['img_tag'][ $index ], $this->srcset_attr ) && ! $this->get_attribute( $images['img_tag'][ $index ], 'sizes' ) ) {
1103
  ewwwio_debug_message( "srcset filling with $src" );
1104
  $zoom = false;
common.php CHANGED
@@ -22,7 +22,7 @@ if ( ! defined( 'ABSPATH' ) ) {
22
  exit;
23
  }
24
 
25
- define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '474.0' );
26
 
27
  // Initialize a couple globals.
28
  $ewww_debug = '';
@@ -63,7 +63,7 @@ if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_noauto' ) ) {
63
  // Resizes and auto-rotates images.
64
  add_filter( 'wp_handle_upload', 'ewww_image_optimizer_handle_upload' );
65
  }
66
- if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_editor' ) ) {
67
  // Turns off the ewwwio_image_editor during uploads.
68
  add_action( 'add_attachment', 'ewww_image_optimizer_add_attachment' );
69
  // Turns off ewwwio_image_editor during Enable Media Replace.
@@ -727,6 +727,8 @@ function ewww_image_optimizer_admin_init() {
727
  update_site_option( 'ewww_image_optimizer_resize_detection', $_POST['ewww_image_optimizer_resize_detection'] );
728
  $_POST['ewww_image_optimizer_resize_existing'] = ( empty( $_POST['ewww_image_optimizer_resize_existing'] ) ? false : true );
729
  update_site_option( 'ewww_image_optimizer_resize_existing', $_POST['ewww_image_optimizer_resize_existing'] );
 
 
730
  $_POST['ewww_image_optimizer_parallel_optimization'] = ( empty( $_POST['ewww_image_optimizer_parallel_optimization'] ) ? false : true );
731
  update_site_option( 'ewww_image_optimizer_parallel_optimization', $_POST['ewww_image_optimizer_parallel_optimization'] );
732
  $_POST['ewww_image_optimizer_include_media_paths'] = ( empty( $_POST['ewww_image_optimizer_include_media_paths'] ) ? false : true );
@@ -797,6 +799,7 @@ function ewww_image_optimizer_admin_init() {
797
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxmediawidth', 'intval' );
798
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxmediaheight', 'intval' );
799
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_resize_existing', 'boolval' );
 
800
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_disable_resizes', 'ewww_image_optimizer_disable_resizes_sanitize' );
801
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_disable_resizes_opt', 'ewww_image_optimizer_disable_resizes_sanitize' );
802
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_disable_convert_links', 'boolval' );
@@ -843,7 +846,7 @@ function ewww_image_optimizer_admin_init() {
843
  add_action( 'admin_notices', 'ewww_image_optimizer_thumbnail_regen_notice' );
844
  }
845
  }
846
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_wc_regen' ) ) {
847
  add_action( 'admin_notices', 'ewww_image_optimizer_notice_wc_regen' );
848
  add_action( 'admin_footer', 'ewww_image_optimizer_wc_regen_script' );
849
  }
@@ -851,8 +854,10 @@ function ewww_image_optimizer_admin_init() {
851
  add_action( 'admin_notices', 'ewww_image_optimizer_pngout_installed' );
852
  add_action( 'network_admin_notices', 'ewww_image_optimizer_pngout_installed' );
853
  }
854
- ewww_image_optimizer_privacy_policy_content();
855
- ewww_image_optimizer_ajax_compat_check();
 
 
856
  // Increase the version when the next bump is coming.
857
  if ( defined( 'PHP_VERSION_ID' ) && PHP_VERSION_ID < 50600 ) {
858
  add_action( 'network_admin_notices', 'ewww_image_optimizer_php55_warning' );
@@ -1151,6 +1156,7 @@ function ewww_image_optimizer_save_admin_colors() {
1151
  if (
1152
  is_array( $_wp_admin_css_colors ) &&
1153
  ! empty( $user_info->admin_color ) &&
 
1154
  is_object( $_wp_admin_css_colors[ $user_info->admin_color ] ) &&
1155
  is_array( $_wp_admin_css_colors[ $user_info->admin_color ]->colors ) &&
1156
  ! empty( $_wp_admin_css_colors[ $user_info->admin_color ]->colors[2] ) &&
@@ -1177,6 +1183,7 @@ function ewww_image_optimizer_admin_background() {
1177
  if (
1178
  is_array( $_wp_admin_css_colors ) &&
1179
  ! empty( $user_info->admin_color ) &&
 
1180
  is_object( $_wp_admin_css_colors[ $user_info->admin_color ] ) &&
1181
  is_array( $_wp_admin_css_colors[ $user_info->admin_color ]->colors ) &&
1182
  ! empty( $_wp_admin_css_colors[ $user_info->admin_color ]->colors[2] ) &&
@@ -1527,11 +1534,9 @@ function ewww_image_optimizer_wc_regen_script() {
1527
  * Let the user know they can view more options and stats in the Media Library's list mode.
1528
  */
1529
  function ewww_image_optimizer_notice_media_listmode() {
1530
- if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_dismiss_media_notice' ) ) {
1531
- $current_screen = get_current_screen();
1532
- if ( 'upload' === $current_screen->id ) {
1533
- echo "<div id='ewww-image-optimizer-media-listmode' class='notice notice-info is-dismissible'><p>" . esc_html__( 'Change the Media Library to List mode for additional image optimization information and actions.', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/62-power-user-options-in-list-mode', '5b61fdd32c7d3a03f89d41c4' ) . '</p></div>';
1534
- }
1535
  }
1536
  }
1537
 
@@ -1645,10 +1650,9 @@ function ewww_image_optimizer_image_sizes( $sizes ) {
1645
  */
1646
  function ewww_image_optimizer_restore_editor_hooks( $metadata = false ) {
1647
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1648
- if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_noauto' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_editor' ) ) {
1649
  global $ewww_preempt_editor;
1650
  $ewww_preempt_editor = false;
1651
- /* add_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 ); */
1652
  }
1653
  if ( function_exists( 'wr2x_wp_generate_attachment_metadata' ) ) {
1654
  remove_filter( 'wp_generate_attachment_metadata', 'wr2x_wp_generate_attachment_metadata' );
@@ -1675,7 +1679,7 @@ function ewww_image_optimizer_restore_editor_hooks( $metadata = false ) {
1675
  */
1676
  function ewww_image_optimizer_editor_save_pre( $image ) {
1677
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1678
- if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_noauto' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_editor' ) ) {
1679
  global $ewww_preempt_editor;
1680
  $ewww_preempt_editor = true;
1681
  add_filter( 'wp_update_attachment_metadata', 'ewww_image_optimizer_restore_editor_hooks', 1 );
@@ -1751,7 +1755,7 @@ function ewww_image_optimizer_path_renamed( $post, $old_filepath, $new_filepath
1751
  * @return array The unaltered metadata.
1752
  */
1753
  function ewww_image_optimizer_retina_wrapper( $meta ) {
1754
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_noauto' ) || ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_editor' ) ) {
1755
  return $meta;
1756
  }
1757
  global $ewww_preempt_editor;
@@ -2434,8 +2438,19 @@ function ewww_image_optimizer_aux_paths_sanitize( $input ) {
2434
  if ( empty( $input ) ) {
2435
  return '';
2436
  }
2437
- $path_array = array();
2438
- $paths = explode( "\n", $input );
 
 
 
 
 
 
 
 
 
 
 
2439
  if ( ewww_image_optimizer_iterable( $paths ) ) {
2440
  $i = 0;
2441
  foreach ( $paths as $path ) {
@@ -2446,12 +2461,24 @@ function ewww_image_optimizer_aux_paths_sanitize( $input ) {
2446
  $upload_dir = apply_filters( 'ewww_image_optimizer_folder_restriction', wp_upload_dir( null, false ) );
2447
  // Retrieve the path of the upload folder from the array.
2448
  $upload_path = trailingslashit( $upload_dir['basedir'] );
2449
- if ( is_dir( $path ) && ( strpos( $path, ABSPATH ) === 0 || strpos( $path, $upload_path ) === 0 ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
2450
  $path_array[] = $path;
2451
  continue;
2452
  }
2453
  // If they put in a relative path.
2454
- if ( is_dir( ABSPATH . ltrim( $path, '/' ) ) ) {
2455
  $path_array[] = ABSPATH . ltrim( $path, '/' );
2456
  continue;
2457
  }
@@ -2462,7 +2489,7 @@ function ewww_image_optimizer_aux_paths_sanitize( $input ) {
2462
  }
2463
  // What if they put in a url?
2464
  $pathabsurl = ABSPATH . ltrim( str_replace( get_site_url(), '', $path ), '/' );
2465
- if ( is_dir( $pathabsurl ) ) {
2466
  $path_array[] = $pathabsurl;
2467
  continue;
2468
  }
@@ -2717,8 +2744,7 @@ function ewww_image_optimizer_manual() {
2717
  } elseif ( 'ewww_image_optimizer_manual_restore' === $_REQUEST['action'] || 'ewww_manual_restore' === $_REQUEST['action'] ) {
2718
  $new_meta = ewww_image_optimizer_restore_from_meta_data( $original_meta, $attachment_id );
2719
  } elseif ( 'ewww_image_optimizer_manual_cloud_restore' === $_REQUEST['action'] || 'ewww_manual_cloud_restore' === $_REQUEST['action'] ) {
2720
- ewww_image_optimizer_cloud_restore_from_meta_data( $attachment_id, 'media' );
2721
- $new_meta = $original_meta;
2722
  } else {
2723
  if ( ! wp_doing_ajax() ) {
2724
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
@@ -2807,8 +2833,10 @@ function ewww_image_optimizer_restore_from_meta_data( $meta, $id ) {
2807
  *
2808
  * @param int $id The attachment id number.
2809
  * @param string $gallery Optional. The gallery from whence we came. Default 'media'.
 
 
2810
  */
2811
- function ewww_image_optimizer_cloud_restore_from_meta_data( $id, $gallery = 'media' ) {
2812
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
2813
  global $wpdb;
2814
  if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
@@ -2817,13 +2845,21 @@ function ewww_image_optimizer_cloud_restore_from_meta_data( $id, $gallery = 'med
2817
  } else {
2818
  $ewwwdb = $wpdb;
2819
  }
2820
- $images = $ewwwdb->get_results( "SELECT id,path,backup FROM $ewwwdb->ewwwio_images WHERE attachment_id = $id AND gallery = '$gallery'", ARRAY_A );
2821
  foreach ( $images as $image ) {
2822
  if ( ! empty( $image['path'] ) ) {
2823
  $image['path'] = ewww_image_optimizer_absolutize_path( $image['path'] );
2824
  }
2825
  ewww_image_optimizer_cloud_restore_single_image( $image );
 
 
 
 
 
 
 
2826
  }
 
2827
  }
2828
 
2829
  /**
@@ -3307,7 +3343,7 @@ function ewww_image_optimizer_cloud_quota( $raw = false ) {
3307
  )
3308
  );
3309
  } elseif ( $quota['licensed'] > 0 && $quota['consumed'] < 0 ) {
3310
- $real_quota = $quota['licensed'] - $quota['consumed'];
3311
  return esc_html(
3312
  sprintf(
3313
  /* translators: 1: Number of images */
@@ -3687,6 +3723,118 @@ function ewww_image_optimizer_cloud_autorotate( $file, $type ) {
3687
  }
3688
  }
3689
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3690
  /**
3691
  * Uses the API to resize images.
3692
  *
@@ -4154,6 +4302,7 @@ function ewww_image_optimizer_size_format( $size, $precision = 1 ) {
4154
  * @global object $ewwwdb A clone of $wpdb unless it is lacking utf8 connectivity.
4155
  * @global bool $ewww_defer Set to false to avoid deferring image optimization.
4156
  * @global string $ewww_debug Contains in-memory debug log.
 
4157
  *
4158
  * @param array $attachment {
4159
  * Optional. The file to optimize. Default null.
@@ -4210,6 +4359,13 @@ function ewww_image_optimizer_aux_images_loop( $attachment = null, $auto = false
4210
  if ( $attachment ) {
4211
  $attachment = ewww_image_optimizer_absolutize_path( $attachment );
4212
  }
 
 
 
 
 
 
 
4213
  // Do the optimization for the current image.
4214
  $results = ewww_image_optimizer( $attachment );
4215
  if ( ! $results[0] && is_numeric( $id ) ) {
@@ -4379,6 +4535,64 @@ function ewww_image_optimizer_remote_fetch( $id, $meta ) {
4379
  if ( ! function_exists( 'download_url' ) ) {
4380
  require_once( ABSPATH . '/wp-admin/includes/file.php' );
4381
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4382
  if ( class_exists( 'Amazon_S3_And_CloudFront' ) ) {
4383
  global $as3cf;
4384
  $full_url = get_attached_file( $id );
@@ -4680,7 +4894,7 @@ function ewww_image_optimizer_better_resize( $file, $dst_x, $dst_y, $src_x, $src
4680
  */
4681
  function ewww_image_optimizer_autorotate( $file ) {
4682
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
4683
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_autorotate' ) ) {
4684
  return;
4685
  }
4686
  if ( function_exists( 'wp_raise_memory_limit' ) ) {
@@ -4739,7 +4953,7 @@ function ewww_image_optimizer_autorotate( $file ) {
4739
  */
4740
  function ewww_image_optimizer_autoconvert( $file ) {
4741
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
4742
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_autoconvert' ) ) {
4743
  return;
4744
  }
4745
  if ( function_exists( 'wp_raise_memory_limit' ) ) {
@@ -4751,7 +4965,7 @@ function ewww_image_optimizer_autoconvert( $file ) {
4751
  return;
4752
  }
4753
  $orig_size = ewww_image_optimizer_filesize( $file );
4754
- if ( $orig_size < 300000 ) {
4755
  ewwwio_debug_message( 'not a large PNG, skipping' );
4756
  return;
4757
  }
@@ -4787,6 +5001,42 @@ function ewww_image_optimizer_noresize( $dimensions, $filename ) {
4787
  return $dimensions;
4788
  }
4789
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4790
  /**
4791
  * Resizes Media Library uploads based on the maximum dimensions specified by the user.
4792
  *
@@ -4931,9 +5181,8 @@ function ewww_image_optimizer_resize_upload( $file ) {
4931
  $error_message = $saved->get_error_message();
4932
  ewwwio_debug_message( "error saving resized image: $error_message" );
4933
  }
4934
- if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_noauto' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_editor' ) ) {
4935
  $ewww_preempt_editor = false;
4936
- /* add_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 ); */
4937
  }
4938
  // to here is replaced by cloud/API function.
4939
  $new_size = ewww_image_optimizer_filesize( $new_file );
@@ -4972,6 +5221,8 @@ function ewww_image_optimizer_resize_upload( $file ) {
4972
  }
4973
  $new_jpeg->saveFile( $new_file );
4974
  }
 
 
4975
  rename( $new_file, $file );
4976
  // Store info on the current image for future reference.
4977
  global $wpdb;
@@ -5326,28 +5577,8 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5326
  if ( ! is_array( $meta ) && empty( $meta ) ) {
5327
  $meta = array();
5328
  } elseif ( ! is_array( $meta ) ) {
5329
- if ( is_string( $meta ) && is_numeric( $id ) && 'processing' === $meta ) {
5330
- ewwwio_debug_message( "attempting to rebuild attachment meta for $id" );
5331
- $new_meta = ewww_image_optimizer_rebuild_meta( $id );
5332
- if ( ! is_array( $new_meta ) ) {
5333
- ewwwio_debug_message( 'attempt to rebuild attachment meta failed' );
5334
- return $meta;
5335
- } else {
5336
- $meta = $new_meta;
5337
- }
5338
- } else {
5339
- ewwwio_debug_message( 'attachment meta is not a usable array' );
5340
- return $meta;
5341
- }
5342
- } elseif ( is_array( $meta ) && ! empty( $meta[0] ) && 'processing' === $meta[0] ) {
5343
- ewwwio_debug_message( "attempting to rebuild attachment meta for $id" );
5344
- $new_meta = ewww_image_optimizer_rebuild_meta( $id );
5345
- if ( ! is_array( $new_meta ) ) {
5346
- ewwwio_debug_message( 'attempt to rebuild attachment meta failed' );
5347
- return $meta;
5348
- } else {
5349
- $meta = $new_meta;
5350
- }
5351
  }
5352
  global $wpdb;
5353
  if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
@@ -5370,7 +5601,18 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5370
  ewwwio_debug_message( 'this image already has metadata, so it is not new' );
5371
  $new_image = false;
5372
  }
 
5373
  list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
 
 
 
 
 
 
 
 
 
 
5374
  // If the attachment has been uploaded via the image store plugin.
5375
  if ( 'ims_image' === get_post_type( $id ) ) {
5376
  $gallery_type = 6;
@@ -5378,6 +5620,9 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5378
  if ( ! $new_image && class_exists( 'Amazon_S3_And_CloudFront' ) && ewww_image_optimizer_stream_wrapped( $file_path ) ) {
5379
  ewww_image_optimizer_check_table_as3cf( $meta, $id, $file_path );
5380
  }
 
 
 
5381
  // If the local file is missing and we have valid metadata, see if we can fetch via CDN.
5382
  if ( ! is_file( $file_path ) || ( ewww_image_optimizer_stream_wrapped( $file_path ) && ! class_exists( 'S3_Uploads' ) ) ) {
5383
  $file_path = ewww_image_optimizer_remote_fetch( $id, $meta );
@@ -5426,6 +5671,11 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5426
  );
5427
  }
5428
  }
 
 
 
 
 
5429
  // Resize here so long as this is not a new image AND resize existing is enabled, and imsanity isn't enabled with a max size.
5430
  if ( ( empty( $new_image ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' ) ) && ! function_exists( 'imsanity_get_max_width_height' ) ) {
5431
  $new_dimensions = ewww_image_optimizer_resize_upload( $file_path );
@@ -5436,7 +5686,7 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5436
  }
5437
  if ( ewww_image_optimizer_test_background_opt( $type ) ) {
5438
  add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
5439
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_defer_s3' ) ) {
5440
  ewwwio_debug_message( 's3 upload deferred' );
5441
  add_filter( 'as3cf_pre_update_attachment_metadata', '__return_true' );
5442
  }
@@ -5500,9 +5750,6 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5500
  $ewwwio_async_optimize_media = new EWWWIO_Async_Request();
5501
  }
5502
  } else {
5503
- $ewww_image = new EWWW_Image( $id, 'media', $file_path );
5504
- $ewww_image->resize = 'full';
5505
-
5506
  // Run the optimization and store the results.
5507
  list( $file, $msg, $conv, $original ) = ewww_image_optimizer( $file_path, $gallery_type, false, $new_image, true );
5508
 
@@ -6435,7 +6682,20 @@ function ewww_image_optimizer_custom_column( $column_name, $id, $meta = null, $r
6435
  $output .= '<div>' . esc_html__( 'Amazon S3 image', 'ewww-image-optimizer' ) . '</div>';
6436
  $ewww_cdn = true;
6437
  }
 
 
 
 
6438
  list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
 
 
 
 
 
 
 
 
 
6439
  // If the file does not exist.
6440
  if ( empty( $file_path ) && ! $ewww_cdn ) {
6441
  $output .= esc_html__( 'Could not retrieve file path.', 'ewww-image-optimizer' ) . '</div>';
@@ -7563,6 +7823,8 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7563
  ewwwio_debug_message( 'home url: ' . get_home_url() );
7564
  ewwwio_debug_message( 'site url: ' . get_site_url() );
7565
  ewwwio_debug_message( 'content_url: ' . content_url() );
 
 
7566
  ewwwio_debug_message( "content_width: $content_width" );
7567
  ewwwio_debug_message( 'registered stream wrappers: ' . implode( ',', stream_get_wrappers() ) );
7568
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_NOEXEC' ) ) {
@@ -8048,7 +8310,12 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8048
  ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_backup_files' ) ? "checked='true'" : '' ) . " $disable_level > " . esc_html__( 'Store a copy of your original images on our secure server for 30 days. *Requires an active API key.', 'ewww-image-optimizer' ) . "</td></tr>\n";
8049
  ewwwio_debug_message( 'backup mode: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_backup_files' ) ? 'on' : 'off' ) );
8050
  if ( class_exists( 'Cloudinary' ) && Cloudinary::config_get( 'api_secret' ) ) {
8051
- $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_enable_cloudinary'>" . esc_html__( 'Automatic Cloudinary Upload', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_enable_cloudinary' name='ewww_image_optimizer_enable_cloudinary' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_cloudinary' ) ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'When enabled, uploads to the Media Library will be transferred to Cloudinary after optimization. Cloudinary generates resizes, so only the full-size image is uploaded.', 'ewww-image-optimizer' ) . "</td></tr>\n";
 
 
 
 
 
8052
  ewwwio_debug_message( 'cloudinary upload: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_cloudinary' ) ? 'on' : 'off' ) );
8053
  }
8054
  $output[] = "</table>\n</div>\n";
@@ -8151,7 +8418,12 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8151
  ewwwio_debug_message( "invalid admin ajax url: $admin_ajax_url" );
8152
  }
8153
  }
8154
- $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_auto'>" . esc_html__( 'Scheduled Optimization', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/11-advanced-configuration', '58542afac697912ffd6c18c0,5853713bc697912ffd6c0b98' ) . "</th><td><input type='checkbox' id='ewww_image_optimizer_auto' name='ewww_image_optimizer_auto' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_auto' ) ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'This will enable scheduled optimization of unoptimized images for your theme, buddypress, and any additional folders you have configured below. Runs hourly: wp_cron only runs when your site is visited, so it may be even longer between optimizations.', 'ewww-image-optimizer' ) . "</td></tr>\n";
 
 
 
 
 
8155
  ewwwio_debug_message( 'scheduled optimization: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_auto' ) ? 'on' : 'off' ) );
8156
  $media_include_disable = '';
8157
  if ( get_option( 'ewww_image_optimizer_disable_resizes_opt' ) ) {
@@ -8186,20 +8458,25 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8186
  $output[] = "<div id='ewww-resize-settings'>\n";
8187
  $output[] = '<noscript><h2>' . esc_html__( 'Resize', 'ewww-image-optimizer' ) . '</h2></noscript>';
8188
  $output[] = "<table class='form-table'>\n";
8189
- $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_resize_detection'>" . esc_html__( 'Resize Detection', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/41-resize-settings', '59849911042863033a1ba5f9' ) . "</th><td><input type='checkbox' id='ewww_image_optimizer_resize_detection' name='ewww_image_optimizer_resize_detection' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_detection' ) ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Highlight images that need to be resized because the browser is scaling them down. Only visible for Admin users and adds a button to the admin bar to detect scaled images that have been lazy loaded.', 'ewww-image-optimizer' ) . "</td></tr>\n";
 
 
 
 
 
8190
  ewwwio_debug_message( 'resize detection: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_detection' ) ? 'on' : 'off' ) );
8191
  if ( function_exists( 'imsanity_get_max_width_height' ) ) {
8192
  $output[] = "<tr class='$network_class'><th>&nbsp;</th><td>" .
8193
  '<p><span style="color: #3eadc9">' . esc_html__( '*Imsanity settings override the EWWW resize dimensions.', 'ewww-image-optimizer' ) . "</span></p></td></tr>\n";
8194
  }
8195
- $output[] = "<tr class='$network_class'><th scope='row'>" . esc_html__( 'Resize Media Images', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/41-resize-settings', '59849911042863033a1ba5f9' ) .
8196
  "</th><td><label for='ewww_image_optimizer_maxmediawidth'>" . esc_html__( 'Max Width', 'ewww-image-optimizer' ) .
8197
  "</label> <input type='number' step='1' min='0' class='small-text' id='ewww_image_optimizer_maxmediawidth' name='ewww_image_optimizer_maxmediawidth' value='" .
8198
  ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' ) . ( function_exists( 'imsanity_get_max_width_height' ) ? "' disabled='disabled" : '' ) .
8199
  "' /> <label for='ewww_image_optimizer_maxmediaheight'>" . esc_html__( 'Max Height', 'ewww-image-optimizer' ) .
8200
  "</label> <input type='number' step='1' min='0' class='small-text' id='ewww_image_optimizer_maxmediaheight' name='ewww_image_optimizer_maxmediaheight' value='" .
8201
  ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' ) . ( function_exists( 'imsanity_get_max_width_height' ) ? "' disabled='disabled" : '' ) . "' /> " .
8202
- esc_html__( 'in pixels', 'ewww-image-optimizer' ) . "\n" . "<p class='description'>" . esc_html__( 'Resizes images uploaded to the Media Library.', 'ewww-image-optimizer' ) .
8203
  "</td></tr>\n";
8204
  ewwwio_debug_message( 'max media dimensions: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' ) . ' x ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' ) );
8205
  ewwwio_debug_message( 'max other dimensions: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherwidth' ) . ' x ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherheight' ) );
@@ -8209,6 +8486,12 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8209
  ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' ) ? "checked='true'" : '' ) . ' /> ' .
8210
  esc_html__( 'Allow resizing of existing Media Library images.', 'ewww-image-optimizer' ) . "</td></tr>\n";
8211
  ewwwio_debug_message( 'resize existing images: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' ) ? 'on' : 'off' ) );
 
 
 
 
 
 
8212
 
8213
  $output[] = '<tr class="network-singlesite"><th scope="row">' . esc_html__( 'Disable Resizes', 'ewww-image-optimizer' ) .
8214
  ewwwio_help_link( 'https://docs.ewww.io/article/41-resize-settings', '59849911042863033a1ba5f9,58598744c697912ffd6c3eb4' ) . '</th><td><p>' .
@@ -8633,6 +8916,9 @@ function ewww_image_optimizer_resize_detection_script() {
8633
  if ( ! current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', 'edit_others_posts' ) ) || 'wp-login.php' === basename( $_SERVER['SCRIPT_NAME'] ) ) {
8634
  return;
8635
  }
 
 
 
8636
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_detection' ) ) {
8637
  $resize_detection_script = file_get_contents( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'includes/resize_detection.js' );
8638
  echo "<style>\n" .
@@ -8641,7 +8927,7 @@ function ewww_image_optimizer_resize_detection_script() {
8641
  "\tmargin: -3px;\n" .
8642
  "}\n" .
8643
  "</style>\n";
8644
- echo "<script>$resize_detection_script</script>";
8645
  }
8646
  }
8647
 
@@ -8661,6 +8947,21 @@ function ewww_image_optimizer_autoptimize_js_exclude( $jsexcludes = '', $content
8661
  return $jsexcludes . ', includes/resize_detection.js';
8662
  }
8663
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8664
  /**
8665
  * Checks if admin bar is visible, and then adds the admin_bar_menu action.
8666
  */
22
  exit;
23
  }
24
 
25
+ define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '480.0' );
26
 
27
  // Initialize a couple globals.
28
  $ewww_debug = '';
63
  // Resizes and auto-rotates images.
64
  add_filter( 'wp_handle_upload', 'ewww_image_optimizer_handle_upload' );
65
  }
66
+ if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_DISABLE_EDITOR' ) || ! EWWW_IMAGE_OPTIMIZER_DISABLE_EDITOR ) {
67
  // Turns off the ewwwio_image_editor during uploads.
68
  add_action( 'add_attachment', 'ewww_image_optimizer_add_attachment' );
69
  // Turns off ewwwio_image_editor during Enable Media Replace.
727
  update_site_option( 'ewww_image_optimizer_resize_detection', $_POST['ewww_image_optimizer_resize_detection'] );
728
  $_POST['ewww_image_optimizer_resize_existing'] = ( empty( $_POST['ewww_image_optimizer_resize_existing'] ) ? false : true );
729
  update_site_option( 'ewww_image_optimizer_resize_existing', $_POST['ewww_image_optimizer_resize_existing'] );
730
+ $_POST['ewww_image_optimizer_resize_other_existing'] = ( empty( $_POST['ewww_image_optimizer_resize_other_existing'] ) ? false : true );
731
+ update_site_option( 'ewww_image_optimizer_resize_other_existing', $_POST['ewww_image_optimizer_resize_other_existing'] );
732
  $_POST['ewww_image_optimizer_parallel_optimization'] = ( empty( $_POST['ewww_image_optimizer_parallel_optimization'] ) ? false : true );
733
  update_site_option( 'ewww_image_optimizer_parallel_optimization', $_POST['ewww_image_optimizer_parallel_optimization'] );
734
  $_POST['ewww_image_optimizer_include_media_paths'] = ( empty( $_POST['ewww_image_optimizer_include_media_paths'] ) ? false : true );
799
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxmediawidth', 'intval' );
800
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxmediaheight', 'intval' );
801
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_resize_existing', 'boolval' );
802
+ register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_resize_other_existing', 'boolval' );
803
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_disable_resizes', 'ewww_image_optimizer_disable_resizes_sanitize' );
804
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_disable_resizes_opt', 'ewww_image_optimizer_disable_resizes_sanitize' );
805
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_disable_convert_links', 'boolval' );
846
  add_action( 'admin_notices', 'ewww_image_optimizer_thumbnail_regen_notice' );
847
  }
848
  }
849
+ if ( class_exists( 'WooCommerce' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_wc_regen' ) ) {
850
  add_action( 'admin_notices', 'ewww_image_optimizer_notice_wc_regen' );
851
  add_action( 'admin_footer', 'ewww_image_optimizer_wc_regen_script' );
852
  }
854
  add_action( 'admin_notices', 'ewww_image_optimizer_pngout_installed' );
855
  add_action( 'network_admin_notices', 'ewww_image_optimizer_pngout_installed' );
856
  }
857
+ if ( ! defined( 'WP_CLI' ) || ! WP_CLI ) {
858
+ ewww_image_optimizer_privacy_policy_content();
859
+ ewww_image_optimizer_ajax_compat_check();
860
+ }
861
  // Increase the version when the next bump is coming.
862
  if ( defined( 'PHP_VERSION_ID' ) && PHP_VERSION_ID < 50600 ) {
863
  add_action( 'network_admin_notices', 'ewww_image_optimizer_php55_warning' );
1156
  if (
1157
  is_array( $_wp_admin_css_colors ) &&
1158
  ! empty( $user_info->admin_color ) &&
1159
+ isset( $_wp_admin_css_colors[ $user_info->admin_color ] ) &&
1160
  is_object( $_wp_admin_css_colors[ $user_info->admin_color ] ) &&
1161
  is_array( $_wp_admin_css_colors[ $user_info->admin_color ]->colors ) &&
1162
  ! empty( $_wp_admin_css_colors[ $user_info->admin_color ]->colors[2] ) &&
1183
  if (
1184
  is_array( $_wp_admin_css_colors ) &&
1185
  ! empty( $user_info->admin_color ) &&
1186
+ isset( $_wp_admin_css_colors[ $user_info->admin_color ] ) &&
1187
  is_object( $_wp_admin_css_colors[ $user_info->admin_color ] ) &&
1188
  is_array( $_wp_admin_css_colors[ $user_info->admin_color ]->colors ) &&
1189
  ! empty( $_wp_admin_css_colors[ $user_info->admin_color ]->colors[2] ) &&
1534
  * Let the user know they can view more options and stats in the Media Library's list mode.
1535
  */
1536
  function ewww_image_optimizer_notice_media_listmode() {
1537
+ $current_screen = get_current_screen();
1538
+ if ( 'upload' === $current_screen->id && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_dismiss_media_notice' ) ) {
1539
+ echo "<div id='ewww-image-optimizer-media-listmode' class='notice notice-info is-dismissible'><p>" . esc_html__( 'Change the Media Library to List mode for additional image optimization information and actions.', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/62-power-user-options-in-list-mode', '5b61fdd32c7d3a03f89d41c4' ) . '</p></div>';
 
 
1540
  }
1541
  }
1542
 
1650
  */
1651
  function ewww_image_optimizer_restore_editor_hooks( $metadata = false ) {
1652
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1653
+ if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_noauto' ) && ( ! defined( 'EWWW_IMAGE_OPTIMIZER_DISABLE_EDITOR' ) || ! EWWW_IMAGE_OPTIMIZER_DISABLE_EDITOR ) ) {
1654
  global $ewww_preempt_editor;
1655
  $ewww_preempt_editor = false;
 
1656
  }
1657
  if ( function_exists( 'wr2x_wp_generate_attachment_metadata' ) ) {
1658
  remove_filter( 'wp_generate_attachment_metadata', 'wr2x_wp_generate_attachment_metadata' );
1679
  */
1680
  function ewww_image_optimizer_editor_save_pre( $image ) {
1681
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1682
+ if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_noauto' ) && ( ! defined( 'EWWW_IMAGE_OPTIMIZER_DISABLE_EDITOR' ) || ! EWWW_IMAGE_OPTIMIZER_DISABLE_EDITOR ) ) {
1683
  global $ewww_preempt_editor;
1684
  $ewww_preempt_editor = true;
1685
  add_filter( 'wp_update_attachment_metadata', 'ewww_image_optimizer_restore_editor_hooks', 1 );
1755
  * @return array The unaltered metadata.
1756
  */
1757
  function ewww_image_optimizer_retina_wrapper( $meta ) {
1758
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_noauto' ) || ( defined( 'EWWW_IMAGE_OPTIMIZER_DISABLE_EDITOR' ) && EWWW_IMAGE_OPTIMIZER_DISABLE_EDITOR ) ) {
1759
  return $meta;
1760
  }
1761
  global $ewww_preempt_editor;
2438
  if ( empty( $input ) ) {
2439
  return '';
2440
  }
2441
+ $path_array = array();
2442
+ $paths = explode( "\n", $input );
2443
+ $abspath = false;
2444
+ $permissions = apply_filters( 'ewww_image_optimizer_superadmin_permissions', '' );
2445
+ if ( is_multisite() && current_user_can( $permissions ) ) {
2446
+ $abspath = true;
2447
+ } elseif ( ! is_multisite() ) {
2448
+ $abspath = true;
2449
+ }
2450
+ $blog_one = false;
2451
+ if ( 1 === get_current_blog_id() ) {
2452
+ $blog_one = true;
2453
+ }
2454
  if ( ewww_image_optimizer_iterable( $paths ) ) {
2455
  $i = 0;
2456
  foreach ( $paths as $path ) {
2461
  $upload_dir = apply_filters( 'ewww_image_optimizer_folder_restriction', wp_upload_dir( null, false ) );
2462
  // Retrieve the path of the upload folder from the array.
2463
  $upload_path = trailingslashit( $upload_dir['basedir'] );
2464
+ if ( ! $abspath && $blog_one && false !== strpos( $path, $upload_path . 'sites' ) ) {
2465
+ add_settings_error(
2466
+ 'ewww_image_optimizer_aux_paths',
2467
+ "ewwwio-aux-paths-$i",
2468
+ sprintf(
2469
+ /* translators: %s: A file system path */
2470
+ esc_html__( 'Could not save Folder to Optimize: %s. Access denied.', 'ewww-image-optimizer' ),
2471
+ esc_html( $path )
2472
+ )
2473
+ );
2474
+ continue;
2475
+ }
2476
+ if ( is_dir( $path ) && ( ( $abspath && strpos( $path, ABSPATH ) === 0 ) || strpos( $path, $upload_path ) === 0 ) ) {
2477
  $path_array[] = $path;
2478
  continue;
2479
  }
2480
  // If they put in a relative path.
2481
+ if ( $abspath && is_dir( ABSPATH . ltrim( $path, '/' ) ) ) {
2482
  $path_array[] = ABSPATH . ltrim( $path, '/' );
2483
  continue;
2484
  }
2489
  }
2490
  // What if they put in a url?
2491
  $pathabsurl = ABSPATH . ltrim( str_replace( get_site_url(), '', $path ), '/' );
2492
+ if ( $abspath && is_dir( $pathabsurl ) ) {
2493
  $path_array[] = $pathabsurl;
2494
  continue;
2495
  }
2744
  } elseif ( 'ewww_image_optimizer_manual_restore' === $_REQUEST['action'] || 'ewww_manual_restore' === $_REQUEST['action'] ) {
2745
  $new_meta = ewww_image_optimizer_restore_from_meta_data( $original_meta, $attachment_id );
2746
  } elseif ( 'ewww_image_optimizer_manual_cloud_restore' === $_REQUEST['action'] || 'ewww_manual_cloud_restore' === $_REQUEST['action'] ) {
2747
+ $new_meta = ewww_image_optimizer_cloud_restore_from_meta_data( $attachment_id, 'media', $original_meta );
 
2748
  } else {
2749
  if ( ! wp_doing_ajax() ) {
2750
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
2833
  *
2834
  * @param int $id The attachment id number.
2835
  * @param string $gallery Optional. The gallery from whence we came. Default 'media'.
2836
+ * @param array $meta Optional. The image metadata from the postmeta table.
2837
+ * @return array The altered meta (if size differs), or the original value passed along.
2838
  */
2839
+ function ewww_image_optimizer_cloud_restore_from_meta_data( $id, $gallery = 'media', $meta = array() ) {
2840
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
2841
  global $wpdb;
2842
  if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
2845
  } else {
2846
  $ewwwdb = $wpdb;
2847
  }
2848
+ $images = $ewwwdb->get_results( "SELECT id,path,resize,backup FROM $ewwwdb->ewwwio_images WHERE attachment_id = $id AND gallery = '$gallery'", ARRAY_A );
2849
  foreach ( $images as $image ) {
2850
  if ( ! empty( $image['path'] ) ) {
2851
  $image['path'] = ewww_image_optimizer_absolutize_path( $image['path'] );
2852
  }
2853
  ewww_image_optimizer_cloud_restore_single_image( $image );
2854
+ if ( 'media' === $gallery && 'full' === $image['resize'] && ! empty( $meta['width'] ) && ! empty( $meta['height'] ) ) {
2855
+ list( $width, $height ) = getimagesize( $image['path'] );
2856
+ if ( (int) $width !== (int) $meta['width'] || (int) $height !== (int) $meta['height'] ) {
2857
+ $meta['height'] = $height;
2858
+ $meta['width'] = $width;
2859
+ }
2860
+ }
2861
  }
2862
+ return $meta;
2863
  }
2864
 
2865
  /**
3343
  )
3344
  );
3345
  } elseif ( $quota['licensed'] > 0 && $quota['consumed'] < 0 ) {
3346
+ $real_quota = (int) $quota['licensed'] - (int) $quota['consumed'];
3347
  return esc_html(
3348
  sprintf(
3349
  /* translators: 1: Number of images */
3723
  }
3724
  }
3725
 
3726
+ /**
3727
+ * Backup an image using API servers.
3728
+ *
3729
+ * @since 4.8.0
3730
+ *
3731
+ * @param string $file Name of the file to backup.
3732
+ */
3733
+ function ewww_image_optimizer_cloud_backup( $file ) {
3734
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
3735
+ $api_key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
3736
+ if ( empty( $api_key ) ) {
3737
+ return false;
3738
+ }
3739
+ if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_backup_files' ) ) {
3740
+ return false;
3741
+ }
3742
+ if ( ! is_file( $file ) ) {
3743
+ return false;
3744
+ }
3745
+ if ( ! ewwwio_check_memory_available( filesize( $file ) * 1.1 ) ) { // 1.1 = upload buffer (filesize) multiplied by a factor of 1.1 for extra wiggle room.
3746
+ $memory_required = filesize( $file ) * 1.1;
3747
+ ewwwio_debug_message( "possibly insufficient memory for cloud (backup) operation: $memory_required" );
3748
+ if ( function_exists( 'wp_raise_memory_limit' ) ) {
3749
+ add_filter( 'image_memory_limit', 'ewww_image_optimizer_raise_memory_limit' );
3750
+ wp_raise_memory_limit( 'image' );
3751
+ }
3752
+ ewww_image_optimizer_debug_log();
3753
+ }
3754
+ if ( ! ewww_image_optimizer_cloud_verify() ) {
3755
+ ewwwio_debug_message( 'cloud verify failed, image not backed up' );
3756
+ return false;
3757
+ }
3758
+ ewwwio_debug_message( "file: $file " );
3759
+ $url = 'http://optimize.exactlywww.com/backup/store.php';
3760
+ $ssl = wp_http_supports( array( 'ssl' ) );
3761
+ if ( $ssl ) {
3762
+ $url = set_url_scheme( $url, 'https' );
3763
+ }
3764
+ $boundary = wp_generate_password( 24, false );
3765
+
3766
+ $headers = array(
3767
+ 'content-type' => 'multipart/form-data; boundary=' . $boundary,
3768
+ 'timeout' => 20,
3769
+ 'httpversion' => '1.0',
3770
+ 'blocking' => true,
3771
+ );
3772
+
3773
+ $post_fields = array(
3774
+ 'filename' => $file,
3775
+ 'api_key' => $api_key,
3776
+ );
3777
+
3778
+ global $ewww_image;
3779
+ if ( is_object( $ewww_image ) && $ewww_image->file === $file && ! empty( $ewww_image->backup ) ) {
3780
+ $post_fields['backup'] = $ewww_image->backup;
3781
+ } elseif ( is_object( $ewww_image ) && $ewww_image->file === $file && empty( $ewww_image->backup ) ) {
3782
+ $post_fields['backup'] = uniqid() . hash( 'sha256', $file );
3783
+ $ewww_image->backup = $post_fields['backup'];
3784
+ } else {
3785
+ ewwwio_debug_message( 'probably a new upload, not backing up yet' );
3786
+ return false;
3787
+ }
3788
+ $payload = '';
3789
+ foreach ( $post_fields as $name => $value ) {
3790
+ $payload .= '--' . $boundary;
3791
+ $payload .= "\r\n";
3792
+ $payload .= 'Content-Disposition: form-data; name="' . $name . '"' . "\r\n\r\n";
3793
+ $payload .= $value;
3794
+ $payload .= "\r\n";
3795
+ }
3796
+
3797
+ $payload .= '--' . $boundary;
3798
+ $payload .= "\r\n";
3799
+ $payload .= 'Content-Disposition: form-data; name="file"; filename="' . basename( $file ) . '"' . "\r\n";
3800
+ $payload .= 'Content-Type: ' . ewww_image_optimizer_mimetype( $file, 'i' ) . "\r\n";
3801
+ $payload .= "\r\n";
3802
+ $payload .= file_get_contents( $file );
3803
+ $payload .= "\r\n";
3804
+ $payload .= '--' . $boundary;
3805
+ $payload .= 'Content-Disposition: form-data; name="submitHandler"' . "\r\n";
3806
+ $payload .= "\r\n";
3807
+ $payload .= "Upload\r\n";
3808
+ $payload .= '--' . $boundary . '--';
3809
+
3810
+ add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
3811
+ $response = wp_remote_post(
3812
+ $url,
3813
+ array(
3814
+ 'timeout' => 20,
3815
+ 'headers' => $headers,
3816
+ 'sslverify' => false,
3817
+ 'body' => $payload,
3818
+ )
3819
+ );
3820
+ if ( is_wp_error( $response ) ) {
3821
+ $error_message = $response->get_error_message();
3822
+ ewwwio_debug_message( "backup failed: $error_message" );
3823
+ return false;
3824
+ } else {
3825
+ if ( false !== strpos( $response['body'], 'error' ) ) {
3826
+ return false;
3827
+ } elseif ( false !== strpos( $response['body'], 'success' ) ) {
3828
+ ewwwio_debug_message( 'cloud backup success' );
3829
+ return true;
3830
+ } else {
3831
+ return false;
3832
+ }
3833
+ }
3834
+ ewwwio_memory( __FUNCTION__ );
3835
+ return false;
3836
+ }
3837
+
3838
  /**
3839
  * Uses the API to resize images.
3840
  *
4302
  * @global object $ewwwdb A clone of $wpdb unless it is lacking utf8 connectivity.
4303
  * @global bool $ewww_defer Set to false to avoid deferring image optimization.
4304
  * @global string $ewww_debug Contains in-memory debug log.
4305
+ * @global object $ewww_image Contains more information about the image currently being processed.
4306
  *
4307
  * @param array $attachment {
4308
  * Optional. The file to optimize. Default null.
4359
  if ( $attachment ) {
4360
  $attachment = ewww_image_optimizer_absolutize_path( $attachment );
4361
  }
4362
+ global $ewww_image;
4363
+ $ewww_image = new EWWW_Image( 0, '', $attachment );
4364
+ // Resize the image, if possible.
4365
+ if ( empty( $ewww_image->resize ) && ewww_image_optimizer_should_resize_other_image( $ewww_image->file ) ) {
4366
+ $new_dimensions = ewww_image_optimizer_resize_upload( $attachment );
4367
+ }
4368
+
4369
  // Do the optimization for the current image.
4370
  $results = ewww_image_optimizer( $attachment );
4371
  if ( ! $results[0] && is_numeric( $id ) ) {
4535
  if ( ! function_exists( 'download_url' ) ) {
4536
  require_once( ABSPATH . '/wp-admin/includes/file.php' );
4537
  }
4538
+ if ( class_exists( 'wpCloud\StatelessMedia\EWWW' ) && ! empty( $meta['gs_link'] ) ) {
4539
+ $full_url = $meta['gs_link'];
4540
+ $filename = get_attached_file( $id, true );
4541
+ ewwwio_debug_message( "GSC (stateless) fullsize url: $full_url" );
4542
+ ewwwio_debug_message( "unfiltered fullsize path: $filename" );
4543
+ $temp_file = download_url( $full_url );
4544
+ if ( ! is_wp_error( $temp_file ) ) {
4545
+ if ( ! is_dir( dirname( $filename ) ) ) {
4546
+ wp_mkdir_p( dirname( $filename ) );
4547
+ }
4548
+ rename( $temp_file, $filename );
4549
+ }
4550
+ // Resized versions, so we'll grab those too.
4551
+ if ( isset( $meta['sizes'] ) && ewww_image_optimizer_iterable( $meta['sizes'] ) ) {
4552
+ $disabled_sizes = get_option( 'ewww_image_optimizer_disable_resizes_opt' );
4553
+ ewwwio_debug_message( 'retrieving resizes' );
4554
+ // Meta sizes don't contain a path, so we calculate one.
4555
+ $base_dir = trailingslashit( dirname( $filename ) );
4556
+ $processed = array();
4557
+ foreach ( $meta['sizes'] as $size => $data ) {
4558
+ ewwwio_debug_message( "processing size: $size" );
4559
+ if ( preg_match( '/webp/', $size ) ) {
4560
+ continue;
4561
+ }
4562
+ if ( ! empty( $disabled_sizes[ $size ] ) ) {
4563
+ continue;
4564
+ }
4565
+ if ( empty( $data['file'] ) ) {
4566
+ continue;
4567
+ }
4568
+ $dup_size = false;
4569
+ // Check through all the sizes we've processed so far.
4570
+ foreach ( $processed as $proc => $scan ) {
4571
+ // If a previous resize had identical dimensions.
4572
+ if ( $scan['height'] === $data['height'] && $scan['width'] === $data['width'] ) {
4573
+ // Found a duplicate resize.
4574
+ $dup_size = true;
4575
+ }
4576
+ }
4577
+ // If this is a unique size.
4578
+ if ( ! $dup_size ) {
4579
+ $resize_path = $base_dir . $data['file'];
4580
+ $resize_url = $data['gs_link'];
4581
+ ewwwio_debug_message( "fetching $resize_url to $resize_path" );
4582
+ $temp_file = download_url( $resize_url );
4583
+ if ( ! is_wp_error( $temp_file ) ) {
4584
+ if ( ! is_dir( dirname( $resize_path ) ) ) {
4585
+ wp_mkdir_p( dirname( $resize_path ) );
4586
+ }
4587
+ rename( $temp_file, $resize_path );
4588
+ }
4589
+ }
4590
+ // Store info on the sizes we've processed, so we can check the list for duplicate sizes.
4591
+ $processed[ $size ]['width'] = $data['width'];
4592
+ $processed[ $size ]['height'] = $data['height'];
4593
+ }
4594
+ } // End if().
4595
+ } // End if().
4596
  if ( class_exists( 'Amazon_S3_And_CloudFront' ) ) {
4597
  global $as3cf;
4598
  $full_url = get_attached_file( $id );
4894
  */
4895
  function ewww_image_optimizer_autorotate( $file ) {
4896
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
4897
+ if ( defined( 'EWWW_IMAGE_OPTIMIZER_DISABLE_AUTOROTATE' ) && EWWW_IMAGE_OPTIMIZER_DISABLE_AUTOROTATE ) {
4898
  return;
4899
  }
4900
  if ( function_exists( 'wp_raise_memory_limit' ) ) {
4953
  */
4954
  function ewww_image_optimizer_autoconvert( $file ) {
4955
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
4956
+ if ( defined( 'EWWW_IMAGE_OPTIMIZER_DISABLE_AUTOCONVERT' ) && EWWW_IMAGE_OPTIMIZER_DISABLE_AUTOCONVERT ) {
4957
  return;
4958
  }
4959
  if ( function_exists( 'wp_raise_memory_limit' ) ) {
4965
  return;
4966
  }
4967
  $orig_size = ewww_image_optimizer_filesize( $file );
4968
+ if ( $orig_size < apply_filters( 'ewww_image_optimizer_autoconvert_threshold', 300000 ) ) {
4969
  ewwwio_debug_message( 'not a large PNG, skipping' );
4970
  return;
4971
  }
5001
  return $dimensions;
5002
  }
5003
 
5004
+ /**
5005
+ * Check non-Media Library filenames to see if the image is eligible for resizing.
5006
+ *
5007
+ * @param string $file The image filename.
5008
+ * @return bool True to allow resizing, false otherwise.
5009
+ */
5010
+ function ewww_image_optimizer_should_resize_other_image( $file ) {
5011
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
5012
+ if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_other_existing' ) ) {
5013
+ return false;
5014
+ }
5015
+ $extensions = array(
5016
+ 'gif',
5017
+ 'jpg',
5018
+ 'jpeg',
5019
+ 'jpe',
5020
+ 'png',
5021
+ );
5022
+ if ( preg_match( '#-(\d+)x(\d+)(@2x)?\.(?:' . implode( '|', $extensions ) . ')$#i', $file ) ) {
5023
+ return false;
5024
+ }
5025
+ if ( strpos( $file, '/wp-includes/' ) ) {
5026
+ return false;
5027
+ }
5028
+ if ( strpos( $file, '/wp-admin/' ) ) {
5029
+ return false;
5030
+ }
5031
+ if ( false !== strpos( $file, get_theme_root() ) ) {
5032
+ return false;
5033
+ }
5034
+ if ( false !== strpos( $file, WP_PLUGIN_DIR ) ) {
5035
+ return false;
5036
+ }
5037
+ ewwwio_debug_message( "allowing resize for $file" );
5038
+ return true;
5039
+ }
5040
  /**
5041
  * Resizes Media Library uploads based on the maximum dimensions specified by the user.
5042
  *
5181
  $error_message = $saved->get_error_message();
5182
  ewwwio_debug_message( "error saving resized image: $error_message" );
5183
  }
5184
+ if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_noauto' ) && ( ! defined( 'EWWW_IMAGE_OPTIMIZER_DISABLE_EDITOR' ) || ! EWWW_IMAGE_OPTIMIZER_DISABLE_EDITOR ) ) {
5185
  $ewww_preempt_editor = false;
 
5186
  }
5187
  // to here is replaced by cloud/API function.
5188
  $new_size = ewww_image_optimizer_filesize( $new_file );
5221
  }
5222
  $new_jpeg->saveFile( $new_file );
5223
  }
5224
+ // backup the file to the API, right before we replace the original.
5225
+ ewww_image_optimizer_cloud_backup( $file );
5226
  rename( $new_file, $file );
5227
  // Store info on the current image for future reference.
5228
  global $wpdb;
5577
  if ( ! is_array( $meta ) && empty( $meta ) ) {
5578
  $meta = array();
5579
  } elseif ( ! is_array( $meta ) ) {
5580
+ ewwwio_debug_message( 'attachment meta is not a usable array' );
5581
+ return $meta;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5582
  }
5583
  global $wpdb;
5584
  if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
5601
  ewwwio_debug_message( 'this image already has metadata, so it is not new' );
5602
  $new_image = false;
5603
  }
5604
+
5605
  list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
5606
+
5607
+ /**
5608
+ * Allow altering the metadata or performing other actions before the plugin processes an attachement.
5609
+ *
5610
+ * @param array $meta The attachment metadata.
5611
+ * @param string $file_path The file path to the image.
5612
+ * @param bool $new_image True if this is a newly uploaded image, false otherwise.
5613
+ */
5614
+ $meta = apply_filters( 'ewww_image_optimizer_resize_from_meta_data', $meta, $file_path, $new_image );
5615
+
5616
  // If the attachment has been uploaded via the image store plugin.
5617
  if ( 'ims_image' === get_post_type( $id ) ) {
5618
  $gallery_type = 6;
5620
  if ( ! $new_image && class_exists( 'Amazon_S3_And_CloudFront' ) && ewww_image_optimizer_stream_wrapped( $file_path ) ) {
5621
  ewww_image_optimizer_check_table_as3cf( $meta, $id, $file_path );
5622
  }
5623
+ if ( ! is_file( $file_path ) && class_exists( 'wpCloud\StatelessMedia\EWWW' ) && ! empty( $meta['gs_link'] ) ) {
5624
+ $file_path = ewww_image_optimizer_remote_fetch( $id, $meta );
5625
+ }
5626
  // If the local file is missing and we have valid metadata, see if we can fetch via CDN.
5627
  if ( ! is_file( $file_path ) || ( ewww_image_optimizer_stream_wrapped( $file_path ) && ! class_exists( 'S3_Uploads' ) ) ) {
5628
  $file_path = ewww_image_optimizer_remote_fetch( $id, $meta );
5671
  );
5672
  }
5673
  }
5674
+
5675
+ // Initialize an EWWW_Image object for the full-size image so that the original will be backed up before any potential resizing operations.
5676
+ $ewww_image = new EWWW_Image( $id, 'media', $file_path );
5677
+ $ewww_image->resize = 'full';
5678
+
5679
  // Resize here so long as this is not a new image AND resize existing is enabled, and imsanity isn't enabled with a max size.
5680
  if ( ( empty( $new_image ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' ) ) && ! function_exists( 'imsanity_get_max_width_height' ) ) {
5681
  $new_dimensions = ewww_image_optimizer_resize_upload( $file_path );
5686
  }
5687
  if ( ewww_image_optimizer_test_background_opt( $type ) ) {
5688
  add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
5689
+ if ( defined( 'EWWW_IMAGE_OPTIMIZER_DEFER_S3' ) && EWWW_IMAGE_OPTIMIZER_DEFER_S3 ) {
5690
  ewwwio_debug_message( 's3 upload deferred' );
5691
  add_filter( 'as3cf_pre_update_attachment_metadata', '__return_true' );
5692
  }
5750
  $ewwwio_async_optimize_media = new EWWWIO_Async_Request();
5751
  }
5752
  } else {
 
 
 
5753
  // Run the optimization and store the results.
5754
  list( $file, $msg, $conv, $original ) = ewww_image_optimizer( $file_path, $gallery_type, false, $new_image, true );
5755
 
6682
  $output .= '<div>' . esc_html__( 'Amazon S3 image', 'ewww-image-optimizer' ) . '</div>';
6683
  $ewww_cdn = true;
6684
  }
6685
+ if ( is_array( $meta ) & class_exists( 'wpCloud\StatelessMedia\EWWW' ) && ! empty( $meta['gs_link'] ) ) {
6686
+ $output .= '<div>' . esc_html__( 'WP Stateless image', 'ewww-image-optimizer' ) . '</div>';
6687
+ $ewww_cdn = true;
6688
+ }
6689
  list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
6690
+ if ( is_array( $meta ) & function_exists( 'ilab_get_image_sizes' ) && ! empty( $meta['s3'] ) && empty( $file_path ) ) {
6691
+ $output .= '<div>' . esc_html__( 'Media Cloud image', 'ewww-image-optimizer' ) . '</div>';
6692
+ $ewww_cdn = true;
6693
+ if ( $return_output ) {
6694
+ return $output;
6695
+ }
6696
+ echo $output;
6697
+ return;
6698
+ }
6699
  // If the file does not exist.
6700
  if ( empty( $file_path ) && ! $ewww_cdn ) {
6701
  $output .= esc_html__( 'Could not retrieve file path.', 'ewww-image-optimizer' ) . '</div>';
7823
  ewwwio_debug_message( 'home url: ' . get_home_url() );
7824
  ewwwio_debug_message( 'site url: ' . get_site_url() );
7825
  ewwwio_debug_message( 'content_url: ' . content_url() );
7826
+ $upload_info = wp_upload_dir( null, false );
7827
+ ewwwio_debug_message( 'upload_dir: ' . $upload_info['basedir'] );
7828
  ewwwio_debug_message( "content_width: $content_width" );
7829
  ewwwio_debug_message( 'registered stream wrappers: ' . implode( ',', stream_get_wrappers() ) );
7830
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_NOEXEC' ) ) {
8310
  ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_backup_files' ) ? "checked='true'" : '' ) . " $disable_level > " . esc_html__( 'Store a copy of your original images on our secure server for 30 days. *Requires an active API key.', 'ewww-image-optimizer' ) . "</td></tr>\n";
8311
  ewwwio_debug_message( 'backup mode: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_backup_files' ) ? 'on' : 'off' ) );
8312
  if ( class_exists( 'Cloudinary' ) && Cloudinary::config_get( 'api_secret' ) ) {
8313
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_enable_cloudinary'>" .
8314
+ esc_html__( 'Automatic Cloudinary Upload', 'ewww-image-optimizer' ) .
8315
+ "</label></th><td><input type='checkbox' id='ewww_image_optimizer_enable_cloudinary' name='ewww_image_optimizer_enable_cloudinary' value='true' " .
8316
+ ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_cloudinary' ) ? "checked='true'" : '' ) . ' /> ' .
8317
+ esc_html__( 'When enabled, uploads to the Media Library will be transferred to Cloudinary after optimization. Cloudinary generates resizes, so only the full-size image is uploaded.', 'ewww-image-optimizer' ) .
8318
+ "</td></tr>\n";
8319
  ewwwio_debug_message( 'cloudinary upload: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_cloudinary' ) ? 'on' : 'off' ) );
8320
  }
8321
  $output[] = "</table>\n</div>\n";
8418
  ewwwio_debug_message( "invalid admin ajax url: $admin_ajax_url" );
8419
  }
8420
  }
8421
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_auto'>" . esc_html__( 'Scheduled Optimization', 'ewww-image-optimizer' ) . '</label>' .
8422
+ ewwwio_help_link( 'https://docs.ewww.io/article/11-advanced-configuration', '58542afac697912ffd6c18c0,5853713bc697912ffd6c0b98' ) .
8423
+ "</th><td><input type='checkbox' id='ewww_image_optimizer_auto' name='ewww_image_optimizer_auto' value='true' " .
8424
+ ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_auto' ) ? "checked='true'" : '' ) . ' /> ' .
8425
+ esc_html__( 'This will enable scheduled optimization of unoptimized images for your theme, buddypress, and any additional folders you have configured below. Runs hourly: wp_cron only runs when your site is visited, so it may be even longer between optimizations.', 'ewww-image-optimizer' ) .
8426
+ "</td></tr>\n";
8427
  ewwwio_debug_message( 'scheduled optimization: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_auto' ) ? 'on' : 'off' ) );
8428
  $media_include_disable = '';
8429
  if ( get_option( 'ewww_image_optimizer_disable_resizes_opt' ) ) {
8458
  $output[] = "<div id='ewww-resize-settings'>\n";
8459
  $output[] = '<noscript><h2>' . esc_html__( 'Resize', 'ewww-image-optimizer' ) . '</h2></noscript>';
8460
  $output[] = "<table class='form-table'>\n";
8461
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_resize_detection'>" . esc_html__( 'Resize Detection', 'ewww-image-optimizer' ) . '</label>' .
8462
+ ewwwio_help_link( 'https://docs.ewww.io/article/41-resize-settings', '59849911042863033a1ba5f9' ) .
8463
+ "</th><td><input type='checkbox' id='ewww_image_optimizer_resize_detection' name='ewww_image_optimizer_resize_detection' value='true' " .
8464
+ ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_detection' ) ? "checked='true'" : '' ) . ' /> ' .
8465
+ esc_html__( 'Highlight images that need to be resized because the browser is scaling them down. Only visible for Admin users and adds a button to the admin bar to detect scaled images that have been lazy loaded.', 'ewww-image-optimizer' ) .
8466
+ "</td></tr>\n";
8467
  ewwwio_debug_message( 'resize detection: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_detection' ) ? 'on' : 'off' ) );
8468
  if ( function_exists( 'imsanity_get_max_width_height' ) ) {
8469
  $output[] = "<tr class='$network_class'><th>&nbsp;</th><td>" .
8470
  '<p><span style="color: #3eadc9">' . esc_html__( '*Imsanity settings override the EWWW resize dimensions.', 'ewww-image-optimizer' ) . "</span></p></td></tr>\n";
8471
  }
8472
+ $output[] = "<tr class='$network_class'><th scope='row'>" . esc_html__( 'Resize Images', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/41-resize-settings', '59849911042863033a1ba5f9' ) .
8473
  "</th><td><label for='ewww_image_optimizer_maxmediawidth'>" . esc_html__( 'Max Width', 'ewww-image-optimizer' ) .
8474
  "</label> <input type='number' step='1' min='0' class='small-text' id='ewww_image_optimizer_maxmediawidth' name='ewww_image_optimizer_maxmediawidth' value='" .
8475
  ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' ) . ( function_exists( 'imsanity_get_max_width_height' ) ? "' disabled='disabled" : '' ) .
8476
  "' /> <label for='ewww_image_optimizer_maxmediaheight'>" . esc_html__( 'Max Height', 'ewww-image-optimizer' ) .
8477
  "</label> <input type='number' step='1' min='0' class='small-text' id='ewww_image_optimizer_maxmediaheight' name='ewww_image_optimizer_maxmediaheight' value='" .
8478
  ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' ) . ( function_exists( 'imsanity_get_max_width_height' ) ? "' disabled='disabled" : '' ) . "' /> " .
8479
+ esc_html__( 'in pixels', 'ewww-image-optimizer' ) . "\n" . "<p class='description'>" . esc_html__( 'Resize uploaded images to these dimensions.', 'ewww-image-optimizer' ) .
8480
  "</td></tr>\n";
8481
  ewwwio_debug_message( 'max media dimensions: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' ) . ' x ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' ) );
8482
  ewwwio_debug_message( 'max other dimensions: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherwidth' ) . ' x ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherheight' ) );
8486
  ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' ) ? "checked='true'" : '' ) . ' /> ' .
8487
  esc_html__( 'Allow resizing of existing Media Library images.', 'ewww-image-optimizer' ) . "</td></tr>\n";
8488
  ewwwio_debug_message( 'resize existing images: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' ) ? 'on' : 'off' ) );
8489
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_resize_other_existing'>" . esc_html__( 'Resize Other Images', 'ewww-image-optimizer' ) . '</label>' .
8490
+ ewwwio_help_link( 'https://docs.ewww.io/article/41-resize-settings', '59849911042863033a1ba5f9' ) .
8491
+ "</th><td><input type='checkbox' id='ewww_image_optimizer_resize_other_existing' name='ewww_image_optimizer_resize_other_existing' value='true' " .
8492
+ ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_other_existing' ) ? "checked='true'" : '' ) . ' /> ' .
8493
+ esc_html__( 'Allow resizing of existing images outside the Media Library. Use this to resize images specified under the Folders to Optimize setting when running Bulk or Scheduled Optimization.', 'ewww-image-optimizer' ) . "</td></tr>\n";
8494
+ ewwwio_debug_message( 'resize existing (non-media) images: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_other_existing' ) ? 'on' : 'off' ) );
8495
 
8496
  $output[] = '<tr class="network-singlesite"><th scope="row">' . esc_html__( 'Disable Resizes', 'ewww-image-optimizer' ) .
8497
  ewwwio_help_link( 'https://docs.ewww.io/article/41-resize-settings', '59849911042863033a1ba5f9,58598744c697912ffd6c3eb4' ) . '</th><td><p>' .
8916
  if ( ! current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', 'edit_others_posts' ) ) || 'wp-login.php' === basename( $_SERVER['SCRIPT_NAME'] ) ) {
8917
  return;
8918
  }
8919
+ if ( ewww_image_optimizer_is_amp() ) {
8920
+ return;
8921
+ }
8922
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_detection' ) ) {
8923
  $resize_detection_script = file_get_contents( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'includes/resize_detection.js' );
8924
  echo "<style>\n" .
8927
  "\tmargin: -3px;\n" .
8928
  "}\n" .
8929
  "</style>\n";
8930
+ echo '<script type="text/javascript">' . $resize_detection_script . '</script>';
8931
  }
8932
  }
8933
 
8947
  return $jsexcludes . ', includes/resize_detection.js';
8948
  }
8949
 
8950
+ /**
8951
+ * Checks to see if the current page being output is an AMP page.
8952
+ *
8953
+ * @return bool True for an AMP endpoint, false otherwise.
8954
+ */
8955
+ function ewww_image_optimizer_is_amp() {
8956
+ if ( function_exists( 'is_amp_endpoint' ) && is_amp_endpoint() ) {
8957
+ return true;
8958
+ }
8959
+ if ( function_exists( 'ampforwp_is_amp_endpoint' ) && ampforwp_is_amp_endpoint() ) {
8960
+ return true;
8961
+ }
8962
+ return false;
8963
+ }
8964
+
8965
  /**
8966
  * Checks if admin bar is visible, and then adds the admin_bar_menu action.
8967
  */
ewww-image-optimizer.php CHANGED
@@ -13,7 +13,7 @@ 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: 4.7.4
17
  Author URI: https://ewww.io/
18
  License: GPLv3
19
  */
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: 4.8.0
17
  Author URI: https://ewww.io/
18
  License: GPLv3
19
  */
includes/lazysizes-post.js CHANGED
@@ -1,27 +1,46 @@
1
  lazysizesWebP('alpha', lazySizes.init);
2
- function constrainSrc(url,objectWidth,objectHeight){
3
  var regW = /w=(\d+)/;
4
  var regFit = /fit=(\d+),(\d+)/;
5
  var regResize = /resize=(\d+),(\d+)/;
 
6
  if (url.search('\\?') > 0 && url.search(ewww_lazy_vars.exactdn_domain) > 0){
7
- var resultResize = regResize.exec(url);
8
  if(resultResize && objectWidth < resultResize[1]){
9
- return url.replace(regResize, 'resize=' + objectWidth + ',' + objectHeight);
10
  }
11
  var resultW = regW.exec(url);
12
  if(resultW && objectWidth <= resultW[1]){
13
- return url.replace(regW, 'resize=' + objectWidth + ',' + objectHeight);
 
 
 
14
  }
15
- var resultFit = regFit.exec(url);
16
  if(resultFit && objectWidth < resultFit[1]){
17
- return url.replace(regFit, 'resize=' + objectWidth + ',' + objectHeight);
 
 
 
18
  }
19
  if(!resultW && !resultFit && !resultResize){
20
- return url + '&resize=' + objectWidth + ',' + objectHeight;
 
 
 
 
 
 
21
  }
22
  }
23
  if (url.search('\\?') == -1 && url.search(ewww_lazy_vars.exactdn_domain) > 0){
24
- return url + '?resize=' + objectWidth + ',' + objectHeight;
 
 
 
 
 
 
25
  }
26
  return url;
27
  }
@@ -40,9 +59,10 @@ document.addEventListener('lazybeforeunveil', function(e){
40
  var dPR = (window.devicePixelRatio || 1);
41
  var wrongWidth = (target.clientWidth * 1.25 < target.naturalWidth);
42
  var wrongHeight = (target.clientHeight * 1.25 < target.naturalHeight);
 
 
 
43
  if (wrongWidth || wrongHeight) {
44
- //console.log(Math.round(target.clientWidth * dPR) + "x" + Math.round(target.clientHeight * dPR) + ", natural is " +
45
- // target.naturalWidth + "x" + target.naturalHeight + "!");
46
  var targetWidth = Math.round(target.offsetWidth * dPR);
47
  var targetHeight = Math.round(target.offsetHeight * dPR);
48
 
@@ -52,7 +72,7 @@ document.addEventListener('lazybeforeunveil', function(e){
52
  //console.log('using data-src-webp');
53
  src = webpsrc;
54
  }
55
- var newSrc = constrainSrc(src,targetWidth,targetHeight);
56
  if (newSrc && src != newSrc){
57
  target.setAttribute('data-src', newSrc);
58
  }
1
  lazysizesWebP('alpha', lazySizes.init);
2
+ function constrainSrc(url,objectWidth,objectHeight,objectType){
3
  var regW = /w=(\d+)/;
4
  var regFit = /fit=(\d+),(\d+)/;
5
  var regResize = /resize=(\d+),(\d+)/;
6
+ var decUrl = decodeURIComponent(url);
7
  if (url.search('\\?') > 0 && url.search(ewww_lazy_vars.exactdn_domain) > 0){
8
+ var resultResize = regResize.exec(decUrl);
9
  if(resultResize && objectWidth < resultResize[1]){
10
+ return decUrl.replace(regResize, 'resize=' + objectWidth + ',' + objectHeight);
11
  }
12
  var resultW = regW.exec(url);
13
  if(resultW && objectWidth <= resultW[1]){
14
+ if('bg-cover'===objectType){
15
+ return url.replace(regW, 'resize=' + objectWidth + ',' + objectHeight );
16
+ }
17
+ return url.replace(regW, 'w=' + objectWidth);
18
  }
19
+ var resultFit = regFit.exec(decUrl);
20
  if(resultFit && objectWidth < resultFit[1]){
21
+ if('bg-cover'===objectType){
22
+ return url.replace(regW, 'resize=' + objectWidth + ',' + objectHeight );
23
+ }
24
+ return decUrl.replace(regFit, 'fit=' + objectWidth + ',' + objectHeight);
25
  }
26
  if(!resultW && !resultFit && !resultResize){
27
+ if('img'===objectType){
28
+ return url + '&fit=' + objectWidth + ',' + objectHeight;
29
+ }
30
+ if('bg-cover'===objectType){
31
+ return url + '?resize=' + objectWidth + ',' + objectHeight;
32
+ }
33
+ return url + '&w=' + objectWidth;
34
  }
35
  }
36
  if (url.search('\\?') == -1 && url.search(ewww_lazy_vars.exactdn_domain) > 0){
37
+ if('img'===objectType){
38
+ return url + '?fit=' + objectWidth + ',' + objectHeight;
39
+ }
40
+ if('bg-cover'===objectType){
41
+ return url + '?resize=' + objectWidth + ',' + objectHeight;
42
+ }
43
+ return url + '?w=' + objectWidth;
44
  }
45
  return url;
46
  }
59
  var dPR = (window.devicePixelRatio || 1);
60
  var wrongWidth = (target.clientWidth * 1.25 < target.naturalWidth);
61
  var wrongHeight = (target.clientHeight * 1.25 < target.naturalHeight);
62
+ /*console.log(Math.round(target.clientWidth * dPR) + "x" + Math.round(target.clientHeight * dPR) + ", natural is " +
63
+ target.naturalWidth + "x" + target.naturalHeight + "!");
64
+ console.log( target.getAttribute('data-src') );*/
65
  if (wrongWidth || wrongHeight) {
 
 
66
  var targetWidth = Math.round(target.offsetWidth * dPR);
67
  var targetHeight = Math.round(target.offsetHeight * dPR);
68
 
72
  //console.log('using data-src-webp');
73
  src = webpsrc;
74
  }
75
+ var newSrc = constrainSrc(src,targetWidth,targetHeight,'img');
76
  if (newSrc && src != newSrc){
77
  target.setAttribute('data-src', newSrc);
78
  }
includes/lazysizes.min.js CHANGED
@@ -1 +1 @@
1
- var ewww_webp_supported=!1;function lazysizesWebP(e,t){var a=new Image;a.onload=function(){ewww_webp_supported=0<a.width&&0<a.height,t()},a.onerror=function(){t()},a.src="data:image/webp;base64,"+{alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"}[e]}function constrainSrc(e,t,a){var i=/w=(\d+)/,n=/fit=(\d+),(\d+)/,r=/resize=(\d+),(\d+)/;if(0<e.search("\\?")&&0<e.search(ewww_lazy_vars.exactdn_domain)){var o=r.exec(e);if(o&&t<o[1])return e.replace(r,"resize="+t+","+a);var s=i.exec(e);if(s&&t<=s[1])return e.replace(i,"resize="+t+","+a);var l=n.exec(e);if(l&&t<l[1])return e.replace(n,"resize="+t+","+a);if(!s&&!l&&!o)return e+"&resize="+t+","+a}return-1==e.search("\\?")&&0<e.search(ewww_lazy_vars.exactdn_domain)?e+"?resize="+t+","+a:e}window.lazySizesConfig=window.lazySizesConfig||{},window.lazySizesConfig.init=!1,function(e,t){var a=function(i,A){"use strict";if(!A.getElementsByClassName)return;var z,g,h=A.documentElement,r=i.Date,n=i.HTMLPictureElement,o="addEventListener",v="getAttribute",t=i[o],u=i.setTimeout,a=i.requestAnimationFrame||u,s=i.requestIdleCallback,f=/^picture$/i,l=["load","error","lazyincluded","_lazyloaded"],d={},p=Array.prototype.forEach,c=function(e,t){return d[t]||(d[t]=new RegExp("(\\s|^)"+t+"(\\s|$)")),d[t].test(e[v]("class")||"")&&d[t]},y=function(e,t){c(e,t)||e.setAttribute("class",(e[v]("class")||"").trim()+" "+t)},m=function(e,t){var a;(a=c(e,t))&&e.setAttribute("class",(e[v]("class")||"").replace(a," "))},b=function(t,a,e){var i=e?o:"removeEventListener";e&&b(t,a),l.forEach(function(e){t[i](e,a)})},w=function(e,t,a,i,n){var r=A.createEvent("Event");return a||(a={}),a.instance=z,r.initEvent(t,!i,!n),r.detail=a,e.dispatchEvent(r),r},C=function(e,t){var a;!n&&(a=i.picturefill||g.pf)?(t&&t.src&&!e[v]("srcset")&&e.setAttribute("srcset",t.src),a({reevaluate:!0,elements:[e]})):t&&t.src&&(e.src=t.src)},_=function(e,t){return(getComputedStyle(e,null)||{})[t]},E=function(e,t,a){for(a=a||e.offsetWidth;a<g.minSize&&t&&!e._lazysizesWidth;)a=t.offsetWidth,t=t.parentNode;return a},W=(B=[],R=[],L=B,N=function(){var e=L;for(L=B.length?R:B,S=!(M=!0);e.length;)e.shift()();M=!1},Q=function(e,t){M&&!t?e.apply(this,arguments):(L.push(e),S||(S=!0,(A.hidden?u:a)(N)))},Q._lsFlush=N,Q),e=function(a,e){return e?function(){W(a)}:function(){var e=this,t=arguments;W(function(){a.apply(e,t)})}},x=function(e){var t,a,i=function(){t=null,e()},n=function(){var e=r.now()-a;e<99?u(n,99-e):(s||i)(i)};return function(){a=r.now(),t||(t=u(n,99))}};var M,S,B,R,L,N,Q;!function(){var e,t={lazyClass:"lazyload",loadedClass:"lazyloaded",loadingClass:"lazyloading",preloadClass:"lazypreload",errorClass:"lazyerror",autosizesClass:"lazyautosizes",srcAttr:"data-src",srcsetAttr:"data-srcset",sizesAttr:"data-sizes",minSize:40,customMedia:{},init:!0,expFactor:1.5,hFac:.8,loadMode:2,loadHidden:!0,ricTimeout:0,throttleDelay:125};for(e in g=i.lazySizesConfig||i.lazysizesConfig||{},t)e in g||(g[e]=t[e]);i.lazySizesConfig=g,u(function(){g.init&&D()})}();var P=(se=/^img$/i,le=/^iframe$/i,de="onscroll"in i&&!/(gle|ing)bot/.test(navigator.userAgent),ce=0,ue=0,fe=-1,Ae=function(e){ue--,(!e||ue<0||!e.target)&&(ue=0)},ze=function(e){return null==Z&&(Z="hidden"==_(A.body,"visibility")),Z||"hidden"!=_(e.parentNode,"visibility")&&"hidden"!=_(e,"visibility")},ge=function(e,t){var a,i=e,n=ze(e);for(V-=t,K+=t,X-=t,Y+=t;n&&(i=i.offsetParent)&&i!=A.body&&i!=h;)(n=0<(_(i,"opacity")||1))&&"visible"!=_(i,"overflow")&&(a=i.getBoundingClientRect(),n=Y>a.left&&X<a.right&&K>a.top-1&&V<a.bottom+1);return n},he=function(){var e,t,a,i,n,r,o,s,l,d,c,u,f=z.elements;if((G=g.loadMode)&&ue<8&&(e=f.length)){for(t=0,fe++,d=!g.expand||g.expand<1?500<h.clientHeight&&500<h.clientWidth?500:370:g.expand,z._defEx=d,c=d*g.expFactor,u=g.hFac,Z=null,ce<c&&ue<1&&2<fe&&2<G&&!A.hidden?(ce=c,fe=0):ce=1<G&&1<fe&&ue<6?d:0;t<e;t++)if(f[t]&&!f[t]._lazyRace)if(de)if((s=f[t][v]("data-expand"))&&(r=1*s)||(r=ce),l!==r&&(q=innerWidth+r*u,j=innerHeight+r,o=-1*r,l=r),a=f[t].getBoundingClientRect(),(K=a.bottom)>=o&&(V=a.top)<=j&&(Y=a.right)>=o*u&&(X=a.left)<=q&&(K||Y||X||V)&&(g.loadHidden||ze(f[t]))&&(J&&ue<3&&!s&&(G<3||fe<4)||ge(f[t],r))){if(Ce(f[t]),n=!0,9<ue)break}else!n&&J&&!i&&ue<4&&fe<4&&2<G&&(I[0]||g.preloadAfterLoad)&&(I[0]||!s&&(K||Y||X||V||"auto"!=f[t][v](g.sizesAttr)))&&(i=I[0]||f[t]);else Ce(f[t]);i&&!n&&Ce(i)}},ee=he,ae=0,ie=g.throttleDelay,ne=g.ricTimeout,re=function(){te=!1,ae=r.now(),ee()},oe=s&&49<ne?function(){s(re,{timeout:ne}),ne!==g.ricTimeout&&(ne=g.ricTimeout)}:e(function(){u(re)},!0),ve=function(e){var t;(e=!0===e)&&(ne=33),te||(te=!0,(t=ie-(r.now()-ae))<0&&(t=0),e||t<9?oe():u(oe,t))},pe=function(e){var t=e.target;t._lazyCache?delete t._lazyCache:(Ae(e),y(t,g.loadedClass),m(t,g.loadingClass),b(t,me),w(t,"lazyloaded"))},ye=e(pe),me=function(e){ye({target:e.target})},be=function(e){var t,a=e[v](g.srcsetAttr);(t=g.customMedia[e[v]("data-media")||e[v]("media")])&&e.setAttribute("media",t),a&&e.setAttribute("srcset",a)},we=e(function(e,t,a,i,n){var r,o,s,l,d,c;(d=w(e,"lazybeforeunveil",t)).defaultPrevented||(i&&(a?y(e,g.autosizesClass):e.setAttribute("sizes",i)),o=e[v](g.srcsetAttr),r=e[v](g.srcAttr),n&&(s=e.parentNode,l=s&&f.test(s.nodeName||"")),c=t.firesLoad||"src"in e&&(o||r||l),d={target:e},y(e,g.loadingClass),c&&(clearTimeout(O),O=u(Ae,2500),b(e,me,!0)),l&&p.call(s.getElementsByTagName("source"),be),o?e.setAttribute("srcset",o):r&&!l&&(le.test(e.nodeName)?function(t,a){try{t.contentWindow.location.replace(a)}catch(e){t.src=a}}(e,r):e.src=r),n&&(o||l)&&C(e,{src:r})),e._lazyRace&&delete e._lazyRace,m(e,g.lazyClass),W(function(){(!c||e.complete&&1<e.naturalWidth)&&(pe(d),e._lazyCache=!0,u(function(){"_lazyCache"in e&&delete e._lazyCache},9))},!0)}),Ce=function(e){var t,a=se.test(e.nodeName),i=a&&(e[v](g.sizesAttr)||e[v]("sizes")),n="auto"==i;(!n&&J||!a||!e[v]("src")&&!e.srcset||e.complete||c(e,g.errorClass)||!c(e,g.lazyClass))&&(t=w(e,"lazyunveilread").detail,n&&k.updateElem(e,!0,e.offsetWidth),e._lazyRace=!0,ue++,we(e,t,n,i,a))},_e=function(){if(!J)if(r.now()-$<999)u(_e,999);else{var e=x(function(){g.loadMode=3,ve()});J=!0,g.loadMode=3,ve(),t("scroll",function(){3==g.loadMode&&(g.loadMode=2),e()},!0)}},{_:function(){$=r.now(),z.elements=A.getElementsByClassName(g.lazyClass),I=A.getElementsByClassName(g.lazyClass+" "+g.preloadClass),t("scroll",ve,!0),t("resize",ve,!0),i.MutationObserver?new MutationObserver(ve).observe(h,{childList:!0,subtree:!0,attributes:!0}):(h[o]("DOMNodeInserted",ve,!0),h[o]("DOMAttrModified",ve,!0),setInterval(ve,999)),t("hashchange",ve,!0),["focus","mouseover","click","load","transitionend","animationend","webkitAnimationEnd"].forEach(function(e){A[o](e,ve,!0)}),/d$|^c/.test(A.readyState)?_e():(t("load",_e),A[o]("DOMContentLoaded",ve),u(_e,2e4)),z.elements.length?(he(),W._lsFlush()):ve()},checkElems:ve,unveil:Ce}),k=(H=e(function(e,t,a,i){var n,r,o;if(e._lazysizesWidth=i,i+="px",e.setAttribute("sizes",i),f.test(t.nodeName||""))for(n=t.getElementsByTagName("source"),r=0,o=n.length;r<o;r++)n[r].setAttribute("sizes",i);a.detail.dataAttr||C(e,a.detail)}),F=function(e,t,a){var i,n=e.parentNode;n&&(a=E(e,n,a),(i=w(e,"lazybeforesizes",{width:a,dataAttr:!!t})).defaultPrevented||(a=i.detail.width)&&a!==e._lazysizesWidth&&H(e,n,i,a))},U=x(function(){var e,t=T.length;if(t)for(e=0;e<t;e++)F(T[e])}),{_:function(){T=A.getElementsByClassName(g.autosizesClass),t("resize",U)},checkElems:U,updateElem:F}),D=function(){D.i||(D.i=!0,k._(),P._())};var T,H,F,U;var I,J,O,G,$,q,j,V,X,Y,K,Z,ee,te,ae,ie,ne,re,oe,se,le,de,ce,ue,fe,Ae,ze,ge,he,ve,pe,ye,me,be,we,Ce,_e;return z={cfg:g,autoSizer:k,loader:P,init:D,uP:C,aC:y,rC:m,hC:c,fire:w,gW:E,rAF:W}}(e,e.document);e.lazySizes=a,"object"==typeof module&&module.exports&&(module.exports=a)}(window),lazysizesWebP("alpha",lazySizes.init),document.addEventListener("lazybeforeunveil",function(e){var t=e.target,a=t.getAttribute("data-srcset");if(!a&&t.naturalWidth&&1<t.naturalWidth&&1<t.naturalHeight){var i=window.devicePixelRatio||1,n=1.25*t.clientWidth<t.naturalWidth,r=1.25*t.clientHeight<t.naturalHeight;if(n||r){var o=Math.round(t.offsetWidth*i),s=Math.round(t.offsetHeight*i),l=t.getAttribute("data-src"),d=t.getAttribute("data-src-webp");ewww_webp_supported&&d&&-1==l.search("webp=1")&&(l=d);var c=constrainSrc(l,o,s);c&&l!=c&&t.setAttribute("data-src",c)}}if(ewww_webp_supported){if(a&&-1<a.search("webp=1"))return;if(a){var u=t.getAttribute("data-srcset-webp");u&&t.setAttribute("data-srcset",u)}if((l=t.getAttribute("data-src"))&&-1<l.search("webp=1"))return;if(!(d=t.getAttribute("data-src-webp")))return;t.setAttribute("data-src",d)}}),function(e,t){var a=function(){t(e.lazySizes),e.removeEventListener("lazyunveilread",a,!0)};t=t.bind(null,e,e.document),"object"==typeof module&&module.exports?t(require("lazysizes")):e.lazySizes?a():e.addEventListener("lazyunveilread",a,!0)}(window,function(s,i,l){"use strict";var d,c;i.addEventListener&&(d=function(e,t){var a=i.createElement("img");a.onload=function(){a.onload=null,a.onerror=null,a=null,t()},a.onerror=a.onload,a.src=e,a&&a.complete&&a.onload&&a.onload()},addEventListener("lazybeforeunveil",function(e){var t,a,i;if(e.detail.instance==l&&!e.defaultPrevented){if("none"==e.target.preload&&(e.target.preload="auto"),t=e.target.getAttribute("data-bg")){ewww_webp_supported&&(a=e.target.getAttribute("data-bg-webp"))&&(t=a);var n=s.devicePixelRatio||1,r=Math.round(e.target.offsetWidth*n),o=Math.round(e.target.offsetHeight*n);t=constrainSrc(t,r,o),e.detail.firesLoad=!0,d(t,function(){e.target.style.backgroundImage="url("+(c.test(t)?JSON.stringify(t):t)+")",e.detail.firesLoad=!1,l.fire(e.target,"_lazyloaded",{},!0,!0)})}(i=e.target.getAttribute("data-poster"))&&(e.detail.firesLoad=!0,d(i,function(){e.target.poster=i,e.detail.firesLoad=!1,l.fire(e.target,"_lazyloaded",{},!0,!0)}))}},!(c=/\(|\)|\s|'/)))});
1
+ var ewww_webp_supported=!1;function lazysizesWebP(e,t){var a=new Image;a.onload=function(){ewww_webp_supported=0<a.width&&0<a.height,t()},a.onerror=function(){t()},a.src="data:image/webp;base64,"+{alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"}[e]}function constrainSrc(e,t,a,i){var r=/w=(\d+)/,n=/fit=(\d+),(\d+)/,o=/resize=(\d+),(\d+)/,s=decodeURIComponent(e);if(0<e.search("\\?")&&0<e.search(ewww_lazy_vars.exactdn_domain)){var l=o.exec(s);if(l&&t<l[1])return s.replace(o,"resize="+t+","+a);var d=r.exec(e);if(d&&t<=d[1])return"bg-cover"===i?e.replace(r,"resize="+t+","+a):e.replace(r,"w="+t);var c=n.exec(s);if(c&&t<c[1])return"bg-cover"===i?e.replace(r,"resize="+t+","+a):s.replace(n,"fit="+t+","+a);if(!d&&!c&&!l)return"img"===i?e+"&fit="+t+","+a:"bg-cover"===i?e+"?resize="+t+","+a:e+"&w="+t}return-1==e.search("\\?")&&0<e.search(ewww_lazy_vars.exactdn_domain)?"img"===i?e+"?fit="+t+","+a:"bg-cover"===i?e+"?resize="+t+","+a:e+"?w="+t:e}window.lazySizesConfig=window.lazySizesConfig||{},window.lazySizesConfig.init=!1,function(e,t){var a=function(i,A){"use strict";if(!A.getElementsByClassName)return;var g,z,v=A.documentElement,n=i.Date,r=i.HTMLPictureElement,o="addEventListener",h="getAttribute",t=i[o],u=i.setTimeout,a=i.requestAnimationFrame||u,s=i.requestIdleCallback,f=/^picture$/i,l=["load","error","lazyincluded","_lazyloaded"],d={},p=Array.prototype.forEach,c=function(e,t){return d[t]||(d[t]=new RegExp("(\\s|^)"+t+"(\\s|$)")),d[t].test(e[h]("class")||"")&&d[t]},m=function(e,t){c(e,t)||e.setAttribute("class",(e[h]("class")||"").trim()+" "+t)},y=function(e,t){var a;(a=c(e,t))&&e.setAttribute("class",(e[h]("class")||"").replace(a," "))},b=function(t,a,e){var i=e?o:"removeEventListener";e&&b(t,a),l.forEach(function(e){t[i](e,a)})},w=function(e,t,a,i,r){var n=A.createEvent("Event");return a||(a={}),a.instance=g,n.initEvent(t,!i,!r),n.detail=a,e.dispatchEvent(n),n},C=function(e,t){var a;!r&&(a=i.picturefill||z.pf)?(t&&t.src&&!e[h]("srcset")&&e.setAttribute("srcset",t.src),a({reevaluate:!0,elements:[e]})):t&&t.src&&(e.src=t.src)},_=function(e,t){return(getComputedStyle(e,null)||{})[t]},E=function(e,t,a){for(a=a||e.offsetWidth;a<z.minSize&&t&&!e._lazysizesWidth;)a=t.offsetWidth,t=t.parentNode;return a},W=(B=[],R=[],L=B,N=function(){var e=L;for(L=B.length?R:B,M=!(S=!0);e.length;)e.shift()();S=!1},Q=function(e,t){S&&!t?e.apply(this,arguments):(L.push(e),M||(M=!0,(A.hidden?u:a)(N)))},Q._lsFlush=N,Q),e=function(a,e){return e?function(){W(a)}:function(){var e=this,t=arguments;W(function(){a.apply(e,t)})}},x=function(e){var t,a,i=function(){t=null,e()},r=function(){var e=n.now()-a;e<99?u(r,99-e):(s||i)(i)};return function(){a=n.now(),t||(t=u(r,99))}};var S,M,B,R,L,N,Q;!function(){var e,t={lazyClass:"lazyload",loadedClass:"lazyloaded",loadingClass:"lazyloading",preloadClass:"lazypreload",errorClass:"lazyerror",autosizesClass:"lazyautosizes",srcAttr:"data-src",srcsetAttr:"data-srcset",sizesAttr:"data-sizes",minSize:40,customMedia:{},init:!0,expFactor:1.5,hFac:.8,loadMode:2,loadHidden:!0,ricTimeout:0,throttleDelay:125};for(e in z=i.lazySizesConfig||i.lazysizesConfig||{},t)e in z||(z[e]=t[e]);i.lazySizesConfig=z,u(function(){z.init&&D()})}();var P=(se=/^img$/i,le=/^iframe$/i,de="onscroll"in i&&!/(gle|ing)bot/.test(navigator.userAgent),ce=0,ue=0,fe=-1,Ae=function(e){ue--,(!e||ue<0||!e.target)&&(ue=0)},ge=function(e){return null==Z&&(Z="hidden"==_(A.body,"visibility")),Z||"hidden"!=_(e.parentNode,"visibility")&&"hidden"!=_(e,"visibility")},ze=function(e,t){var a,i=e,r=ge(e);for(V-=t,K+=t,X-=t,Y+=t;r&&(i=i.offsetParent)&&i!=A.body&&i!=v;)(r=0<(_(i,"opacity")||1))&&"visible"!=_(i,"overflow")&&(a=i.getBoundingClientRect(),r=Y>a.left&&X<a.right&&K>a.top-1&&V<a.bottom+1);return r},ve=function(){var e,t,a,i,r,n,o,s,l,d,c,u,f=g.elements;if((G=z.loadMode)&&ue<8&&(e=f.length)){for(t=0,fe++,d=!z.expand||z.expand<1?500<v.clientHeight&&500<v.clientWidth?500:370:z.expand,g._defEx=d,c=d*z.expFactor,u=z.hFac,Z=null,ce<c&&ue<1&&2<fe&&2<G&&!A.hidden?(ce=c,fe=0):ce=1<G&&1<fe&&ue<6?d:0;t<e;t++)if(f[t]&&!f[t]._lazyRace)if(de)if((s=f[t][h]("data-expand"))&&(n=1*s)||(n=ce),l!==n&&(q=innerWidth+n*u,j=innerHeight+n,o=-1*n,l=n),a=f[t].getBoundingClientRect(),(K=a.bottom)>=o&&(V=a.top)<=j&&(Y=a.right)>=o*u&&(X=a.left)<=q&&(K||Y||X||V)&&(z.loadHidden||ge(f[t]))&&(J&&ue<3&&!s&&(G<3||fe<4)||ze(f[t],n))){if(Ce(f[t]),r=!0,9<ue)break}else!r&&J&&!i&&ue<4&&fe<4&&2<G&&(I[0]||z.preloadAfterLoad)&&(I[0]||!s&&(K||Y||X||V||"auto"!=f[t][h](z.sizesAttr)))&&(i=I[0]||f[t]);else Ce(f[t]);i&&!r&&Ce(i)}},ee=ve,ae=0,ie=z.throttleDelay,re=z.ricTimeout,ne=function(){te=!1,ae=n.now(),ee()},oe=s&&49<re?function(){s(ne,{timeout:re}),re!==z.ricTimeout&&(re=z.ricTimeout)}:e(function(){u(ne)},!0),he=function(e){var t;(e=!0===e)&&(re=33),te||(te=!0,(t=ie-(n.now()-ae))<0&&(t=0),e||t<9?oe():u(oe,t))},pe=function(e){var t=e.target;t._lazyCache?delete t._lazyCache:(Ae(e),m(t,z.loadedClass),y(t,z.loadingClass),b(t,ye),w(t,"lazyloaded"))},me=e(pe),ye=function(e){me({target:e.target})},be=function(e){var t,a=e[h](z.srcsetAttr);(t=z.customMedia[e[h]("data-media")||e[h]("media")])&&e.setAttribute("media",t),a&&e.setAttribute("srcset",a)},we=e(function(e,t,a,i,r){var n,o,s,l,d,c;(d=w(e,"lazybeforeunveil",t)).defaultPrevented||(i&&(a?m(e,z.autosizesClass):e.setAttribute("sizes",i)),o=e[h](z.srcsetAttr),n=e[h](z.srcAttr),r&&(s=e.parentNode,l=s&&f.test(s.nodeName||"")),c=t.firesLoad||"src"in e&&(o||n||l),d={target:e},m(e,z.loadingClass),c&&(clearTimeout(O),O=u(Ae,2500),b(e,ye,!0)),l&&p.call(s.getElementsByTagName("source"),be),o?e.setAttribute("srcset",o):n&&!l&&(le.test(e.nodeName)?function(t,a){try{t.contentWindow.location.replace(a)}catch(e){t.src=a}}(e,n):e.src=n),r&&(o||l)&&C(e,{src:n})),e._lazyRace&&delete e._lazyRace,y(e,z.lazyClass),W(function(){(!c||e.complete&&1<e.naturalWidth)&&(pe(d),e._lazyCache=!0,u(function(){"_lazyCache"in e&&delete e._lazyCache},9))},!0)}),Ce=function(e){var t,a=se.test(e.nodeName),i=a&&(e[h](z.sizesAttr)||e[h]("sizes")),r="auto"==i;(!r&&J||!a||!e[h]("src")&&!e.srcset||e.complete||c(e,z.errorClass)||!c(e,z.lazyClass))&&(t=w(e,"lazyunveilread").detail,r&&k.updateElem(e,!0,e.offsetWidth),e._lazyRace=!0,ue++,we(e,t,r,i,a))},_e=function(){if(!J)if(n.now()-$<999)u(_e,999);else{var e=x(function(){z.loadMode=3,he()});J=!0,z.loadMode=3,he(),t("scroll",function(){3==z.loadMode&&(z.loadMode=2),e()},!0)}},{_:function(){$=n.now(),g.elements=A.getElementsByClassName(z.lazyClass),I=A.getElementsByClassName(z.lazyClass+" "+z.preloadClass),t("scroll",he,!0),t("resize",he,!0),i.MutationObserver?new MutationObserver(he).observe(v,{childList:!0,subtree:!0,attributes:!0}):(v[o]("DOMNodeInserted",he,!0),v[o]("DOMAttrModified",he,!0),setInterval(he,999)),t("hashchange",he,!0),["focus","mouseover","click","load","transitionend","animationend","webkitAnimationEnd"].forEach(function(e){A[o](e,he,!0)}),/d$|^c/.test(A.readyState)?_e():(t("load",_e),A[o]("DOMContentLoaded",he),u(_e,2e4)),g.elements.length?(ve(),W._lsFlush()):he()},checkElems:he,unveil:Ce}),k=(H=e(function(e,t,a,i){var r,n,o;if(e._lazysizesWidth=i,i+="px",e.setAttribute("sizes",i),f.test(t.nodeName||""))for(r=t.getElementsByTagName("source"),n=0,o=r.length;n<o;n++)r[n].setAttribute("sizes",i);a.detail.dataAttr||C(e,a.detail)}),U=function(e,t,a){var i,r=e.parentNode;r&&(a=E(e,r,a),(i=w(e,"lazybeforesizes",{width:a,dataAttr:!!t})).defaultPrevented||(a=i.detail.width)&&a!==e._lazysizesWidth&&H(e,r,i,a))},F=x(function(){var e,t=T.length;if(t)for(e=0;e<t;e++)U(T[e])}),{_:function(){T=A.getElementsByClassName(z.autosizesClass),t("resize",F)},checkElems:F,updateElem:U}),D=function(){D.i||(D.i=!0,k._(),P._())};var T,H,U,F;var I,J,O,G,$,q,j,V,X,Y,K,Z,ee,te,ae,ie,re,ne,oe,se,le,de,ce,ue,fe,Ae,ge,ze,ve,he,pe,me,ye,be,we,Ce,_e;return g={cfg:z,autoSizer:k,loader:P,init:D,uP:C,aC:m,rC:y,hC:c,fire:w,gW:E,rAF:W}}(e,e.document);e.lazySizes=a,"object"==typeof module&&module.exports&&(module.exports=a)}(window),lazysizesWebP("alpha",lazySizes.init),document.addEventListener("lazybeforeunveil",function(e){var t=e.target,a=t.getAttribute("data-srcset");if(!a&&t.naturalWidth&&1<t.naturalWidth&&1<t.naturalHeight){var i=window.devicePixelRatio||1,r=1.25*t.clientWidth<t.naturalWidth,n=1.25*t.clientHeight<t.naturalHeight;if(r||n){var o=Math.round(t.offsetWidth*i),s=Math.round(t.offsetHeight*i),l=t.getAttribute("data-src"),d=t.getAttribute("data-src-webp");ewww_webp_supported&&d&&-1==l.search("webp=1")&&(l=d);var c=constrainSrc(l,o,s,"img");c&&l!=c&&t.setAttribute("data-src",c)}}if(ewww_webp_supported){if(a&&-1<a.search("webp=1"))return;if(a){var u=t.getAttribute("data-srcset-webp");u&&t.setAttribute("data-srcset",u)}if((l=t.getAttribute("data-src"))&&-1<l.search("webp=1"))return;if(!(d=t.getAttribute("data-src-webp")))return;t.setAttribute("data-src",d)}}),function(e,t){var a=function(){t(e.lazySizes),e.removeEventListener("lazyunveilread",a,!0)};t=t.bind(null,e,e.document),"object"==typeof module&&module.exports?t(require("lazysizes")):e.lazySizes?a():e.addEventListener("lazyunveilread",a,!0)}(window,function(s,i,l){"use strict";var d,c;i.addEventListener&&(d=function(e,t){var a=i.createElement("img");a.onload=function(){a.onload=null,a.onerror=null,a=null,t()},a.onerror=a.onload,a.src=e,a&&a.complete&&a.onload&&a.onload()},addEventListener("lazybeforeunveil",function(e){var t,a,i;if(e.detail.instance==l&&!e.defaultPrevented){if("none"==e.target.preload&&(e.target.preload="auto"),t=e.target.getAttribute("data-bg")){ewww_webp_supported&&(a=e.target.getAttribute("data-bg-webp"))&&(t=a);var r=s.devicePixelRatio||1,n=Math.round(e.target.offsetWidth*r),o=Math.round(e.target.offsetHeight*r);t=s.lazySizes.hC(e.target,"wp-block-cover")?constrainSrc(t,n,o,"bg-cover"):constrainSrc(t,n,o,"bg"),e.detail.firesLoad=!0,d(t,function(){e.target.style.backgroundImage="url("+(c.test(t)?JSON.stringify(t):t)+")",e.detail.firesLoad=!1,l.fire(e.target,"_lazyloaded",{},!0,!0)})}(i=e.target.getAttribute("data-poster"))&&(e.detail.firesLoad=!0,d(i,function(){e.target.poster=i,e.detail.firesLoad=!1,l.fire(e.target,"_lazyloaded",{},!0,!0)}))}},!(c=/\(|\)|\s|'/)))});
includes/ls.unveilhooks.js CHANGED
@@ -85,7 +85,11 @@ For background images, use data-bg attribute:
85
  var dPR = (window.devicePixelRatio || 1);
86
  var targetWidth = Math.round(e.target.offsetWidth * dPR);
87
  var targetHeight = Math.round(e.target.offsetHeight * dPR);
88
- bg = constrainSrc(bg,targetWidth,targetHeight);
 
 
 
 
89
  e.detail.firesLoad = true;
90
  load = function(){
91
  e.target.style.backgroundImage = 'url(' + (regBgUrlEscape.test(bg) ? JSON.stringify(bg) : bg ) + ')';
85
  var dPR = (window.devicePixelRatio || 1);
86
  var targetWidth = Math.round(e.target.offsetWidth * dPR);
87
  var targetHeight = Math.round(e.target.offsetHeight * dPR);
88
+ if(window.lazySizes.hC(e.target,'wp-block-cover')){
89
+ bg = constrainSrc(bg,targetWidth,targetHeight,'bg-cover');
90
+ } else {
91
+ bg = constrainSrc(bg,targetWidth,targetHeight,'bg');
92
+ }
93
  e.detail.firesLoad = true;
94
  load = function(){
95
  e.target.style.backgroundImage = 'url(' + (regBgUrlEscape.test(bg) ? JSON.stringify(bg) : bg ) + ')';
readme.txt CHANGED
@@ -2,10 +2,10 @@
2
  Contributors: nosilver4u
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MKMQKCBFFG3WW
4
  Tags: image, compress, resize, optimize, optimization, lossless, lossy, seo, webp, wp-cli, scale, tinypng, tinyjpg
5
- Requires at least: 4.9
6
  Tested up to: 5.2
7
  Requires PHP: 5.6
8
- Stable tag: 4.7.4
9
  License: GPLv3
10
 
11
  Speed up your website and improve your visitors' experience by automatically compressing and resizing images and PDFs. Boost SEO and improve sales.
@@ -174,6 +174,24 @@ http://developer.yahoo.com/performance/rules.html#opt_images
174
  * Feature requests can be viewed and submitted at https://github.com/nosilver4u/ewww-image-optimizer/labels/enhancement
175
  * If you would like to help translate this plugin in your language, get started here: https://translate.wordpress.org/projects/wp-plugins/ewww-image-optimizer/
176
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  = 4.7.4 =
178
  * fixed: ExactDN modifies Autoptimize CDN setting even when Include All Resources is disabled
179
  * fixed: noscript elements with newlines being parsed incorrectly by Lazy Load and JS WebP
2
  Contributors: nosilver4u
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MKMQKCBFFG3WW
4
  Tags: image, compress, resize, optimize, optimization, lossless, lossy, seo, webp, wp-cli, scale, tinypng, tinyjpg
5
+ Requires at least: 5.0
6
  Tested up to: 5.2
7
  Requires PHP: 5.6
8
+ Stable tag: 4.8.0
9
  License: GPLv3
10
 
11
  Speed up your website and improve your visitors' experience by automatically compressing and resizing images and PDFs. Boost SEO and improve sales.
174
  * Feature requests can be viewed and submitted at https://github.com/nosilver4u/ewww-image-optimizer/labels/enhancement
175
  * If you would like to help translate this plugin in your language, get started here: https://translate.wordpress.org/projects/wp-plugins/ewww-image-optimizer/
176
 
177
+ = 4.8.0 =
178
+ * added: ability to resize images outside media library via scheduled or bulk optimization
179
+ * added: compatibility with WP Stateless for GSC
180
+ * added: use ewww_image_optimizer_autoconvert_threshold filter to modify conversion threshold (default of 300kb)
181
+ * changed: Lazy Load without ExactDN uses blank PNG placeholders for better srcset auto-sizing
182
+ * changed: API backups taken prior to resizing/scaling rather than just before compression
183
+ * changed: ExactDN + Lazy Load uses scaling rather than cropping by default
184
+ * changed: prevent NextGEN backup images from being optimized
185
+ * fixed: bulk optimizer not resuming when non-media library images remain in queue
186
+ * fixed: notices when a user-selected admin theme is unavailable
187
+ * fixed: privacy policy function triggers notices in WP-CLI
188
+ * fixed: background-image attributes with single-quotes now supported by ExactDN, Lazy Load, and JS WebP
189
+ * fixed: background-image attributes getting extra arguments with lazy load
190
+ * fixed: On multi-site installs, site admins could add folders to optimize outside of the uploads folder
191
+ * fixed: LQIP with SVG files results in duplicate requests
192
+ * fixed: image optimization results in media library report file missing when using WP Stateless
193
+ * fixed: plugin checking for 'nice' on Windows servers
194
+
195
  = 4.7.4 =
196
  * fixed: ExactDN modifies Autoptimize CDN setting even when Include All Resources is disabled
197
  * fixed: noscript elements with newlines being parsed incorrectly by Lazy Load and JS WebP
tests/test-convert.php CHANGED
@@ -255,7 +255,7 @@ class EWWWIO_Convert_Tests extends WP_UnitTestCase {
255
  */
256
  function test_convert_png_attachment() {
257
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_png_level', 0 );
258
- ewww_image_optimizer_set_option( 'ewww_image_optimizer_disable_autoconvert', true );
259
 
260
  $upload_png = self::$test_png . '.png';
261
  copy( self::$test_png, $upload_png );
255
  */
256
  function test_convert_png_attachment() {
257
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_png_level', 0 );
258
+ define( 'EWWW_IMAGE_OPTIMIZER_DISABLE_AUTOCONVERT', true );
259
 
260
  $upload_png = self::$test_png . '.png';
261
  copy( self::$test_png, $upload_png );
unique.php CHANGED
@@ -31,7 +31,12 @@ function ewww_image_optimizer_cloud_init() {
31
  define( 'EWWW_IMAGE_OPTIMIZER_CLOUD', false );
32
  return;
33
  }
34
- if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_CLOUD' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) > 10 && ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) > 10 ) {
 
 
 
 
 
35
  define( 'EWWW_IMAGE_OPTIMIZER_CLOUD', true );
36
  } elseif ( ! defined( 'EWWW_IMAGE_OPTIMIZER_CLOUD' ) ) {
37
  define( 'EWWW_IMAGE_OPTIMIZER_CLOUD', false );
@@ -349,7 +354,7 @@ function ewww_image_optimizer_install_tools() {
349
  $toolfail = false;
350
  if ( ! is_dir( EWWW_IMAGE_OPTIMIZER_TOOL_PATH ) && is_writable( dirname( EWWW_IMAGE_OPTIMIZER_TOOL_PATH ) ) ) {
351
  ewwwio_debug_message( 'folder does not exist, creating...' );
352
- if ( ! mkdir( EWWW_IMAGE_OPTIMIZER_TOOL_PATH ) ) {
353
  ewwwio_debug_message( 'could not create folder' );
354
  return;
355
  }
@@ -553,7 +558,11 @@ function ewww_image_optimizer_notice_utils( $quiet = null ) {
553
  // Check if exec is disabled.
554
  if ( ewww_image_optimizer_exec_check() ) {
555
  $no_compression = false;
556
- if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' ) ) {
 
 
 
 
557
  $no_compression = true;
558
  }
559
  // Need to be a little particular with the quiet parameter.
@@ -1197,10 +1206,14 @@ function ewww_image_optimizer_escapeshellcmd( $path ) {
1197
  function ewww_image_optimizer_tool_found( $path, $tool ) {
1198
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1199
  ewwwio_debug_message( "testing case: $tool at $path" );
 
 
 
 
1200
  // '*b' cases are 'blind' testing in case we can't get at the version string, but the binaries are actually working, we run a test compression, and compare the results with what they should be.
1201
  switch ( $tool ) {
1202
  case 'j': // jpegtran.
1203
- exec( $path . ' -v ' . EWWW_IMAGE_OPTIMIZER_IMAGES_PATH . 'sample.jpg 2>&1', $jpegtran_version );
1204
  if ( ewww_image_optimizer_iterable( $jpegtran_version ) ) {
1205
  ewwwio_debug_message( "$path: {$jpegtran_version[0]}" );
1206
  } else {
@@ -1229,7 +1242,7 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1229
  }
1230
  break;
1231
  case 'o': // optipng.
1232
- exec( $path . ' -v 2>&1', $optipng_version );
1233
  if ( ewww_image_optimizer_iterable( $optipng_version ) ) {
1234
  ewwwio_debug_message( "$path: {$optipng_version[0]}" );
1235
  } else {
@@ -1256,7 +1269,7 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1256
  }
1257
  break;
1258
  case 'g': // gifsicle.
1259
- exec( $path . ' --version 2>&1', $gifsicle_version );
1260
  if ( ewww_image_optimizer_iterable( $gifsicle_version ) ) {
1261
  ewwwio_debug_message( "$path: {$gifsicle_version[0]}" );
1262
  } else {
@@ -1283,7 +1296,7 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1283
  }
1284
  break;
1285
  case 'p': // pngout.
1286
- exec( "$path 2>&1", $pngout_version );
1287
  if ( ewww_image_optimizer_iterable( $pngout_version ) ) {
1288
  ewwwio_debug_message( "$path: {$pngout_version[0]}" );
1289
  } else {
@@ -1310,7 +1323,7 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1310
  }
1311
  break;
1312
  case 'q': // pngquant.
1313
- exec( $path . ' -V 2>&1', $pngquant_version );
1314
  if ( ewww_image_optimizer_iterable( $pngquant_version ) ) {
1315
  ewwwio_debug_message( "$path: {$pngquant_version[0]}" );
1316
  } else {
@@ -1336,37 +1349,11 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1336
  return esc_html__( 'unknown', 'ewww-image-optimizer' );
1337
  }
1338
  break;
1339
- case 'i': // ImageMagick.
1340
- exec( "$path -version 2>&1", $convert_version );
1341
- if ( ewww_image_optimizer_iterable( $convert_version ) ) {
1342
- ewwwio_debug_message( "$path: {$convert_version[0]}" );
1343
- } else {
1344
- ewwwio_debug_message( "$path: invalid output" );
1345
- break;
1346
- }
1347
- if ( ! empty( $convert_version ) && strpos( $convert_version[0], 'ImageMagick' ) ) {
1348
- ewwwio_debug_message( 'imagemagick found' );
1349
- return $convert_version[0];
1350
- }
1351
- break;
1352
- case 'f': // file.
1353
- exec( "$path -v 2>&1", $file_version );
1354
- if ( ewww_image_optimizer_iterable( $file_version ) ) {
1355
- ewwwio_debug_message( "$path: {$file_version[1]}" );
1356
- } else {
1357
- ewwwio_debug_message( "$path: invalid output" );
1358
- break;
1359
- }
1360
- if ( ! empty( $file_version[1] ) && preg_match( '/magic/', $file_version[1] ) ) {
1361
- ewwwio_debug_message( 'file binary found' );
1362
- return $file_version[0];
1363
- } elseif ( ! empty( $file_version[1] ) && preg_match( '/usage: file/', $file_version[1] ) ) {
1364
- ewwwio_debug_message( 'file binary found' );
1365
- return $file_version[0];
1366
- }
1367
- break;
1368
  case 'n': // nice.
1369
- exec( "$path 2>&1", $nice_output );
 
 
 
1370
  if ( ewww_image_optimizer_iterable( $nice_output ) && isset( $nice_output[0] ) ) {
1371
  ewwwio_debug_message( "$path: {$nice_output[0]}" );
1372
  } else {
@@ -1381,24 +1368,8 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1381
  return true;
1382
  }
1383
  break;
1384
- case 't': // tar.
1385
- exec( "$path --version 2>&1", $tar_version );
1386
- if ( ewww_image_optimizer_iterable( $tar_version ) ) {
1387
- ewwwio_debug_message( "$path: {$tar_version[0]}" );
1388
- } else {
1389
- ewwwio_debug_message( "$path: invalid output" );
1390
- break;
1391
- }
1392
- if ( ! empty( $tar_version[0] ) && preg_match( '/bsdtar/', $tar_version[0] ) ) {
1393
- ewwwio_debug_message( 'tar found' );
1394
- return $tar_version[0];
1395
- } elseif ( ! empty( $tar_version[0] ) && preg_match( '/GNU tar/i', $tar_version[0] ) ) {
1396
- ewwwio_debug_message( 'tar found' );
1397
- return $tar_version[0];
1398
- }
1399
- break;
1400
  case 'w': // cwebp.
1401
- exec( "$path -version 2>&1", $webp_version );
1402
  if ( ewww_image_optimizer_iterable( $webp_version ) ) {
1403
  ewwwio_debug_message( "$path: {$webp_version[0]}" );
1404
  } else {
@@ -1631,11 +1602,10 @@ function ewww_image_optimizer_jpegtran_autorotate( $file, $type, $orientation )
1631
  if ( ! $orientation || 1 === (int) $orientation ) {
1632
  return false;
1633
  }
 
1634
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_CLOUD' ) || ! EWWW_IMAGE_OPTIMIZER_CLOUD ) {
1635
  ewww_image_optimizer_define_noexec();
1636
- if ( EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
1637
- $nice = '';
1638
- } else {
1639
  // Check to see if 'nice' exists.
1640
  $nice = ewww_image_optimizer_find_nix_binary( 'nice', 'n' );
1641
  }
@@ -1799,11 +1769,10 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1799
  if ( ! is_object( $ewww_image ) || ! $ewww_image instanceof EWWW_Image || $ewww_image->file !== $file ) {
1800
  $ewww_image = new EWWW_Image( 0, '', $file );
1801
  }
 
1802
  if ( ! EWWW_IMAGE_OPTIMIZER_CLOUD ) {
1803
  ewww_image_optimizer_define_noexec();
1804
- if ( EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
1805
- $nice = '';
1806
- } else {
1807
  // Check to see if 'nice' exists.
1808
  $nice = ewww_image_optimizer_find_nix_binary( 'nice', 'n' );
1809
  }
@@ -2648,8 +2617,14 @@ function ewww_image_optimizer_webp_create( $file, $orig_size, $type, $tool, $rec
2648
  if ( empty( $tool ) ) {
2649
  ewww_image_optimizer_cloud_optimizer( $file, $type, false, $webpfile, 'image/webp' );
2650
  } else {
2651
- // Check to see if 'nice' exists.
2652
- $nice = ewww_image_optimizer_find_nix_binary( 'nice', 'n' );
 
 
 
 
 
 
2653
  // Check to see if we are supposed to strip metadata.
2654
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) ) {
2655
  // Don't copy metadata.
31
  define( 'EWWW_IMAGE_OPTIMIZER_CLOUD', false );
32
  return;
33
  }
34
+ if (
35
+ ! defined( 'EWWW_IMAGE_OPTIMIZER_CLOUD' ) &&
36
+ ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) &&
37
+ ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) > 10 &&
38
+ ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) > 10
39
+ ) {
40
  define( 'EWWW_IMAGE_OPTIMIZER_CLOUD', true );
41
  } elseif ( ! defined( 'EWWW_IMAGE_OPTIMIZER_CLOUD' ) ) {
42
  define( 'EWWW_IMAGE_OPTIMIZER_CLOUD', false );
354
  $toolfail = false;
355
  if ( ! is_dir( EWWW_IMAGE_OPTIMIZER_TOOL_PATH ) && is_writable( dirname( EWWW_IMAGE_OPTIMIZER_TOOL_PATH ) ) ) {
356
  ewwwio_debug_message( 'folder does not exist, creating...' );
357
+ if ( ! wp_mkdir_p( EWWW_IMAGE_OPTIMIZER_TOOL_PATH ) ) {
358
  ewwwio_debug_message( 'could not create folder' );
359
  return;
360
  }
558
  // Check if exec is disabled.
559
  if ( ewww_image_optimizer_exec_check() ) {
560
  $no_compression = false;
561
+ if (
562
+ ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) &&
563
+ ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) &&
564
+ ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' )
565
+ ) {
566
  $no_compression = true;
567
  }
568
  // Need to be a little particular with the quiet parameter.
1206
  function ewww_image_optimizer_tool_found( $path, $tool ) {
1207
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1208
  ewwwio_debug_message( "testing case: $tool at $path" );
1209
+ $fork = '2>&1';
1210
+ if ( ( defined( 'EWWW_IMAGE_OPTIMIZER_FORK' ) && ! EWWW_IMAGE_OPTIMIZER_FORK ) || 'WINNT' === PHP_OS ) {
1211
+ $fork = '';
1212
+ }
1213
  // '*b' cases are 'blind' testing in case we can't get at the version string, but the binaries are actually working, we run a test compression, and compare the results with what they should be.
1214
  switch ( $tool ) {
1215
  case 'j': // jpegtran.
1216
+ exec( $path . ' -v ' . EWWW_IMAGE_OPTIMIZER_IMAGES_PATH . "sample.jpg $fork", $jpegtran_version );
1217
  if ( ewww_image_optimizer_iterable( $jpegtran_version ) ) {
1218
  ewwwio_debug_message( "$path: {$jpegtran_version[0]}" );
1219
  } else {
1242
  }
1243
  break;
1244
  case 'o': // optipng.
1245
+ exec( $path . " -v $fork", $optipng_version );
1246
  if ( ewww_image_optimizer_iterable( $optipng_version ) ) {
1247
  ewwwio_debug_message( "$path: {$optipng_version[0]}" );
1248
  } else {
1269
  }
1270
  break;
1271
  case 'g': // gifsicle.
1272
+ exec( $path . " --version $fork", $gifsicle_version );
1273
  if ( ewww_image_optimizer_iterable( $gifsicle_version ) ) {
1274
  ewwwio_debug_message( "$path: {$gifsicle_version[0]}" );
1275
  } else {
1296
  }
1297
  break;
1298
  case 'p': // pngout.
1299
+ exec( "$path $fork", $pngout_version );
1300
  if ( ewww_image_optimizer_iterable( $pngout_version ) ) {
1301
  ewwwio_debug_message( "$path: {$pngout_version[0]}" );
1302
  } else {
1323
  }
1324
  break;
1325
  case 'q': // pngquant.
1326
+ exec( $path . " -V $fork", $pngquant_version );
1327
  if ( ewww_image_optimizer_iterable( $pngquant_version ) ) {
1328
  ewwwio_debug_message( "$path: {$pngquant_version[0]}" );
1329
  } else {
1349
  return esc_html__( 'unknown', 'ewww-image-optimizer' );
1350
  }
1351
  break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1352
  case 'n': // nice.
1353
+ if ( PHP_OS === 'WINNT' ) {
1354
+ return false;
1355
+ }
1356
+ exec( "$path $fork", $nice_output );
1357
  if ( ewww_image_optimizer_iterable( $nice_output ) && isset( $nice_output[0] ) ) {
1358
  ewwwio_debug_message( "$path: {$nice_output[0]}" );
1359
  } else {
1368
  return true;
1369
  }
1370
  break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1371
  case 'w': // cwebp.
1372
+ exec( "$path -version $fork", $webp_version );
1373
  if ( ewww_image_optimizer_iterable( $webp_version ) ) {
1374
  ewwwio_debug_message( "$path: {$webp_version[0]}" );
1375
  } else {
1602
  if ( ! $orientation || 1 === (int) $orientation ) {
1603
  return false;
1604
  }
1605
+ $nice = '';
1606
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_CLOUD' ) || ! EWWW_IMAGE_OPTIMIZER_CLOUD ) {
1607
  ewww_image_optimizer_define_noexec();
1608
+ if ( ! EWWW_IMAGE_OPTIMIZER_NOEXEC && PHP_OS !== 'WINNT' ) {
 
 
1609
  // Check to see if 'nice' exists.
1610
  $nice = ewww_image_optimizer_find_nix_binary( 'nice', 'n' );
1611
  }
1769
  if ( ! is_object( $ewww_image ) || ! $ewww_image instanceof EWWW_Image || $ewww_image->file !== $file ) {
1770
  $ewww_image = new EWWW_Image( 0, '', $file );
1771
  }
1772
+ $nice = '';
1773
  if ( ! EWWW_IMAGE_OPTIMIZER_CLOUD ) {
1774
  ewww_image_optimizer_define_noexec();
1775
+ if ( ! EWWW_IMAGE_OPTIMIZER_NOEXEC && PHP_OS !== 'WINNT' ) {
 
 
1776
  // Check to see if 'nice' exists.
1777
  $nice = ewww_image_optimizer_find_nix_binary( 'nice', 'n' );
1778
  }
2617
  if ( empty( $tool ) ) {
2618
  ewww_image_optimizer_cloud_optimizer( $file, $type, false, $webpfile, 'image/webp' );
2619
  } else {
2620
+ $nice = '';
2621
+ if ( ! EWWW_IMAGE_OPTIMIZER_CLOUD ) {
2622
+ ewww_image_optimizer_define_noexec();
2623
+ if ( ! EWWW_IMAGE_OPTIMIZER_NOEXEC && PHP_OS !== 'WINNT' ) {
2624
+ // Check to see if 'nice' exists.
2625
+ $nice = ewww_image_optimizer_find_nix_binary( 'nice', 'n' );
2626
+ }
2627
+ }
2628
  // Check to see if we are supposed to strip metadata.
2629
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) ) {
2630
  // Don't copy metadata.