EWWW Image Optimizer - Version 4.4.2

Version Description

  • added: notice for Pantheon users that an API key is required
  • added: ExactDN fully supports protocol-relative urls for non-image resources
  • changed: better lazy load support in ExactDN
  • fixed: optimization failure produces rename() errors
  • fixed: folder scanner ignores files with no extension
  • fixed: Alt WebP blocks on Facebook tracking pixel
  • fixed: ExactDN srcset functions cause duplicate image requests with zoom=1
  • fixed: ExactDN srcset fill adds double arguments to urls
  • fixed: srcset fill generates notices with non-numeric widths
  • fixed: bulk scanner stuck in resume mode with nothing to do
Download this release

Release Info

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

Code changes from version 4.4.1 to 4.4.2

.travis.yml CHANGED
@@ -20,7 +20,7 @@ php:
20
 
21
  env:
22
  - WP_VERSION=latest WP_MULTISITE=0
23
- - WP_VERSION=4.6 WP_MULTISITE=0
24
 
25
  matrix:
26
  include:
20
 
21
  env:
22
  - WP_VERSION=latest WP_MULTISITE=0
23
+ - WP_VERSION=4.8 WP_MULTISITE=0
24
 
25
  matrix:
26
  include:
aux-optimize.php CHANGED
@@ -384,7 +384,8 @@ function ewww_image_optimizer_image_scan( $dir, $started = 0 ) {
384
  if ( $started && ! empty( $_REQUEST['ewww_scan'] ) && 0 === $file_counter % 100 && microtime( true ) - $started > apply_filters( 'ewww_image_optimizer_timeout', 15 ) ) {
385
  if ( ! empty( $reset_images ) ) {
386
  array_walk( $reset_images, 'intval' );
387
- $wpdb->query( "UPDATE $wpdb->ewwwio_images SET pending = 1 WHERE id IN (" . implode( ',', $reset_images ) . ')' ); // WPCS: unprepared SQL ok.
 
388
  }
389
  if ( ! empty( $images ) ) {
390
  ewww_image_optimizer_mass_insert( $wpdb->ewwwio_images, $images, array( '%s', '%d', '%d' ) );
@@ -415,7 +416,8 @@ function ewww_image_optimizer_image_scan( $dir, $started = 0 ) {
415
  }
416
  if ( ! empty( $reset_images ) ) {
417
  array_walk( $reset_images, 'intval' );
418
- $wpdb->query( "UPDATE $wpdb->ewwwio_images SET pending = 1 WHERE id IN (" . implode( ',', $reset_images ) . ')' ); // WPCS: unprepared SQL ok.
 
419
  }
420
  if ( ! empty( $images ) ) {
421
  ewww_image_optimizer_mass_insert( $wpdb->ewwwio_images, $images, array( '%s', '%d', '%d' ) );
@@ -438,7 +440,11 @@ function ewww_image_optimizer_image_scan( $dir, $started = 0 ) {
438
  if ( preg_match( '/(\/|\\\\)\./', $path ) && apply_filters( 'ewww_image_optimizer_ignore_hidden_files', true ) ) {
439
  continue;
440
  }
441
- $mime = ewww_image_optimizer_quick_mimetype( $path );
 
 
 
 
442
  if ( ! in_array( $mime, $enabled_types ) ) {
443
  continue;
444
  }
@@ -512,7 +518,8 @@ function ewww_image_optimizer_image_scan( $dir, $started = 0 ) {
512
  }
513
  if ( ! empty( $reset_images ) ) {
514
  array_walk( $reset_images, 'intval' );
515
- $wpdb->query( "UPDATE $wpdb->ewwwio_images SET pending = 1 WHERE id IN (" . implode( ',', $reset_images ) . ')' ); // WPCS: unprepared SQL ok.
 
516
  }
517
  delete_transient( 'ewww_image_optimizer_aux_iterator' );
518
  $end = microtime( true ) - $start;
384
  if ( $started && ! empty( $_REQUEST['ewww_scan'] ) && 0 === $file_counter % 100 && microtime( true ) - $started > apply_filters( 'ewww_image_optimizer_timeout', 15 ) ) {
385
  if ( ! empty( $reset_images ) ) {
386
  array_walk( $reset_images, 'intval' );
387
+ $reset_images_sql = '(' . implode( ',', $reset_images ) . ')';
388
+ $wpdb->query( "UPDATE $wpdb->ewwwio_images SET pending = 1 WHERE id IN $reset_images_sql" ); // WPCS: unprepared SQL ok.
389
  }
390
  if ( ! empty( $images ) ) {
391
  ewww_image_optimizer_mass_insert( $wpdb->ewwwio_images, $images, array( '%s', '%d', '%d' ) );
416
  }
417
  if ( ! empty( $reset_images ) ) {
418
  array_walk( $reset_images, 'intval' );
419
+ $reset_images_sql = '(' . implode( ',', $reset_images ) . ')';
420
+ $wpdb->query( "UPDATE $wpdb->ewwwio_images SET pending = 1 WHERE id IN $reset_images_sql" ); // WPCS: unprepared SQL ok.
421
  }
422
  if ( ! empty( $images ) ) {
423
  ewww_image_optimizer_mass_insert( $wpdb->ewwwio_images, $images, array( '%s', '%d', '%d' ) );
440
  if ( preg_match( '/(\/|\\\\)\./', $path ) && apply_filters( 'ewww_image_optimizer_ignore_hidden_files', true ) ) {
441
  continue;
442
  }
443
+ if ( defined( 'EWWW_IMAGE_OPTIMIZER_REAL_MIME' ) && EWWW_IMAGE_OPTIMIZER_REAL_MIME ) {
444
+ $mime = ewww_image_optimizer_mimetype( $path, 'i' );
445
+ } else {
446
+ $mime = ewww_image_optimizer_quick_mimetype( $path );
447
+ }
448
  if ( ! in_array( $mime, $enabled_types ) ) {
449
  continue;
450
  }
518
  }
519
  if ( ! empty( $reset_images ) ) {
520
  array_walk( $reset_images, 'intval' );
521
+ $reset_images_sql = '(' . implode( ',', $reset_images ) . ')';
522
+ $wpdb->query( "UPDATE $wpdb->ewwwio_images SET pending = 1 WHERE id IN $reset_images_sql" ); // WPCS: unprepared SQL ok.
523
  }
524
  delete_transient( 'ewww_image_optimizer_aux_iterator' );
525
  $end = microtime( true ) - $start;
bulk.php CHANGED
@@ -108,7 +108,7 @@ function ewww_image_optimizer_bulk_head_output() {
108
  </div>
109
  </div>
110
  <form class="ewww-bulk-form">
111
- <p><label for="ewww-force" style="font-weight: bold"><?php esc_html_e( 'Force re-optimize', 'ewww-image-optimizer' ); ?></label>
112
  &emsp;<input type="checkbox" id="ewww-force" name="ewww-force"<?php echo ( get_transient( 'ewww_image_optimizer_force_reopt' ) ) ? ' checked' : ''; ?>>
113
  &nbsp;<?php esc_html_e( 'Previously optimized images will be skipped by default, check this box before scanning to override.', 'ewww-image-optimizer' ); ?></p>
114
  <p><label for="ewww-delay" style="font-weight: bold"><?php esc_html_e( 'Choose how long to pause between images (in seconds, 0 = disabled)', 'ewww-image-optimizer' ); ?></label>&emsp;<input type="text" id="ewww-delay" name="ewww-delay" value="<?php echo $delay; ?>"></p>
@@ -223,17 +223,22 @@ function ewww_image_optimizer_count_optimized( $gallery ) {
223
  ewwwio_debug_message( 'we have received attachment ids via $_REQUEST' );
224
  // Retrieve the attachment IDs that were pre-loaded in the database.
225
  if ( 'scanning' == $resume ) {
 
226
  $finished = (array) get_option( 'ewww_image_optimizer_bulk_attachments' );
227
  $remaining = (array) get_option( 'ewww_image_optimizer_scanning_attachments' );
228
  $attachment_ids = array_merge( $finished, $remaining );
229
  } elseif ( $resume ) {
230
  // This shouldn't ever happen, but doesn't hurt to account for the use case, just in case something changes in the future.
 
231
  $attachment_ids = get_option( 'ewww_image_optimizer_bulk_attachments' );
232
  } else {
 
233
  $attachment_ids = get_option( 'ewww_image_optimizer_scanning_attachments' );
234
  }
235
  if ( ! empty( $attachment_ids ) ) {
236
  $full_count = count( $attachment_ids );
 
 
237
  }
238
  } else {
239
  $full_count = $wpdb->get_var( "SELECT COUNT(ID) FROM $wpdb->posts WHERE (post_type = 'attachment' OR post_type = 'ims_image') AND (post_mime_type LIKE '%%image%%' OR post_mime_type LIKE '%%pdf%%')" );
108
  </div>
109
  </div>
110
  <form class="ewww-bulk-form">
111
+ <p><label for="ewww-force" style="font-weight: bold"><?php esc_html_e( 'Force re-optimize', 'ewww-image-optimizer' ); ?></label><?php echo ewwwio_help_link( 'https://docs.ewww.io/article/65-force-re-optimization', '5bb640a7042863158cc711cd' ); ?>
112
  &emsp;<input type="checkbox" id="ewww-force" name="ewww-force"<?php echo ( get_transient( 'ewww_image_optimizer_force_reopt' ) ) ? ' checked' : ''; ?>>
113
  &nbsp;<?php esc_html_e( 'Previously optimized images will be skipped by default, check this box before scanning to override.', 'ewww-image-optimizer' ); ?></p>
114
  <p><label for="ewww-delay" style="font-weight: bold"><?php esc_html_e( 'Choose how long to pause between images (in seconds, 0 = disabled)', 'ewww-image-optimizer' ); ?></label>&emsp;<input type="text" id="ewww-delay" name="ewww-delay" value="<?php echo $delay; ?>"></p>
223
  ewwwio_debug_message( 'we have received attachment ids via $_REQUEST' );
224
  // Retrieve the attachment IDs that were pre-loaded in the database.
225
  if ( 'scanning' == $resume ) {
226
+ ewwwio_debug_message( 'still scanning media - phase 1' );
227
  $finished = (array) get_option( 'ewww_image_optimizer_bulk_attachments' );
228
  $remaining = (array) get_option( 'ewww_image_optimizer_scanning_attachments' );
229
  $attachment_ids = array_merge( $finished, $remaining );
230
  } elseif ( $resume ) {
231
  // This shouldn't ever happen, but doesn't hurt to account for the use case, just in case something changes in the future.
232
+ ewwwio_debug_message( 'this is the improbable, but it happened' );
233
  $attachment_ids = get_option( 'ewww_image_optimizer_bulk_attachments' );
234
  } else {
235
+ ewwwio_debug_message( 'we really did get attachments via $_REQUEST, or so we think' );
236
  $attachment_ids = get_option( 'ewww_image_optimizer_scanning_attachments' );
237
  }
238
  if ( ! empty( $attachment_ids ) ) {
239
  $full_count = count( $attachment_ids );
240
+ } else {
241
+ $full_count = $wpdb->get_var( "SELECT COUNT(ID) FROM $wpdb->posts WHERE (post_type = 'attachment' OR post_type = 'ims_image') AND (post_mime_type LIKE '%%image%%' OR post_mime_type LIKE '%%pdf%%')" );
242
  }
243
  } else {
244
  $full_count = $wpdb->get_var( "SELECT COUNT(ID) FROM $wpdb->posts WHERE (post_type = 'attachment' OR post_type = 'ims_image') AND (post_mime_type LIKE '%%image%%' OR post_mime_type LIKE '%%pdf%%')" );
changelog.txt CHANGED
@@ -1,3 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
  = 4.4.1 =
2
  * fixed: ExactDN srcset fill replaces images with first image on page
3
 
1
+ = 4.4.2 =
2
+ * added: notice for Pantheon users that an API key is required
3
+ * added: ExactDN fully supports protocol-relative urls for non-image resources
4
+ * changed: better lazy load support in ExactDN
5
+ * fixed: optimization failure produces rename() errors
6
+ * fixed: folder scanner ignores files with no extension
7
+ * fixed: Alt WebP blocks on Facebook tracking pixel
8
+ * fixed: ExactDN srcset functions cause duplicate image requests with zoom=1
9
+ * fixed: ExactDN srcset fill adds double arguments to urls
10
+ * fixed: srcset fill generates notices with non-numeric widths
11
+ * fixed: bulk scanner stuck in resume mode with nothing to do
12
+
13
  = 4.4.1 =
14
  * fixed: ExactDN srcset fill replaces images with first image on page
15
 
classes/class-ewwwio-alt-webp.php CHANGED
@@ -319,8 +319,17 @@ class EWWWIO_Alt_Webp extends EWWWIO_Page_Parser {
319
 
320
  // TODO: Eventually route through a custom parsing routine for noscript images.
321
  $noscript_images = $this->get_noscript_images_from_html( $buffer );
322
- if ( ! empty( $noscript_images ) ) {
323
- ewwwio_debug_message( 'noscript-encased images found, will not process any img elements' );
 
 
 
 
 
 
 
 
 
324
  }
325
  /* TODO: detect non-utf8 encoding and convert the buffer (if necessary). */
326
 
319
 
320
  // TODO: Eventually route through a custom parsing routine for noscript images.
321
  $noscript_images = $this->get_noscript_images_from_html( $buffer );
322
+ if ( ! empty( $noscript_images ) && isset( $noscript_images[0] ) ) {
323
+ foreach ( $noscript_images[0] as $nindex => $noscript_image ) {
324
+ if ( strpos( $noscript_image, 'facebook.com/tr?' ) ) {
325
+ unset( $noscript_images[0][ $nindex ] );
326
+ }
327
+ }
328
+ if ( empty( $noscript_images[0] ) ) {
329
+ $noscript_images = false;
330
+ } else {
331
+ ewwwio_debug_message( 'noscript-encased images found, will not process any img elements' );
332
+ }
333
  }
334
  /* TODO: detect non-utf8 encoding and convert the buffer (if necessary). */
335
 
classes/class-ewwwio-page-parser.php CHANGED
@@ -9,20 +9,11 @@
9
  if ( ! defined( 'ABSPATH' ) ) {
10
  exit;
11
  }
12
- // TODO: may remove content property.
13
  /**
14
  * HTML element and attribute parsing, replacing, etc.
15
  */
16
  class EWWWIO_Page_Parser {
17
 
18
- /**
19
- * The content to parse.
20
- *
21
- * @access public
22
- * @var string $content
23
- */
24
- public $content = '';
25
-
26
  /**
27
  * Match all images and any relevant <a> tags in a block of HTML.
28
  *
@@ -43,7 +34,7 @@ class EWWWIO_Page_Parser {
43
  }
44
  if ( preg_match_all( $search_pattern, $content, $images ) ) {
45
  foreach ( $images as $key => $unused ) {
46
- // Simplify the output as much as possible, mostly for confirming test results.
47
  if ( is_numeric( $key ) && $key > 0 ) {
48
  unset( $images[ $key ] );
49
  }
9
  if ( ! defined( 'ABSPATH' ) ) {
10
  exit;
11
  }
 
12
  /**
13
  * HTML element and attribute parsing, replacing, etc.
14
  */
15
  class EWWWIO_Page_Parser {
16
 
 
 
 
 
 
 
 
 
17
  /**
18
  * Match all images and any relevant <a> tags in a block of HTML.
19
  *
34
  }
35
  if ( preg_match_all( $search_pattern, $content, $images ) ) {
36
  foreach ( $images as $key => $unused ) {
37
+ // Simplify the output as much as possible.
38
  if ( is_numeric( $key ) && $key > 0 ) {
39
  unset( $images[ $key ] );
40
  }
classes/class-exactdn.php CHANGED
@@ -94,6 +94,14 @@ class ExactDN extends EWWWIO_Page_Parser {
94
  */
95
  private $elapsed_time = 0;
96
 
 
 
 
 
 
 
 
 
97
  /**
98
  * Register (once) actions and filters for ExactDN. If you want to use this class, use the global.
99
  */
@@ -546,7 +554,8 @@ class ExactDN extends EWWWIO_Page_Parser {
546
  public function get_img_width( $img ) {
547
  $width = $this->get_attribute( $img, 'width' );
548
  // Then check for an inline max-width directive.
549
- if ( preg_match( '#max-width:\s?(\d+)px#', $img, $max_width_string ) ) {
 
550
  if ( $max_width_string[1] && ( ! $width || $max_width_string[1] < $width ) ) {
551
  $width = $max_width_string[1];
552
  }
@@ -634,6 +643,8 @@ class ExactDN extends EWWWIO_Page_Parser {
634
  $attachment_id = false;
635
  $exactdn_url = false;
636
  $width = false;
 
 
637
 
638
  // Flag if we need to munge a fullsize URL.
639
  $fullsize_url = false;
@@ -655,23 +666,64 @@ class ExactDN extends EWWWIO_Page_Parser {
655
  }
656
 
657
  ewwwio_debug_message( 'made it passed the filters' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
658
  // Support Lazy Load plugins.
659
  // Don't modify $tag yet as we need unmodified version later.
660
- if ( preg_match( '#data-lazy-src=["|\'](.+?)["|\']#i', $images['img_tag'][ $index ], $lazy_load_src ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
661
  $placeholder_src = $src;
662
  $placeholder_src_orig = $src;
663
- $src = $lazy_load_src[1];
664
- $src_orig = $lazy_load_src[1];
665
- } elseif ( preg_match( '#data-lazy-original=["|\'](.+?)["|\']#i', $images['img_tag'][ $index ], $lazy_load_src ) ) {
 
 
 
 
 
666
  $placeholder_src = $src;
667
  $placeholder_src_orig = $src;
668
- $src = $lazy_load_src[1];
669
- $src_orig = $lazy_load_src[1];
670
- } elseif ( strpos( $images['img_tag'][ $index ], 'a3-lazy-load/assets/images/lazy_placeholder' ) && preg_match( '#data-src=["|\'](.+?)["|\']#i', $images['img_tag'][ $index ], $lazy_load_src ) ) {
 
 
 
 
 
 
 
671
  $placeholder_src = $src;
672
  $placeholder_src_orig = $src;
673
- $src = $lazy_load_src[1];
674
- $src_orig = $lazy_load_src[1];
 
675
  }
676
 
677
  // Check if image URL should be used with ExactDN.
@@ -859,12 +911,11 @@ class ExactDN extends EWWWIO_Page_Parser {
859
  // Insert new image src into the srcset as well, if we have a width.
860
  if ( false !== $width && false === strpos( $width, '%' ) ) {
861
  ewwwio_debug_message( 'checking to see if srcset width already exists' );
862
- $srcset_url = $exactdn_url . ' ' . (int) $width . 'w, ';
863
- if ( false === strpos( $tag, $width . 'w' ) ) {
864
- // For double-quotes...
865
- $new_tag = str_replace( 'srcset="', 'srcset="' . $srcset_url, $new_tag );
866
- // and for single-quotes.
867
- $new_tag = str_replace( "srcset='", "srcset='" . $srcset_url, $new_tag );
868
  }
869
  }
870
 
@@ -886,8 +937,8 @@ class ExactDN extends EWWWIO_Page_Parser {
886
  // Replace original tag with modified version.
887
  $content = str_replace( $tag, $new_tag, $content );
888
  }
889
- } elseif ( ! preg_match( '#data-lazy-(original|src)=#i', $images['img_tag'][ $index ] ) && $this->validate_image_url( $src, true ) ) {
890
- ewwwio_debug_message( 'found a potential exactdn src url to insert into srcset' );
891
  // Find the width attribute.
892
  $width = $this->get_img_width( $images['img_tag'][ $index ] );
893
  if ( $width ) {
@@ -902,13 +953,11 @@ class ExactDN extends EWWWIO_Page_Parser {
902
  $new_tag = $tag;
903
  $exactdn_url = $src;
904
  ewwwio_debug_message( 'checking to see if srcset width already exists' );
905
- $srcset_url = $exactdn_url . ' ' . (int) $width . 'w, ';
906
- if ( false === strpos( $tag, $width . 'w' ) ) {
 
907
  ewwwio_debug_message( 'src not in srcset, adding' );
908
- // For double-quotes...
909
- $new_tag = str_replace( 'srcset="', 'srcset="' . $srcset_url, $new_tag );
910
- // and for single-quotes.
911
- $new_tag = str_replace( "srcset='", "srcset='" . $srcset_url, $new_tag );
912
  // Replace original tag with modified version.
913
  $content = str_replace( $tag, $new_tag, $content );
914
  }
@@ -919,32 +968,33 @@ class ExactDN extends EWWWIO_Page_Parser {
919
  if ( ! empty( $exactdn_url ) ) {
920
  $src = $exactdn_url;
921
  }
922
- if ( ! ewww_image_optimizer_get_option( 'exactdn_prevent_srcset_fill' ) && ! preg_match( '#data-lazy-(original|src)=#i', $images['img_tag'][ $index ] ) && false !== strpos( $src, $this->exactdn_domain ) ) {
923
- if ( ! $this->get_attribute( $images['img_tag'][ $index ], 'srcset' ) && ! $this->get_attribute( $images['img_tag'][ $index ], 'sizes' ) ) {
924
  $zoom = false;
925
  // If $width is empty, we'll search the url for a width param, then we try searching the img element, with fall back to the filename.
926
- if ( empty( $width ) ) {
927
  // This only searches for w, resize, or fit flags, others are ignored.
928
  $width = $this->get_exactdn_width_from_url( $src );
929
  if ( $width ) {
930
  $zoom = true;
931
  }
932
  }
933
- if ( empty( $width ) ) {
934
  $width = $this->get_img_width( $images['img_tag'][ $index ] );
935
  }
936
- if ( empty( $width ) ) {
937
- list( $width, $discard_height ) = $this->get_dimensions_from_filename( $src );
 
938
  }
939
  if ( false !== strpos( $src, 'crop=' ) || false !== strpos( $src, '&h=' ) || false !== strpos( $src, '?h=' ) ) {
940
  $width = false;
941
  }
942
  // Then add a srcset and sizes.
943
  if ( $width ) {
944
- $srcset = $this->generate_image_srcset( $src, $width, $zoom );
945
  if ( $srcset ) {
946
  $new_tag = $images['img_tag'][ $index ];
947
- $this->set_attribute( $new_tag, 'srcset', $srcset );
948
  $this->set_attribute( $new_tag, 'sizes', sprintf( '(max-width: %1$dpx) 100vw, %1$dpx', $width ) );
949
  // Replace original tag with modified version.
950
  $content = str_replace( $images['img_tag'][ $index ], $new_tag, $content );
@@ -960,14 +1010,14 @@ class ExactDN extends EWWWIO_Page_Parser {
960
  $escaped_upload_domain = str_replace( '.', '\.', ltrim( $this->upload_domain, 'w.' ) );
961
  ewwwio_debug_message( $escaped_upload_domain );
962
  if ( ! empty( $this->user_exclusions ) ) {
963
- $content = preg_replace( '#(https?)://(?:www\.)?' . $escaped_upload_domain . '([^"\'?>]+?)?/wp-content/([^"\'?>]+?)?(' . implode( '|', $this->user_exclusions ) . ')#i', '$1://' . $this->upload_domain . '$2/?wpcontent-bypass?/$3$4', $content );
964
  }
965
  // Pre-empt rewriting of simple-social-icons SVG (because they aren't allowed in use tags.
966
- $content = preg_replace( '#(https?)://(?:www\.)?' . $escaped_upload_domain . '([^"\'?>]+?)?/wp-content/plugins/simple-social-icons#i', '$1://' . $this->upload_domain . '$2/?wpcontent-bypass?/plugins/simple-social-icons', $content );
967
  // Pre-empt rewriting of wp-includes and wp-content if the extension is not allowed by using a temporary placeholder.
968
- $content = preg_replace( '#(https?)://(?:www\.)?' . $escaped_upload_domain . '([^"\'?>]+?)?/wp-content/([^"\'?>]+?)\.(php|ashx|m4v|mov|wvm|qt|webm|ogv|mp4|m4p|mpg|mpeg|mpv)#i', '$1://' . $this->upload_domain . '$2/?wpcontent-bypass?/$3.$4', $content );
969
  $content = str_replace( 'wp-content/themes/jupiter"', '?wpcontent-bypass?/themes/jupiter"', $content );
970
- $content = preg_replace( '#(https?)://(?:www\.)?' . $escaped_upload_domain . '/([^"\'?>]+?)?(nextgen-image|wp-includes|wp-content)/#i', '$1://' . $this->exactdn_domain . '/$2$3/', $content );
971
  $content = str_replace( '?wpcontent-bypass?', 'wp-content', $content );
972
  }
973
  }
@@ -1432,7 +1482,9 @@ class ExactDN extends EWWWIO_Page_Parser {
1432
  }
1433
  } // foreach ( $currentwidths as $currentwidth ){
1434
 
1435
- if ( 'soft' == $crop ) {
 
 
1436
  $args = array(
1437
  'w' => $newwidth,
1438
  );
@@ -1497,17 +1549,21 @@ class ExactDN extends EWWWIO_Page_Parser {
1497
  * @param string $url The url of the image.
1498
  * @param int $width Image width to use for calculations.
1499
  * @param bool $zoom Whether to use zoom or w param.
1500
- * @uses this::validate_image_url, this::generate_url, this::parse_from_filename
1501
- * @uses this::strip_image_dimensions_maybe, this::get_content_width
1502
  * @return string A srcset attribute with ExactDN image urls and widths.
1503
  */
1504
- public function generate_image_srcset( $url, $width, $zoom = false ) {
1505
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1506
  // Don't foul up the admin side of things.
1507
  if ( is_admin() ) {
1508
  return '';
1509
  }
1510
 
 
 
 
 
1511
  /**
1512
  * Filter the multiplier ExactDN uses to create new srcset items.
1513
  * Return false to short-circuit and bypass auto-generation.
@@ -1521,7 +1577,10 @@ class ExactDN extends EWWWIO_Page_Parser {
1521
  *
1522
  * @param int|bool $width The max width for this $url, or false to bypass.
1523
  */
1524
- $width = apply_filters( 'exactdn_srcset_fill_width', $width, $url );
 
 
 
1525
  $srcset = '';
1526
 
1527
  if (
@@ -1535,8 +1594,13 @@ class ExactDN extends EWWWIO_Page_Parser {
1535
 
1536
  foreach ( $multipliers as $multiplier ) {
1537
  $newwidth = intval( $width * $multiplier );
 
 
 
1538
 
1539
- if ( $zoom ) {
 
 
1540
  $args = array(
1541
  'zoom' => $multiplier,
1542
  );
@@ -1922,6 +1986,9 @@ class ExactDN extends EWWWIO_Page_Parser {
1922
  if ( strpos( $image_url, 'LayerSlider/static/img' ) ) {
1923
  return array();
1924
  }
 
 
 
1925
  return $args;
1926
  }
1927
 
@@ -2041,13 +2108,13 @@ class ExactDN extends EWWWIO_Page_Parser {
2041
  $webp_quality = apply_filters( 'jpeg_quality', $jpg_quality, 'image/webp' );
2042
 
2043
  $more_args = array();
2044
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) ) {
2045
  $more_args['strip'] = 'all';
2046
  }
2047
- if ( ewww_image_optimizer_get_option( 'exactdn_lossy' ) ) {
2048
  $more_args['lossy'] = is_numeric( ewww_image_optimizer_get_option( 'exactdn_lossy' ) ) ? (int) ewww_image_optimizer_get_option( 'exactdn_lossy' ) : 80;
2049
  }
2050
- if ( ! is_null( $jpg_quality ) && 82 != $jpg_quality ) {
2051
  $more_args['quality'] = $jpg_quality;
2052
  }
2053
  // Merge given args with the automatic (option-based) args, and also makes sure args is an array if it was previously a string.
94
  */
95
  private $elapsed_time = 0;
96
 
97
+ /**
98
+ * Keep track of the attribute we use for srcset, in case a lazy load plugin is active.
99
+ *
100
+ * @access private
101
+ * @var string $srcset_attr
102
+ */
103
+ private $srcset_attr = 'srcset';
104
+
105
  /**
106
  * Register (once) actions and filters for ExactDN. If you want to use this class, use the global.
107
  */
554
  public function get_img_width( $img ) {
555
  $width = $this->get_attribute( $img, 'width' );
556
  // Then check for an inline max-width directive.
557
+ $style = $this->get_attribute( $img, 'style' );
558
+ if ( $style && preg_match( '#max-width:\s?(\d+)px#', $style, $max_width_string ) ) {
559
  if ( $max_width_string[1] && ( ! $width || $max_width_string[1] < $width ) ) {
560
  $width = $max_width_string[1];
561
  }
643
  $attachment_id = false;
644
  $exactdn_url = false;
645
  $width = false;
646
+ $lazy = false;
647
+ $srcset_fill = false;
648
 
649
  // Flag if we need to munge a fullsize URL.
650
  $fullsize_url = false;
666
  }
667
 
668
  ewwwio_debug_message( 'made it passed the filters' );
669
+
670
+ // Pre-empt srcset fill if the surrounding link has a background image or if there is a data-desktop attribute indicating a potential slider.
671
+ if ( strpos( $tag, 'background-image:' ) || strpos( $tag, 'data-desktop=' ) ) {
672
+ $srcset_fill = false;
673
+ }
674
+ /**
675
+ * Documented in generate_url, in this case used to detect images that should bypass srcset fill.
676
+ *
677
+ * @param array|string $args Array of ExactDN arguments.
678
+ * @param string $image_url Image URL.
679
+ * @param string|null $scheme Image scheme. Default to null.
680
+ */
681
+ $args = apply_filters( 'exactdn_pre_args', array( 'test' => 'lazy-test' ), $src, null );
682
+ if ( empty( $args ) ) {
683
+ $srcset_fill = false;
684
+ }
685
  // Support Lazy Load plugins.
686
  // Don't modify $tag yet as we need unmodified version later.
687
+ $lazy_load_src = $this->get_attribute( $images['img_tag'][ $index ], 'data-lazy-src' );
688
+ if ( $lazy_load_src ) {
689
+ $placeholder_src = $src;
690
+ $placeholder_src_orig = $src;
691
+ $src = $lazy_load_src;
692
+ $src_orig = $lazy_load_src;
693
+ $this->srcset_attr = 'data-lazy-srcset';
694
+ $lazy = true;
695
+ $srcset_fill = true;
696
+ }
697
+ // Must be a legacy Jetpack thing as far as I can tell, no matches found in any currently installed plugins.
698
+ $lazy_load_src = $this->get_attribute( $images['img_tag'][ $index ], 'data-lazy-original' );
699
+ if ( ! $lazy && $lazy_load_src ) {
700
  $placeholder_src = $src;
701
  $placeholder_src_orig = $src;
702
+ $src = $lazy_load_src;
703
+ $src_orig = $lazy_load_src;
704
+ $lazy = true;
705
+ }
706
+ if ( ! $lazy && strpos( $images['img_tag'][ $index ], 'a3-lazy-load/assets/images/lazy_placeholder' ) ) {
707
+ $lazy_load_src = $this->get_attribute( $images['img_tag'][ $index ], 'data-src' );
708
+ }
709
+ if ( ! $lazy && $lazy_load_src ) {
710
  $placeholder_src = $src;
711
  $placeholder_src_orig = $src;
712
+ $src = $lazy_load_src;
713
+ $src_orig = $lazy_load_src;
714
+ $this->srcset_attr = 'data-srcset';
715
+ $lazy = true;
716
+ $srcset_fill = true;
717
+ }
718
+ if ( ! $lazy && strpos( $images['img_tag'][ $index ], 'revslider/admin/assets/images/dummy' ) ) {
719
+ $lazy_load_src = $this->get_attribute( $images['img_tag'][ $index ], 'data-lazyload' );
720
+ }
721
+ if ( ! $lazy && $lazy_load_src ) {
722
  $placeholder_src = $src;
723
  $placeholder_src_orig = $src;
724
+ $src = $lazy_load_src;
725
+ $src_orig = $lazy_load_src;
726
+ $lazy = true;
727
  }
728
 
729
  // Check if image URL should be used with ExactDN.
911
  // Insert new image src into the srcset as well, if we have a width.
912
  if ( false !== $width && false === strpos( $width, '%' ) ) {
913
  ewwwio_debug_message( 'checking to see if srcset width already exists' );
914
+ $srcset_url = $exactdn_url . ' ' . (int) $width . 'w, ';
915
+ $new_srcset_attr = $this->get_attribute( $new_tag, $this->srcset_attr );
916
+ if ( $new_srcset_attr && false === strpos( $new_srcset_attr, ' ' . (int) $width . 'w' ) ) {
917
+ ewwwio_debug_message( 'src not in srcset, adding' );
918
+ $this->set_attribute( $new_tag, $this->srcset_attr, $srcset_url . $new_srcset_attr );
 
919
  }
920
  }
921
 
937
  // Replace original tag with modified version.
938
  $content = str_replace( $tag, $new_tag, $content );
939
  }
940
+ } elseif ( ! $lazy && $this->validate_image_url( $src, true ) ) {
941
+ ewwwio_debug_message( "found a potential exactdn src url to insert into srcset: $src" );
942
  // Find the width attribute.
943
  $width = $this->get_img_width( $images['img_tag'][ $index ] );
944
  if ( $width ) {
953
  $new_tag = $tag;
954
  $exactdn_url = $src;
955
  ewwwio_debug_message( 'checking to see if srcset width already exists' );
956
+ $srcset_url = $exactdn_url . ' ' . (int) $width . 'w, ';
957
+ $new_srcset_attr = $this->get_attribute( $new_tag, $this->srcset_attr );
958
+ if ( $new_srcset_attr && false === strpos( $new_srcset_attr, ' ' . (int) $width . 'w' ) ) {
959
  ewwwio_debug_message( 'src not in srcset, adding' );
960
+ $this->set_attribute( $new_tag, $this->srcset_attr, $srcset_url . $new_srcset_attr );
 
 
 
961
  // Replace original tag with modified version.
962
  $content = str_replace( $tag, $new_tag, $content );
963
  }
968
  if ( ! empty( $exactdn_url ) ) {
969
  $src = $exactdn_url;
970
  }
971
+ if ( $srcset_fill && ! ewww_image_optimizer_get_option( 'exactdn_prevent_srcset_fill' ) && false !== strpos( $src, $this->exactdn_domain ) ) {
972
+ if ( ! $this->get_attribute( $images['img_tag'][ $index ], $this->srcset_attr ) && ! $this->get_attribute( $images['img_tag'][ $index ], 'sizes' ) ) {
973
  $zoom = false;
974
  // If $width is empty, we'll search the url for a width param, then we try searching the img element, with fall back to the filename.
975
+ if ( empty( $width ) || ! is_numeric( $width ) ) {
976
  // This only searches for w, resize, or fit flags, others are ignored.
977
  $width = $this->get_exactdn_width_from_url( $src );
978
  if ( $width ) {
979
  $zoom = true;
980
  }
981
  }
982
+ if ( empty( $width ) || ! is_numeric( $width ) ) {
983
  $width = $this->get_img_width( $images['img_tag'][ $index ] );
984
  }
985
+ list( $filename_width, $discard_height ) = $this->get_dimensions_from_filename( $src );
986
+ if ( empty( $width ) || ! is_numeric( $width ) ) {
987
+ $width = $filename_width;
988
  }
989
  if ( false !== strpos( $src, 'crop=' ) || false !== strpos( $src, '&h=' ) || false !== strpos( $src, '?h=' ) ) {
990
  $width = false;
991
  }
992
  // Then add a srcset and sizes.
993
  if ( $width ) {
994
+ $srcset = $this->generate_image_srcset( $src, $width, $zoom, $filename_width );
995
  if ( $srcset ) {
996
  $new_tag = $images['img_tag'][ $index ];
997
+ $this->set_attribute( $new_tag, $this->srcset_attr, $srcset );
998
  $this->set_attribute( $new_tag, 'sizes', sprintf( '(max-width: %1$dpx) 100vw, %1$dpx', $width ) );
999
  // Replace original tag with modified version.
1000
  $content = str_replace( $images['img_tag'][ $index ], $new_tag, $content );
1010
  $escaped_upload_domain = str_replace( '.', '\.', ltrim( $this->upload_domain, 'w.' ) );
1011
  ewwwio_debug_message( $escaped_upload_domain );
1012
  if ( ! empty( $this->user_exclusions ) ) {
1013
+ $content = preg_replace( '#(https?:)?//(?:www\.)?' . $escaped_upload_domain . '([^"\'?>]+?)?/wp-content/([^"\'?>]+?)?(' . implode( '|', $this->user_exclusions ) . ')#i', '$1://' . $this->upload_domain . '$2/?wpcontent-bypass?/$3$4', $content );
1014
  }
1015
  // Pre-empt rewriting of simple-social-icons SVG (because they aren't allowed in use tags.
1016
+ $content = preg_replace( '#(https?:)?//(?:www\.)?' . $escaped_upload_domain . '([^"\'?>]+?)?/wp-content/plugins/simple-social-icons#i', '$1//' . $this->upload_domain . '$2/?wpcontent-bypass?/plugins/simple-social-icons', $content );
1017
  // Pre-empt rewriting of wp-includes and wp-content if the extension is not allowed by using a temporary placeholder.
1018
+ $content = preg_replace( '#(https?:)?//(?:www\.)?' . $escaped_upload_domain . '([^"\'?>]+?)?/wp-content/([^"\'?>]+?)\.(php|ashx|m4v|mov|wvm|qt|webm|ogv|mp4|m4p|mpg|mpeg|mpv)#i', '$1://' . $this->upload_domain . '$2/?wpcontent-bypass?/$3.$4', $content );
1019
  $content = str_replace( 'wp-content/themes/jupiter"', '?wpcontent-bypass?/themes/jupiter"', $content );
1020
+ $content = preg_replace( '#(https?:)?//(?:www\.)?' . $escaped_upload_domain . '/([^"\'?>]+?)?(nextgen-image|wp-includes|wp-content)/#i', '$1//' . $this->exactdn_domain . '/$2$3/', $content );
1021
  $content = str_replace( '?wpcontent-bypass?', 'wp-content', $content );
1022
  }
1023
  }
1482
  }
1483
  } // foreach ( $currentwidths as $currentwidth ){
1484
 
1485
+ if ( 1 === $multiplier ) {
1486
+ $args = array();
1487
+ } elseif ( 'soft' == $crop ) {
1488
  $args = array(
1489
  'w' => $newwidth,
1490
  );
1549
  * @param string $url The url of the image.
1550
  * @param int $width Image width to use for calculations.
1551
  * @param bool $zoom Whether to use zoom or w param.
1552
+ * @param int $filename_width The width derived from the filename, or false.
1553
+ * @uses this::generate_url
1554
  * @return string A srcset attribute with ExactDN image urls and widths.
1555
  */
1556
+ public function generate_image_srcset( $url, $width, $zoom = false, $filename_width = false ) {
1557
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1558
  // Don't foul up the admin side of things.
1559
  if ( is_admin() ) {
1560
  return '';
1561
  }
1562
 
1563
+ if ( ! is_numeric( $width ) ) {
1564
+ return '';
1565
+ }
1566
+
1567
  /**
1568
  * Filter the multiplier ExactDN uses to create new srcset items.
1569
  * Return false to short-circuit and bypass auto-generation.
1577
  *
1578
  * @param int|bool $width The max width for this $url, or false to bypass.
1579
  */
1580
+ $width = (int) apply_filters( 'exactdn_srcset_fill_width', $width, $url );
1581
+ if ( ! $width ) {
1582
+ return '';
1583
+ }
1584
  $srcset = '';
1585
 
1586
  if (
1594
 
1595
  foreach ( $multipliers as $multiplier ) {
1596
  $newwidth = intval( $width * $multiplier );
1597
+ if ( $filename_width && $newwidth > $filename_width ) {
1598
+ continue;
1599
+ }
1600
 
1601
+ if ( 1 === $multiplier ) {
1602
+ $args = array();
1603
+ } elseif ( $zoom ) {
1604
  $args = array(
1605
  'zoom' => $multiplier,
1606
  );
1986
  if ( strpos( $image_url, 'LayerSlider/static/img' ) ) {
1987
  return array();
1988
  }
1989
+ if ( strpos( $image_url, 'lazy-load/images/' ) ) {
1990
+ return array();
1991
+ }
1992
  return $args;
1993
  }
1994
 
2108
  $webp_quality = apply_filters( 'jpeg_quality', $jpg_quality, 'image/webp' );
2109
 
2110
  $more_args = array();
2111
+ if ( false === strpos( $image_url, 'strip=all' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) ) {
2112
  $more_args['strip'] = 'all';
2113
  }
2114
+ if ( false === strpos( $image_url, 'lossy=' ) && ewww_image_optimizer_get_option( 'exactdn_lossy' ) ) {
2115
  $more_args['lossy'] = is_numeric( ewww_image_optimizer_get_option( 'exactdn_lossy' ) ) ? (int) ewww_image_optimizer_get_option( 'exactdn_lossy' ) : 80;
2116
  }
2117
+ if ( false === strpos( $image_url, 'quality=' ) && ! is_null( $jpg_quality ) && 82 != $jpg_quality ) {
2118
  $more_args['quality'] = $jpg_quality;
2119
  }
2120
  // Merge given args with the automatic (option-based) args, and also makes sure args is an array if it was previously a string.
common.php CHANGED
@@ -18,14 +18,14 @@
18
  // TODO: write some conversion tests.
19
  // TODO: check this patch, to see if the use of 'full' causes any issues: https://core.trac.wordpress.org/ticket/37840 .
20
  // TODO: use this: https://codex.wordpress.org/AJAX_in_Plugins#The_post-load_JavaScript_Event .
21
- // TODO: handle relative urls with ExactDN.
22
- // TODO: see if we can parse all use tags and use the bypass mechanism to avoid ExactDN + SVG issues.
23
  // TODO: can some of the bulk "fallbacks" be implemented for async processing?
24
  if ( ! defined( 'ABSPATH' ) ) {
25
  exit;
26
  }
27
 
28
- define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '441.0' );
29
 
30
  // Initialize a couple globals.
31
  $ewww_debug = '';
@@ -3371,10 +3371,11 @@ function ewww_image_optimizer_cloud_optimizer( $file, $type, $convert = false, $
3371
  $newsize = filesize( $tempfile );
3372
  ewwwio_debug_message( "cloud results: $newsize (new) vs. $orig_size (original)" );
3373
  rename( $tempfile, $newfile );
3374
- } elseif ( ewww_image_optimizer_mimetype( $tempfile, 'i' ) == $newtype ) {
3375
  $converted = true;
3376
  $newsize = filesize( $tempfile );
3377
  ewwwio_debug_message( "cloud results: $newsize (new) vs. $orig_size (original)" );
 
3378
  rename( $tempfile, $newfile );
3379
  $file = $newfile;
3380
  } else {
@@ -6001,6 +6002,9 @@ function ewww_image_optimizer_quick_mimetype( $path ) {
6001
  case 'pdf':
6002
  return 'application/pdf';
6003
  default:
 
 
 
6004
  return false;
6005
  }
6006
  }
@@ -7277,8 +7281,12 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7277
  ewwwio_debug_message( 'site url: ' . get_site_url() );
7278
  ewwwio_debug_message( 'content_url: ' . content_url() );
7279
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_NOEXEC' ) ) {
7280
- ewww_image_optimizer_tool_init();
7281
- ewww_image_optimizer_notice_utils( 'quiet' );
 
 
 
 
7282
  }
7283
  $network_class = $network;
7284
  if ( empty( $network ) ) {
18
  // TODO: write some conversion tests.
19
  // TODO: check this patch, to see if the use of 'full' causes any issues: https://core.trac.wordpress.org/ticket/37840 .
20
  // TODO: use this: https://codex.wordpress.org/AJAX_in_Plugins#The_post-load_JavaScript_Event .
21
+ // TODO: relative urls with ExactDN: https://github.com/nosilver4u/ewww-image-optimizer/issues/17 .
22
+ // TODO: avoid ExactDN + SVG issues in <use> tags: https://github.com/nosilver4u/ewww-image-optimizer/issues/18 .
23
  // TODO: can some of the bulk "fallbacks" be implemented for async processing?
24
  if ( ! defined( 'ABSPATH' ) ) {
25
  exit;
26
  }
27
 
28
+ define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '442.0' );
29
 
30
  // Initialize a couple globals.
31
  $ewww_debug = '';
3371
  $newsize = filesize( $tempfile );
3372
  ewwwio_debug_message( "cloud results: $newsize (new) vs. $orig_size (original)" );
3373
  rename( $tempfile, $newfile );
3374
+ } elseif ( ! is_null( $newtype ) && ! is_null( $newfile ) && ewww_image_optimizer_mimetype( $tempfile, 'i' ) == $newtype ) {
3375
  $converted = true;
3376
  $newsize = filesize( $tempfile );
3377
  ewwwio_debug_message( "cloud results: $newsize (new) vs. $orig_size (original)" );
3378
+ ewwwio_debug_message( "renaming file from $tempfile to $newfile" );
3379
  rename( $tempfile, $newfile );
3380
  $file = $newfile;
3381
  } else {
6002
  case 'pdf':
6003
  return 'application/pdf';
6004
  default:
6005
+ if ( empty( $pathextension ) && 0 !== strpos( $path, 's3' ) && is_file( $path ) ) {
6006
+ return ewww_image_optimizer_mimetype( $path, 'i' );
6007
+ }
6008
  return false;
6009
  }
6010
  }
7281
  ewwwio_debug_message( 'site url: ' . get_site_url() );
7282
  ewwwio_debug_message( 'content_url: ' . content_url() );
7283
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_NOEXEC' ) ) {
7284
+ if ( defined( 'EWWW_IMAGE_OPTIMIZER_CLOUD' ) && EWWW_IMAGE_OPTIMIZER_CLOUD ) {
7285
+ ewww_image_optimizer_disable_tools();
7286
+ } else {
7287
+ ewww_image_optimizer_tool_init();
7288
+ ewww_image_optimizer_notice_utils( 'quiet' );
7289
+ }
7290
  }
7291
  $network_class = $network;
7292
  if ( empty( $network ) ) {
ewww-image-optimizer.php CHANGED
@@ -14,7 +14,7 @@ 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: Shane Bishop
16
  Text Domain: ewww-image-optimizer
17
- Version: 4.4.1
18
  Author URI: https://ewww.io/
19
  License: GPLv3
20
  */
14
  Description: Reduce file sizes for images within WordPress including NextGEN Gallery and GRAND FlAGallery. Uses jpegtran, optipng/pngout, and gifsicle.
15
  Author: Shane Bishop
16
  Text Domain: ewww-image-optimizer
17
+ Version: 4.4.2
18
  Author URI: https://ewww.io/
19
  License: GPLv3
20
  */
includes/eio.js CHANGED
@@ -37,6 +37,39 @@ jQuery(document).ready(function($) {
37
  $(this).children('.toggle-indicator').attr('aria-hidden', 'false');
38
  }
39
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  if (!ewww_vars.scan_fail) {
41
  $('#ewww-webp-rewrite #ewww-webp-insert').click(function() {
42
  var ewww_webp_rewrite_action = 'ewww_webp_rewrite';
@@ -140,39 +173,6 @@ jQuery(document).ready(function($) {
140
  $('#ewww-resize-settings').hide();
141
  $('#ewww-conversion-settings').show();
142
  });
143
- function HSregister() {
144
- if (typeof(HS) !== 'undefined' ) {
145
- $('.ewww-overrides-nav').click(function() {
146
- HS.beacon.ready(function() {
147
- event.preventDefault();
148
- HS.beacon.show('59710ce4042863033a1b45a6');
149
- });
150
- });
151
- $('.ewww-docs-root').click(function() {
152
- HS.beacon.ready(function() {
153
- event.preventDefault();
154
- HS.beacon.open();
155
- });
156
- });
157
- $('.ewww-help-beacon-multi').click(function() {
158
- var hsids = $(this).attr('data-beacon-articles');
159
- hsids = hsids.split(',');
160
- HS.beacon.ready(function() {
161
- event.preventDefault();
162
- HS.beacon.suggest(hsids);
163
- HS.beacon.open();
164
- });
165
- });
166
- $('.ewww-help-beacon-single').click(function() {
167
- var hsid = $(this).attr('data-beacon-article');
168
- HS.beacon.ready(function() {
169
- event.preventDefault();
170
- HS.beacon.show(hsid);
171
- });
172
- });
173
- }
174
- }
175
- HSregister();
176
  $('.ewww-guage').tooltip({
177
  items: '.ewww-guage',
178
  content: function() {
37
  $(this).children('.toggle-indicator').attr('aria-hidden', 'false');
38
  }
39
  });
40
+ function HSregister() {
41
+ if (typeof(HS) !== 'undefined' ) {
42
+ $('.ewww-overrides-nav').click(function() {
43
+ HS.beacon.ready(function() {
44
+ event.preventDefault();
45
+ HS.beacon.show('59710ce4042863033a1b45a6');
46
+ });
47
+ });
48
+ $('.ewww-docs-root').click(function() {
49
+ HS.beacon.ready(function() {
50
+ event.preventDefault();
51
+ HS.beacon.open();
52
+ });
53
+ });
54
+ $('.ewww-help-beacon-multi').click(function() {
55
+ var hsids = $(this).attr('data-beacon-articles');
56
+ hsids = hsids.split(',');
57
+ HS.beacon.ready(function() {
58
+ event.preventDefault();
59
+ HS.beacon.suggest(hsids);
60
+ HS.beacon.open();
61
+ });
62
+ });
63
+ $('.ewww-help-beacon-single').click(function() {
64
+ var hsid = $(this).attr('data-beacon-article');
65
+ HS.beacon.ready(function() {
66
+ event.preventDefault();
67
+ HS.beacon.show(hsid);
68
+ });
69
+ });
70
+ }
71
+ }
72
+ HSregister();
73
  if (!ewww_vars.scan_fail) {
74
  $('#ewww-webp-rewrite #ewww-webp-insert').click(function() {
75
  var ewww_webp_rewrite_action = 'ewww_webp_rewrite';
173
  $('#ewww-resize-settings').hide();
174
  $('#ewww-conversion-settings').show();
175
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  $('.ewww-guage').tooltip({
177
  items: '.ewww-guage',
178
  content: function() {
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.6
6
  Tested up to: 4.9
7
  Requires PHP: 5.5
8
- Stable tag: 4.4.1
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,18 @@ http://developer.yahoo.com/performance/rules.html#opt_images
174
  * Feature requests can be submitted via https://ewww.io/contact-us/ and commented on here: https://trello.com/b/Fp81dWof/ewww-image-optimizer
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.4.1 =
178
  * fixed: ExactDN srcset fill replaces images with first image on page
179
 
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: 4.9
7
  Requires PHP: 5.5
8
+ Stable tag: 4.4.2
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 submitted via https://ewww.io/contact-us/ and commented on here: https://trello.com/b/Fp81dWof/ewww-image-optimizer
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.4.2 =
178
+ * added: notice for Pantheon users that an API key is required
179
+ * added: ExactDN fully supports protocol-relative urls for non-image resources
180
+ * changed: better lazy load support in ExactDN
181
+ * fixed: optimization failure produces rename() errors
182
+ * fixed: folder scanner ignores files with no extension
183
+ * fixed: Alt WebP blocks on Facebook tracking pixel
184
+ * fixed: ExactDN srcset functions cause duplicate image requests with zoom=1
185
+ * fixed: ExactDN srcset fill adds double arguments to urls
186
+ * fixed: srcset fill generates notices with non-numeric widths
187
+ * fixed: bulk scanner stuck in resume mode with nothing to do
188
+
189
  = 4.4.1 =
190
  * fixed: ExactDN srcset fill replaces images with first image on page
191
 
tests/test-optimize.php CHANGED
@@ -191,7 +191,7 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
191
  update_site_option( 'ewww_image_optimizer_cloud_key', '' );
192
  $this->assertEquals( 1335586, filesize( $results[0] ) );
193
  unlink( $results[0] );
194
- $this->assertEquals( 277992, filesize( $results[0] . '.webp' ) );
195
  if ( is_file( $results[0] . '.webp' ) ) {
196
  unlink( $results[0] . '.webp' );
197
  }
@@ -220,7 +220,7 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
220
  $this->assertEquals( ewww_image_optimizer_get_orientation( $results[0], 'image/jpeg' ), 1 );
221
  unlink( $results[0] );
222
  // size of webp with meta.
223
- $this->assertEquals( 297578, filesize( $results[0] . '.webp' ) );
224
  if ( is_file( $results[0] . '.webp' ) ) {
225
  unlink( $results[0] . '.webp' );
226
  }
@@ -368,7 +368,7 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
368
  $results = $this->optimize_png();
369
  update_option( 'ewww_image_optimizer_cloud_key', '' );
370
  update_site_option( 'ewww_image_optimizer_cloud_key', '' );
371
- $this->assertEquals( 37557, filesize( $results[0] ) );
372
  unlink( $results[0] );
373
  }
374
 
191
  update_site_option( 'ewww_image_optimizer_cloud_key', '' );
192
  $this->assertEquals( 1335586, filesize( $results[0] ) );
193
  unlink( $results[0] );
194
+ $this->assertEquals( 284142, filesize( $results[0] . '.webp' ) );
195
  if ( is_file( $results[0] . '.webp' ) ) {
196
  unlink( $results[0] . '.webp' );
197
  }
220
  $this->assertEquals( ewww_image_optimizer_get_orientation( $results[0], 'image/jpeg' ), 1 );
221
  unlink( $results[0] );
222
  // size of webp with meta.
223
+ $this->assertEquals( 303728, filesize( $results[0] . '.webp' ) );
224
  if ( is_file( $results[0] . '.webp' ) ) {
225
  unlink( $results[0] . '.webp' );
226
  }
368
  $results = $this->optimize_png();
369
  update_option( 'ewww_image_optimizer_cloud_key', '' );
370
  update_site_option( 'ewww_image_optimizer_cloud_key', '' );
371
+ $this->assertLessThanOrEqual( 38442, filesize( $results[0] ) );
372
  unlink( $results[0] );
373
  }
374
 
unique.php CHANGED
@@ -54,21 +54,21 @@ function ewww_image_optimizer_exec_init() {
54
  if ( EWWW_IMAGE_OPTIMIZER_CLOUD ) {
55
  ewwwio_debug_message( 'cloud options enabled, shutting off binaries' );
56
  ewww_image_optimizer_disable_tools();
57
- // Check if this is an unsupported OS (not Linux or Mac OSX or FreeBSD or Windows or SunOS).
58
- } elseif ( defined( 'WPCOMSH_VERSION' ) ) {
59
  if (
60
  ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) &&
61
  empty( $_POST['ewww_image_optimizer_cloud_key'] ) &&
62
  ( ! is_object( $exactdn ) || ! $exactdn->get_exactdn_domain() )
63
  ) {
64
- add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_wpcom' );
65
- add_action( 'admin_notices', 'ewww_image_optimizer_notice_wpcom' );
66
  }
67
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_NOEXEC' ) ) {
68
  define( 'EWWW_IMAGE_OPTIMIZER_NOEXEC', true );
69
  }
70
  ewwwio_debug_message( 'wp.com site, disabling tools' );
71
  ewww_image_optimizer_disable_tools();
 
72
  } elseif ( 'Linux' != PHP_OS && 'Darwin' != PHP_OS && 'FreeBSD' != PHP_OS && 'WINNT' != PHP_OS && 'SunOS' != PHP_OS ) {
73
  // Call the function to display a notice.
74
  add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_os' );
@@ -123,9 +123,9 @@ function ewww_image_optimizer_set_defaults() {
123
  }
124
 
125
  /**
126
- * Let the user know the plugin requires API/ExactDN to operate at wp.com.
127
  */
128
- function ewww_image_optimizer_notice_wpcom() {
129
  if ( ! function_exists( 'is_plugin_active_for_network' ) && is_multisite() ) {
130
  // Need to include the plugin library for the is_plugin_active function.
131
  require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
@@ -135,9 +135,17 @@ function ewww_image_optimizer_notice_wpcom() {
135
  } else {
136
  $options_page = 'options-general.php';
137
  }
 
 
 
 
 
 
 
138
  $settings_url = admin_url( "$options_page?page=" . plugin_basename( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ) );
139
  echo "<div id='ewww-image-optimizer-cloud-key-required' class='error'><p><strong>" .
140
- esc_html__( 'The EWWW Image Optimizer requires an API key or an ExactDN subscription to optimize images on WordPress.com sites.', 'ewww-image-optimizer-cloud' ) .
 
141
  "</strong> <a href='https://ewww.io/plans/'>" . esc_html__( 'Purchase a subscription.', 'ewww-image-optimizer-cloud' ) .
142
  "</a> <a href='$settings_url'>" . esc_html__( 'Then, activate it on the settings page.', 'ewww-image-optimizer-cloud' ) . '</a></p></div>';
143
  }
54
  if ( EWWW_IMAGE_OPTIMIZER_CLOUD ) {
55
  ewwwio_debug_message( 'cloud options enabled, shutting off binaries' );
56
  ewww_image_optimizer_disable_tools();
57
+ } elseif ( defined( 'WPCOMSH_VERSION' ) || ! empty( $_ENV['PANTHEON_ENVIRONMENT'] ) ) {
 
58
  if (
59
  ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) &&
60
  empty( $_POST['ewww_image_optimizer_cloud_key'] ) &&
61
  ( ! is_object( $exactdn ) || ! $exactdn->get_exactdn_domain() )
62
  ) {
63
+ add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_hosting_requires_api' );
64
+ add_action( 'admin_notices', 'ewww_image_optimizer_notice_hosting_requires_api' );
65
  }
66
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_NOEXEC' ) ) {
67
  define( 'EWWW_IMAGE_OPTIMIZER_NOEXEC', true );
68
  }
69
  ewwwio_debug_message( 'wp.com site, disabling tools' );
70
  ewww_image_optimizer_disable_tools();
71
+ // Check if this is an unsupported OS (not Linux or Mac OSX or FreeBSD or Windows or SunOS).
72
  } elseif ( 'Linux' != PHP_OS && 'Darwin' != PHP_OS && 'FreeBSD' != PHP_OS && 'WINNT' != PHP_OS && 'SunOS' != PHP_OS ) {
73
  // Call the function to display a notice.
74
  add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_os' );
123
  }
124
 
125
  /**
126
+ * Let the user know the plugin requires API/ExactDN to operate at their webhost.
127
  */
128
+ function ewww_image_optimizer_notice_hosting_requires_api() {
129
  if ( ! function_exists( 'is_plugin_active_for_network' ) && is_multisite() ) {
130
  // Need to include the plugin library for the is_plugin_active function.
131
  require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
135
  } else {
136
  $options_page = 'options-general.php';
137
  }
138
+ if ( defined( 'WPCOMSH_VERSION' ) ) {
139
+ $webhost = 'WordPress.com';
140
+ } elseif ( ! empty( $_ENV['PANTHEON_ENVIRONMENT'] ) ) {
141
+ $webhost = 'Pantheon';
142
+ } else {
143
+ return;
144
+ }
145
  $settings_url = admin_url( "$options_page?page=" . plugin_basename( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ) );
146
  echo "<div id='ewww-image-optimizer-cloud-key-required' class='error'><p><strong>" .
147
+ /* translators: %s: Name of a web host, like WordPress.com or Pantheon. */
148
+ sprintf( esc_html__( 'The EWWW Image Optimizer requires an API key or an ExactDN subscription to optimize images on %s sites.', 'ewww-image-optimizer-cloud' ), $webhost ) .
149
  "</strong> <a href='https://ewww.io/plans/'>" . esc_html__( 'Purchase a subscription.', 'ewww-image-optimizer-cloud' ) .
150
  "</a> <a href='$settings_url'>" . esc_html__( 'Then, activate it on the settings page.', 'ewww-image-optimizer-cloud' ) . '</a></p></div>';
151
  }