EWWW Image Optimizer - Version 6.3.0

Version Description

  • added: EIO_LAZY_FOLD override to configure number of images above-the-fold that will be skipped by Lazy Load
  • added: Easy IO URLs for custom (non-WP) srcset markup
  • added: Easy IO support for CSS background images with relative URLs
  • fixed: Easy IO scaling not working on full-size images without srcset/responsive markup
  • fixed: WebP and Lazy Load function skip images dynamically created by Brizy builder
  • fixed: Easy IO conflict on Elementor preview pages
  • fixed: EXACTDN_CONTENT_WIDTH not effective at overriding $content_width during image_downsize filter
Download this release

Release Info

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

Code changes from version 6.2.5 to 6.3.0

changelog.txt CHANGED
@@ -1,3 +1,12 @@
 
 
 
 
 
 
 
 
 
1
  = 6.2.5 =
2
  * added: Easy IO and Lazy Load support for AJAX responses from FacetWP
3
  * changed: Vimeo videos excluded from iframe lazy load
1
+ = 6.3.0 =
2
+ * added: EIO_LAZY_FOLD override to configure number of images above-the-fold that will be skipped by Lazy Load
3
+ * added: Easy IO URLs for custom (non-WP) srcset markup
4
+ * added: Easy IO support for CSS background images with relative URLs
5
+ * fixed: Easy IO scaling not working on full-size images without srcset/responsive markup
6
+ * fixed: WebP and Lazy Load function skip images dynamically created by Brizy builder
7
+ * fixed: Easy IO conflict on Elementor preview pages
8
+ * fixed: EXACTDN_CONTENT_WIDTH not effective at overriding $content_width during image_downsize filter
9
+
10
  = 6.2.5 =
11
  * added: Easy IO and Lazy Load support for AJAX responses from FacetWP
12
  * changed: Vimeo videos excluded from iframe lazy load
classes/class-eio-base.php CHANGED
@@ -379,7 +379,7 @@ if ( ! class_exists( 'EIO_Base' ) ) {
379
  * @return bool True for an AMP endpoint, false otherwise.
380
  */
381
  function is_amp() {
382
- if ( ! did_action( 'parse_query' ) ) {
383
  return false;
384
  }
385
  if ( function_exists( 'amp_is_request' ) && amp_is_request() ) {
@@ -446,6 +446,28 @@ if ( ! class_exists( 'EIO_Base' ) ) {
446
  return true;
447
  }
448
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
449
  /**
450
  * Check if file exists, and that it is local rather than using a protocol like http:// or phar://
451
  *
@@ -831,7 +853,7 @@ if ( ! class_exists( 'EIO_Base' ) ) {
831
  if ( $this->s3_active ) {
832
  $this->site_url = defined( 'EXACTDN_LOCAL_DOMAIN' ) && EXACTDN_LOCAL_DOMAIN ? EXACTDN_LOCAL_DOMAIN : $s3_scheme . '://' . $s3_domain;
833
  } else {
834
- // Normally, we use this one, as it will be shorter for sub-directory installs.
835
  $home_url = get_home_url();
836
  $site_url = get_site_url();
837
  $home_domain = $this->parse_url( $home_url, PHP_URL_HOST );
379
  * @return bool True for an AMP endpoint, false otherwise.
380
  */
381
  function is_amp() {
382
+ if ( ! did_action( 'wp' ) ) {
383
  return false;
384
  }
385
  if ( function_exists( 'amp_is_request' ) && amp_is_request() ) {
446
  return true;
447
  }
448
 
449
+ /**
450
+ * Checks if the image URL points to a lazy load placeholder.
451
+ *
452
+ * @param string $image The image URL (or an image element).
453
+ * @return bool True if it matches a known placeholder pattern, false otherwise.
454
+ */
455
+ function is_lazy_placeholder( $image ) {
456
+ $this->debug_message( '<b>' . __METHOD__ . '()</b>' );
457
+ if (
458
+ strpos( $image, 'base64,R0lGOD' ) ||
459
+ strpos( $image, 'lazy-load/images/1x1' ) ||
460
+ strpos( $image, '/assets/images/lazy' ) ||
461
+ strpos( $image, '/assets/images/dummy.png' ) ||
462
+ strpos( $image, '/assets/images/transparent.png' ) ||
463
+ strpos( $image, '/lazy/placeholder' )
464
+ ) {
465
+ $this->debug_message( 'lazy load placeholder' );
466
+ return true;
467
+ }
468
+ return false;
469
+ }
470
+
471
  /**
472
  * Check if file exists, and that it is local rather than using a protocol like http:// or phar://
473
  *
853
  if ( $this->s3_active ) {
854
  $this->site_url = defined( 'EXACTDN_LOCAL_DOMAIN' ) && EXACTDN_LOCAL_DOMAIN ? EXACTDN_LOCAL_DOMAIN : $s3_scheme . '://' . $s3_domain;
855
  } else {
856
+ // Normally, we use this one, as it will be shorter for sub-directory (not multi-site) installs.
857
  $home_url = get_home_url();
858
  $site_url = get_site_url();
859
  $home_domain = $this->parse_url( $home_url, PHP_URL_HOST );
classes/class-eio-js-webp.php CHANGED
@@ -190,6 +190,9 @@ class EIO_JS_Webp extends EIO_Page_Parser {
190
  if ( false !== strpos( $uri, 'tatsu=' ) ) {
191
  return false;
192
  }
 
 
 
193
  if ( ! empty( $_POST['action'] ) && 'tatsu_get_concepts' === sanitize_text_field( wp_unslash( $_POST['action'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
194
  return false;
195
  }
@@ -201,9 +204,6 @@ class EIO_JS_Webp extends EIO_Page_Parser {
201
  if ( ! isset( $wp_query ) || ! ( $wp_query instanceof WP_Query ) ) {
202
  return $should_process;
203
  }
204
- if ( ! did_action( 'parse_query' ) ) {
205
- return $should_process;
206
- }
207
  if ( $this->is_amp() ) {
208
  return false;
209
  }
@@ -948,16 +948,14 @@ class EIO_JS_Webp extends EIO_Page_Parser {
948
  * @return bool True if the file exists or matches a forced path, false otherwise.
949
  */
950
  function validate_image_url( $image ) {
951
- $this->debug_message( "webp validation for $image" );
952
- if (
953
- strpos( $image, 'base64,R0lGOD' ) ||
954
- strpos( $image, 'lazy-load/images/1x1' ) ||
955
- strpos( $image, '/assets/images/' ) ||
956
- strpos( $image, '/lazy/placeholder' )
957
- ) {
958
- $this->debug_message( 'lazy load placeholder' );
959
  return false;
960
  }
 
 
 
 
961
  $extension = '';
962
  $image_path = $this->parse_url( $image, PHP_URL_PATH );
963
  if ( ! is_null( $image_path ) && $image_path ) {
@@ -992,9 +990,7 @@ class EIO_JS_Webp extends EIO_Page_Parser {
992
  }
993
 
994
  /**
995
- * Generate a WebP url.
996
- *
997
- * Adds .webp to the end, or adds a webp parameter for ExactDN urls.
998
  *
999
  * @param string $url The image url.
1000
  * @return string The WebP version of the image url.
190
  if ( false !== strpos( $uri, 'tatsu=' ) ) {
191
  return false;
192
  }
193
+ if ( false !== strpos( $uri, 'tve=true' ) ) {
194
+ return false;
195
+ }
196
  if ( ! empty( $_POST['action'] ) && 'tatsu_get_concepts' === sanitize_text_field( wp_unslash( $_POST['action'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
197
  return false;
198
  }
204
  if ( ! isset( $wp_query ) || ! ( $wp_query instanceof WP_Query ) ) {
205
  return $should_process;
206
  }
 
 
 
207
  if ( $this->is_amp() ) {
208
  return false;
209
  }
948
  * @return bool True if the file exists or matches a forced path, false otherwise.
949
  */
950
  function validate_image_url( $image ) {
951
+ $this->debug_message( __METHOD__ . "() webp validation for $image" );
952
+ if ( $this->is_lazy_placeholder( $image ) ) {
 
 
 
 
 
 
953
  return false;
954
  }
955
+ // Cleanup the image from encoded HTML characters.
956
+ $image = str_replace( '&#038;', '&', $image );
957
+ $image = str_replace( '#038;', '&', $image );
958
+
959
  $extension = '';
960
  $image_path = $this->parse_url( $image, PHP_URL_PATH );
961
  if ( ! is_null( $image_path ) && $image_path ) {
990
  }
991
 
992
  /**
993
+ * Generate a WebP URL by appending .webp to the filename.
 
 
994
  *
995
  * @param string $url The image url.
996
  * @return string The WebP version of the image url.
classes/class-eio-lazy-load.php CHANGED
@@ -142,6 +142,8 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
142
  define( 'EIO_LL_AUTOSCALE', false );
143
  }
144
 
 
 
145
  // Filter early, so that others at the default priority take precendence.
146
  add_filter( 'eio_use_piip', array( $this, 'maybe_piip' ), 9 );
147
  add_filter( 'eio_use_siip', array( $this, 'maybe_siip' ), 9 );
@@ -228,6 +230,9 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
228
  if ( false !== strpos( $uri, 'tatsu=' ) ) {
229
  return false;
230
  }
 
 
 
231
  if ( ! empty( $_POST['action'] ) && 'tatsu_get_concepts' === sanitize_text_field( wp_unslash( $_POST['action'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
232
  return false;
233
  }
@@ -319,8 +324,9 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
319
  }
320
  }
321
 
322
- $above_the_fold = apply_filters( 'eio_lazy_fold', 0 );
323
  $images_processed = 0;
 
324
 
325
  // Clean the buffer of incompatible sections.
326
  $search_buffer = preg_replace( '/<div id="footer_photostream".*?\/div>/s', '', $buffer );
@@ -329,10 +335,6 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
329
  $images = $this->get_images_from_html( $search_buffer, false );
330
  if ( ! empty( $images[0] ) && $this->is_iterable( $images[0] ) ) {
331
  foreach ( $images[0] as $index => $image ) {
332
- $images_processed++;
333
- if ( $images_processed <= $above_the_fold ) {
334
- continue;
335
- }
336
  $file = $images['img_url'][ $index ];
337
  $this->debug_message( "parsing an image: $file" );
338
  if ( $this->validate_image_tag( $image ) ) {
@@ -343,14 +345,28 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
343
  $image = $this->parse_img_tag( $image, $file );
344
  $this->set_attribute( $ns_img, 'data-eio', 'l', true );
345
  $noscript = '<noscript>' . $ns_img . '</noscript>';
346
- $buffer = str_replace( $orig_img, $image . $noscript, $buffer );
 
 
 
 
 
 
 
347
  }
348
  } // End foreach().
349
  } // End if().
350
  $element_types = apply_filters( 'eio_allowed_background_image_elements', array( 'div', 'li', 'span', 'section', 'a' ) );
351
  foreach ( $element_types as $element_type ) {
352
  // Process background images on HTML elements.
353
- $buffer = $this->parse_background_images( $buffer, $element_type );
 
 
 
 
 
 
 
354
  }
355
  if ( in_array( 'picture', $this->user_element_exclusions, true ) ) {
356
  $pictures = '';
@@ -397,9 +413,14 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
397
  $picture = str_replace( $source, $lazy_source, $picture );
398
  }
399
  }
400
- if ( $picture !== $pictures[ $index ] ) {
 
401
  $this->debug_message( 'lazified sources for picture element' );
402
- $buffer = str_replace( $pictures[ $index ], $picture, $buffer );
 
 
 
 
403
  }
404
  }
405
  }
@@ -425,6 +446,24 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
425
  }
426
  }
427
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
428
  $this->debug_message( 'all done parsing page for lazy' );
429
  return $buffer;
430
  }
@@ -437,6 +476,7 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
437
  * @return string The modified tag.
438
  */
439
  function parse_img_tag( $image, $file = '' ) {
 
440
  global $exactdn;
441
  if ( ! $file ) {
442
  $file = $this->get_attribute( $image, 'src' );
@@ -470,27 +510,28 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
470
  $width_attr = false;
471
  $height_attr = false;
472
  }
 
 
 
473
  $placeholder_src = $this->placeholder_src;
474
 
475
  $insert_dimensions = false;
 
476
  if ( apply_filters( 'eio_add_missing_width_height_attrs', $this->get_option( $this->prefix . 'add_missing_dims' ) ) && ( empty( $width_attr ) || empty( $height_attr ) ) ) {
477
  $this->debug_message( 'missing width attr or height attr' );
478
- list( $new_width_attr, $new_height_attr ) = $this->get_image_dimensions_by_url( $file );
479
- if ( $new_width_attr && is_numeric( $new_width_attr ) && $new_height_attr && is_numeric( $new_height_attr ) ) {
480
- $this->debug_message( "found $width_attr and $height_attr to insert (maybe)" );
481
- if ( $width_attr && is_numeric( $width_attr ) && $width_attr < $new_width_attr ) { // Then $height_attr is empty...
482
- $height_attr = round( ( $new_height_attr / $new_width_attr ) * $width_attr );
483
- $this->debug_message( "width was set to $width_attr, height was empty, but now $height_attr" );
484
- } elseif ( $height_attr && is_numeric( $height_attr ) && $height_attr < $new_height_attr ) { // Or $width_attr is empty...
485
- $width_attr = round( ( $new_width_attr / $new_height_attr ) * $height_attr );
486
- $this->debug_message( "height was set to $height_attr, width was empty, but now $width_attr" );
487
  } else {
488
- $width_attr = $new_width_attr;
489
- $height_attr = $new_height_attr;
490
- $this->debug_message( 'both width and height were empty, filling for sure' );
491
  }
492
- $physical_width = $new_width_attr;
493
- $physical_height = $new_height_attr;
494
  $insert_dimensions = true;
495
  }
496
  }
@@ -511,16 +552,12 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
511
  $placeholder_types[] = 'piip';
512
  }
513
 
514
- list( $filename_width, $filename_height ) = $this->get_dimensions_from_filename( $file, $this->parsing_exactdn );
515
- if ( $filename_width && is_numeric( $filename_width ) && $filename_height && is_numeric( $filename_height ) ) {
516
- $physical_width = $filename_width;
517
- $physical_height = $filename_height;
518
- } elseif (
519
- ( ! $physical_width || ! $physical_height ) &&
520
  $width_attr && is_numeric( $width_attr ) && $height_attr && is_numeric( $height_attr )
521
  ) {
522
- $physical_width = $width_attr;
523
- $physical_height = $height_attr;
524
  }
525
  foreach ( $placeholder_types as $placeholder_type ) {
526
  switch ( $placeholder_type ) {
@@ -550,14 +587,8 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
550
  case 'epip':
551
  $this->debug_message( 'using epip, maybe' );
552
  if ( false === strpos( $file, 'nggid' ) && ! preg_match( '#\.svg(\?|$)#', $file ) && strpos( $file, $this->exactdn_domain ) ) {
553
- if ( false === $filename_width || false === $filename_height ) {
554
- $filename_width = $width_attr;
555
- $filename_height = $height_attr;
556
- }
557
-
558
- if ( $filename_width && $filename_height && $this->allow_piip ) {
559
- $placeholder_src = $this->create_piip( $filename_width, $filename_height );
560
- /* $placeholder_src = $exactdn->generate_url( $this->content_url . 'lazy/placeholder-' . $filename_width . 'x' . $filename_height . '.png' ); */
561
  $use_native_lazy = true;
562
  break 2;
563
  } else {
@@ -570,17 +601,17 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
570
  case 'piip':
571
  $this->debug_message( 'trying piip' );
572
 
573
- if ( false === $filename_width || false === $filename_height ) {
574
- $filename_width = $width_attr;
575
- $filename_height = $height_attr;
576
  }
577
 
578
  // Falsify them if empty.
579
- $filename_width = (int) $filename_width ? (int) $filename_width : false;
580
- $filename_height = (int) $filename_height ? (int) $filename_height : false;
581
- if ( $filename_width && $filename_height ) {
582
- $this->debug_message( "creating piip of $filename_width x $filename_height" );
583
- $png_placeholder_src = $this->create_piip( $filename_width, $filename_height );
584
  if ( $png_placeholder_src ) {
585
  $placeholder_src = $png_placeholder_src;
586
  $use_native_lazy = true;
@@ -649,14 +680,15 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
649
  /**
650
  * Parse elements of a given type for inline CSS background images.
651
  *
652
- * @param string $buffer The HTML content to parse.
653
  * @param string $tag_type The type of HTML tag to look for.
654
- * @return string The modified content with LL markup.
 
655
  */
656
- function parse_background_images( $buffer, $tag_type ) {
657
  $this->debug_message( '<b>' . __METHOD__ . '()</b>' );
 
658
  if ( in_array( $tag_type, $this->user_element_exclusions, true ) ) {
659
- return $buffer;
660
  }
661
  $elements = $this->get_elements_from_html( preg_replace( '/<(noscript|script).*?\/\1>/s', '', $buffer ), $tag_type );
662
  if ( $this->is_iterable( $elements ) ) {
@@ -691,13 +723,18 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
691
  $element = str_replace( $style, $new_style, $element );
692
  }
693
  }
694
- if ( $element !== $elements[ $index ] ) {
 
695
  $this->debug_message( "$tag_type modified, replacing in html source" );
696
- $buffer = str_replace( $elements[ $index ], $element, $buffer );
 
 
 
 
697
  }
698
  }
699
  }
700
- return $buffer;
701
  }
702
 
703
  /**
@@ -814,12 +851,7 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
814
  */
815
  function validate_image_tag( $image ) {
816
  $this->debug_message( '<b>' . __METHOD__ . '()</b>' );
817
- if (
818
- strpos( $image, 'base64,R0lGOD' ) ||
819
- strpos( $image, 'lazy-load/images/1x1' ) ||
820
- strpos( $image, '/assets/images/' )
821
- ) {
822
- $this->debug_message( 'lazy load placeholder detected' );
823
  return false;
824
  }
825
 
@@ -972,6 +1004,10 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
972
  return $this->placeholder_src;
973
  }
974
 
 
 
 
 
975
  $piip_path = $this->piip_folder . 'placeholder-' . $width . 'x' . $height . '.png';
976
  // Keep this in case folks really want external Easy IO CDN placeholders.
977
  if ( defined( 'EIO_USE_EXTERNAL_PLACEHOLDERS' ) && EIO_USE_EXTERNAL_PLACEHOLDERS && $this->parsing_exactdn ) {
@@ -1029,6 +1065,23 @@ if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
1029
  }
1030
  return $this->placeholder_src;
1031
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1032
  /**
1033
  * Allow lazy loading of images for some admin-ajax requests.
1034
  *
142
  define( 'EIO_LL_AUTOSCALE', false );
143
  }
144
 
145
+ // Override for number of images to consider "above the fold".
146
+ add_filter( 'eio_lazy_fold', array( $this, 'override_lazy_fold' ), 9 );
147
  // Filter early, so that others at the default priority take precendence.
148
  add_filter( 'eio_use_piip', array( $this, 'maybe_piip' ), 9 );
149
  add_filter( 'eio_use_siip', array( $this, 'maybe_siip' ), 9 );
230
  if ( false !== strpos( $uri, 'tatsu=' ) ) {
231
  return false;
232
  }
233
+ if ( false !== strpos( $uri, 'tve=true' ) ) {
234
+ return false;
235
+ }
236
  if ( ! empty( $_POST['action'] ) && 'tatsu_get_concepts' === sanitize_text_field( wp_unslash( $_POST['action'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
237
  return false;
238
  }
324
  }
325
  }
326
 
327
+ $above_the_fold = apply_filters( 'eio_lazy_fold', 1 );
328
  $images_processed = 0;
329
+ $replacements = array();
330
 
331
  // Clean the buffer of incompatible sections.
332
  $search_buffer = preg_replace( '/<div id="footer_photostream".*?\/div>/s', '', $buffer );
335
  $images = $this->get_images_from_html( $search_buffer, false );
336
  if ( ! empty( $images[0] ) && $this->is_iterable( $images[0] ) ) {
337
  foreach ( $images[0] as $index => $image ) {
 
 
 
 
338
  $file = $images['img_url'][ $index ];
339
  $this->debug_message( "parsing an image: $file" );
340
  if ( $this->validate_image_tag( $image ) ) {
345
  $image = $this->parse_img_tag( $image, $file );
346
  $this->set_attribute( $ns_img, 'data-eio', 'l', true );
347
  $noscript = '<noscript>' . $ns_img . '</noscript>';
348
+ $position = strpos( $buffer, $orig_img );
349
+ if ( $position && $orig_img !== $image ) {
350
+ $replacements[ $position ] = array(
351
+ 'orig' => $orig_img,
352
+ 'lazy' => $image . $noscript,
353
+ );
354
+ }
355
+ /* $buffer = str_replace( $orig_img, $image . $noscript, $buffer ); */
356
  }
357
  } // End foreach().
358
  } // End if().
359
  $element_types = apply_filters( 'eio_allowed_background_image_elements', array( 'div', 'li', 'span', 'section', 'a' ) );
360
  foreach ( $element_types as $element_type ) {
361
  // Process background images on HTML elements.
362
+ $css_replacements = $this->parse_background_images( $element_type, $buffer );
363
+ if ( $this->is_iterable( $css_replacements ) ) {
364
+ foreach ( $css_replacements as $position => $css_replacement ) {
365
+ if ( $position ) {
366
+ $replacements[ $position ] = $css_replacement;
367
+ }
368
+ }
369
+ }
370
  }
371
  if ( in_array( 'picture', $this->user_element_exclusions, true ) ) {
372
  $pictures = '';
413
  $picture = str_replace( $source, $lazy_source, $picture );
414
  }
415
  }
416
+ $position = strpos( $buffer, $pictures[ $index ] );
417
+ if ( $position && $picture !== $pictures[ $index ] ) {
418
  $this->debug_message( 'lazified sources for picture element' );
419
+ $replacements[ $position ] = array(
420
+ 'orig' => $pictures[ $index ],
421
+ 'lazy' => $picture,
422
+ );
423
+ /* $buffer = str_replace( $pictures[ $index ], $picture, $buffer ); */
424
  }
425
  }
426
  }
446
  }
447
  }
448
  }
449
+ if ( $this->is_iterable( $replacements ) ) {
450
+ ksort( $replacements );
451
+ foreach ( $replacements as $position => $replacement ) {
452
+ $this->debug_message( "possible replacement at $position" );
453
+ $images_processed++;
454
+ if ( $images_processed <= $above_the_fold ) {
455
+ continue;
456
+ }
457
+ if ( empty( $replacement['orig'] ) || empty( $replacement['lazy'] ) ) {
458
+ continue;
459
+ }
460
+ if ( $replacement['orig'] === $replacement['lazy'] ) {
461
+ continue;
462
+ }
463
+ $this->debug_message( "replacing {$replacement['orig']} with {$replacement['lazy']}" );
464
+ $buffer = str_replace( $replacement['orig'], $replacement['lazy'], $buffer );
465
+ }
466
+ }
467
  $this->debug_message( 'all done parsing page for lazy' );
468
  return $buffer;
469
  }
476
  * @return string The modified tag.
477
  */
478
  function parse_img_tag( $image, $file = '' ) {
479
+ $this->debug_message( '<b>' . __METHOD__ . '()</b>' );
480
  global $exactdn;
481
  if ( ! $file ) {
482
  $file = $this->get_attribute( $image, 'src' );
510
  $width_attr = false;
511
  $height_attr = false;
512
  }
513
+ list( $physical_width, $physical_height ) = $this->get_image_dimensions_by_url( $file );
514
+
515
+ // Initialize the placeholder for this image.
516
  $placeholder_src = $this->placeholder_src;
517
 
518
  $insert_dimensions = false;
519
+ $this->debug_message( "width attr: $width_attr and height attr: $height_attr" );
520
  if ( apply_filters( 'eio_add_missing_width_height_attrs', $this->get_option( $this->prefix . 'add_missing_dims' ) ) && ( empty( $width_attr ) || empty( $height_attr ) ) ) {
521
  $this->debug_message( 'missing width attr or height attr' );
522
+ if ( $physical_width && is_numeric( $physical_width ) && $physical_height && is_numeric( $physical_height ) ) {
523
+ $this->debug_message( "found $physical_width and/or $physical_height to insert (maybe)" );
524
+ if ( $width_attr && is_numeric( $width_attr ) && $width_attr < $physical_width ) { // Then $height_attr is empty...
525
+ $height_attr = round( ( $physical_height / $physical_width ) * $width_attr );
526
+ $this->debug_message( "width was already $width_attr, height was empty, but now $height_attr" );
527
+ } elseif ( $height_attr && is_numeric( $height_attr ) && $height_attr < $physical_height ) { // Or $width_attr is empty...
528
+ $width_attr = round( ( $physical_width / $physical_height ) * $height_attr );
529
+ $this->debug_message( "height was already $height_attr, width was empty, but now $width_attr" );
 
530
  } else {
531
+ $width_attr = $physical_width;
532
+ $height_attr = $physical_height;
533
+ $this->debug_message( 'both width and height were empty' );
534
  }
 
 
535
  $insert_dimensions = true;
536
  }
537
  }
552
  $placeholder_types[] = 'piip';
553
  }
554
 
555
+ if ( // This isn't super helpful. It makes PIIPs that don't help with auto-scaling.
556
+ false && ( ! $physical_width || ! $physical_height ) &&
 
 
 
 
557
  $width_attr && is_numeric( $width_attr ) && $height_attr && is_numeric( $height_attr )
558
  ) {
559
+ $physical_width = $width_attr;
560
+ $physical_height = $height_attr;
561
  }
562
  foreach ( $placeholder_types as $placeholder_type ) {
563
  switch ( $placeholder_type ) {
587
  case 'epip':
588
  $this->debug_message( 'using epip, maybe' );
589
  if ( false === strpos( $file, 'nggid' ) && ! preg_match( '#\.svg(\?|$)#', $file ) && strpos( $file, $this->exactdn_domain ) ) {
590
+ if ( $physical_width && $physical_height && $this->allow_piip ) {
591
+ $placeholder_src = $this->create_piip( $physical_width, $physical_height );
 
 
 
 
 
 
592
  $use_native_lazy = true;
593
  break 2;
594
  } else {
601
  case 'piip':
602
  $this->debug_message( 'trying piip' );
603
 
604
+ if ( false === $physical_width || false === $physical_height ) {
605
+ $physical_width = $width_attr;
606
+ $physical_height = $height_attr;
607
  }
608
 
609
  // Falsify them if empty.
610
+ $physical_width = (int) $physical_width ? (int) $physical_width : false;
611
+ $physical_height = (int) $physical_height ? (int) $physical_height : false;
612
+ if ( $physical_width && $physical_height ) {
613
+ $this->debug_message( "creating piip of $physical_width x $physical_height" );
614
+ $png_placeholder_src = $this->create_piip( $physical_width, $physical_height );
615
  if ( $png_placeholder_src ) {
616
  $placeholder_src = $png_placeholder_src;
617
  $use_native_lazy = true;
680
  /**
681
  * Parse elements of a given type for inline CSS background images.
682
  *
 
683
  * @param string $tag_type The type of HTML tag to look for.
684
+ * @param string $buffer The HTML content to parse (and possibly modify).
685
+ * @return array A list of replacements to make in $buffer.
686
  */
687
+ function parse_background_images( $tag_type, &$buffer ) {
688
  $this->debug_message( '<b>' . __METHOD__ . '()</b>' );
689
+ $replacements = array();
690
  if ( in_array( $tag_type, $this->user_element_exclusions, true ) ) {
691
+ return $replacements;
692
  }
693
  $elements = $this->get_elements_from_html( preg_replace( '/<(noscript|script).*?\/\1>/s', '', $buffer ), $tag_type );
694
  if ( $this->is_iterable( $elements ) ) {
723
  $element = str_replace( $style, $new_style, $element );
724
  }
725
  }
726
+ $position = strpos( $buffer, $elements[ $index ] );
727
+ if ( $position && $element !== $elements[ $index ] ) {
728
  $this->debug_message( "$tag_type modified, replacing in html source" );
729
+ $replacements[ $position ] = array(
730
+ 'orig' => $elements[ $index ],
731
+ 'lazy' => $element,
732
+ );
733
+ /* $buffer = str_replace( $elements[ $index ], $element, $buffer ); */
734
  }
735
  }
736
  }
737
+ return $replacements;
738
  }
739
 
740
  /**
851
  */
852
  function validate_image_tag( $image ) {
853
  $this->debug_message( '<b>' . __METHOD__ . '()</b>' );
854
+ if ( $this->is_lazy_placeholder( $image ) ) {
 
 
 
 
 
855
  return false;
856
  }
857
 
1004
  return $this->placeholder_src;
1005
  }
1006
 
1007
+ if ( empty( $width ) || empty( $height ) ) {
1008
+ return $this->placeholder_src;
1009
+ }
1010
+
1011
  $piip_path = $this->piip_folder . 'placeholder-' . $width . 'x' . $height . '.png';
1012
  // Keep this in case folks really want external Easy IO CDN placeholders.
1013
  if ( defined( 'EIO_USE_EXTERNAL_PLACEHOLDERS' ) && EIO_USE_EXTERNAL_PLACEHOLDERS && $this->parsing_exactdn ) {
1065
  }
1066
  return $this->placeholder_src;
1067
  }
1068
+
1069
+ /**
1070
+ * Allow the user to override the number of images to consider "above the fold".
1071
+ *
1072
+ * Any images that are encountered before the above the fold threshold is reached
1073
+ * will be skipped by the lazy loader. Only applies to img elements, not CSS backgrounds.
1074
+ *
1075
+ * @param int $images The number of images that are above the fold.
1076
+ * @return int The (potentially overriden) number of images.
1077
+ */
1078
+ function override_lazy_fold( $images ) {
1079
+ if ( defined( 'EIO_LAZY_FOLD' ) ) {
1080
+ return (int) constant( 'EIO_LAZY_FOLD' );
1081
+ }
1082
+ return $images;
1083
+ }
1084
+
1085
  /**
1086
  * Allow lazy loading of images for some admin-ajax requests.
1087
  *
classes/class-eio-picture-webp.php CHANGED
@@ -150,6 +150,9 @@ class EIO_Picture_Webp extends EIO_Page_Parser {
150
  if ( false !== strpos( $uri, 'tatsu=' ) ) {
151
  return false;
152
  }
 
 
 
153
  if ( ! empty( $_POST['action'] ) && 'tatsu_get_concepts' === sanitize_text_field( wp_unslash( $_POST['action'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
154
  return false;
155
  }
@@ -161,9 +164,6 @@ class EIO_Picture_Webp extends EIO_Page_Parser {
161
  if ( ! isset( $wp_query ) || ! ( $wp_query instanceof WP_Query ) ) {
162
  return $should_process;
163
  }
164
- if ( ! did_action( 'parse_query' ) ) {
165
- return $should_process;
166
- }
167
  if ( $this->is_amp() ) {
168
  return false;
169
  }
@@ -460,21 +460,20 @@ class EIO_Picture_Webp extends EIO_Page_Parser {
460
  * @return bool True if the file exists or matches a forced path, false otherwise.
461
  */
462
  function validate_image_url( $image ) {
463
- ewwwio_debug_message( __METHOD__ . "() webp validation for $image" );
464
- if (
465
- strpos( $image, 'base64,R0lGOD' ) ||
466
- strpos( $image, 'lazy-load/images/1x1' ) ||
467
- strpos( $image, '/assets/images/' )
468
- ) {
469
- ewwwio_debug_message( 'lazy load placeholder' );
470
  return false;
471
  }
 
 
 
 
472
  $extension = '';
473
  $image_path = $this->parse_url( $image, PHP_URL_PATH );
474
  if ( ! is_null( $image_path ) && $image_path ) {
475
  $extension = strtolower( pathinfo( $image_path, PATHINFO_EXTENSION ) );
476
  }
477
- if ( $extension && 'gif' === $extension && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_force_gif2webp' ) ) {
478
  return false;
479
  }
480
  if ( $extension && 'svg' === $extension ) {
@@ -503,9 +502,7 @@ class EIO_Picture_Webp extends EIO_Page_Parser {
503
  }
504
 
505
  /**
506
- * Generate a WebP url.
507
- *
508
- * Adds .webp to the end.
509
  *
510
  * @param string $url The image url.
511
  * @return string The WebP version of the image url.
150
  if ( false !== strpos( $uri, 'tatsu=' ) ) {
151
  return false;
152
  }
153
+ if ( false !== strpos( $uri, 'tve=true' ) ) {
154
+ return false;
155
+ }
156
  if ( ! empty( $_POST['action'] ) && 'tatsu_get_concepts' === sanitize_text_field( wp_unslash( $_POST['action'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
157
  return false;
158
  }
164
  if ( ! isset( $wp_query ) || ! ( $wp_query instanceof WP_Query ) ) {
165
  return $should_process;
166
  }
 
 
 
167
  if ( $this->is_amp() ) {
168
  return false;
169
  }
460
  * @return bool True if the file exists or matches a forced path, false otherwise.
461
  */
462
  function validate_image_url( $image ) {
463
+ $this->debug_message( __METHOD__ . "() webp validation for $image" );
464
+ if ( $this->is_lazy_placeholder( $image ) ) {
 
 
 
 
 
465
  return false;
466
  }
467
+ // Cleanup the image from encoded HTML characters.
468
+ $image = str_replace( '&#038;', '&', $image );
469
+ $image = str_replace( '#038;', '&', $image );
470
+
471
  $extension = '';
472
  $image_path = $this->parse_url( $image, PHP_URL_PATH );
473
  if ( ! is_null( $image_path ) && $image_path ) {
474
  $extension = strtolower( pathinfo( $image_path, PATHINFO_EXTENSION ) );
475
  }
476
+ if ( $extension && 'gif' === $extension && ! $this->get_option( 'ewww_image_optimizer_force_gif2webp' ) ) {
477
  return false;
478
  }
479
  if ( $extension && 'svg' === $extension ) {
502
  }
503
 
504
  /**
505
+ * Generate a WebP URL by appending .webp to the filename.
 
 
506
  *
507
  * @param string $url The image url.
508
  * @return string The WebP version of the image url.
classes/class-ewwwio-media-background-process.php CHANGED
@@ -677,3 +677,35 @@ class EWWWIO_Test_Async_Handler extends WP_Async_Request {
677
  }
678
  global $ewwwio_test_async;
679
  $ewwwio_test_async = new EWWWIO_Test_Async_Handler();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
677
  }
678
  global $ewwwio_test_async;
679
  $ewwwio_test_async = new EWWWIO_Test_Async_Handler();
680
+
681
+ /**
682
+ * Handles a simulated async request used to test async requests for the debugger.
683
+ *
684
+ * @see WP_Async_Request
685
+ */
686
+ class EWWWIO_Test_Optimize_Handler extends WP_Async_Request {
687
+
688
+ /**
689
+ * The action name used to trigger this class extension.
690
+ *
691
+ * @access protected
692
+ * @var string $action
693
+ */
694
+ protected $action = 'ewwwio_test_optimize';
695
+
696
+ /**
697
+ * Handles the test async request.
698
+ *
699
+ * Called via a POST request to verify that nothing is blocking or altering requests from the server to itself.
700
+ */
701
+ protected function handle() {
702
+ session_write_close();
703
+ ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
704
+ check_ajax_referer( $this->identifier, 'nonce' );
705
+ if ( empty( $_POST['ewwwio_test_verify'] ) ) {
706
+ return;
707
+ }
708
+ }
709
+ }
710
+ global $ewwwio_test_optimize;
711
+ $ewwwio_test_optimize = new EWWWIO_Test_Optimize_Handler();
classes/class-exactdn.php CHANGED
@@ -445,13 +445,6 @@ if ( ! class_exists( 'ExactDN' ) ) {
445
  $this->set_option( 'exactdn_all_the_things', true );
446
  delete_option( 'exactdn_never_been_active' );
447
  }
448
- if ( 'external' === get_option( 'elementor_css_print_method' ) ) {
449
- update_option( 'elementor_css_print_method', 'internal' );
450
- }
451
- if ( function_exists( 'et_get_option' ) && function_exists( 'et_update_option' ) && 'on' === et_get_option( 'et_pb_static_css_file', 'on' ) ) {
452
- et_update_option( 'et_pb_static_css_file', 'off' );
453
- et_update_option( 'et_pb_css_in_footer', 'off' );
454
- }
455
  if ( function_exists( 'envira_flush_all_cache' ) ) {
456
  envira_flush_all_cache();
457
  }
@@ -920,6 +913,7 @@ if ( ! class_exists( 'ExactDN' ) ) {
920
  $this->filtering_the_content = true;
921
  $this->debug_message( 'filtering the content' );
922
  $content_width = $this->get_content_width();
 
923
  }
924
  $resize_existing = defined( 'EXACTDN_RESIZE_EXISTING' ) && EXACTDN_RESIZE_EXISTING;
925
 
@@ -1041,7 +1035,7 @@ if ( ! class_exists( 'ExactDN' ) ) {
1041
  }
1042
 
1043
  $is_relative = false;
1044
- // Check for relative urls that start with a slash. Unlikely that we'll attempt relative urls beyond that.
1045
  if (
1046
  '/' === substr( $src, 0, 1 ) &&
1047
  '/' !== substr( $src, 1, 1 ) &&
@@ -1300,14 +1294,21 @@ if ( ! class_exists( 'ExactDN' ) ) {
1300
  );
1301
  }
1302
 
 
1303
  // Insert new image src into the srcset as well, if we have a width.
1304
  if ( false !== $width && false === strpos( $width, '%' ) && $width ) {
1305
- $this->debug_message( 'checking to see if srcset width already exists' );
1306
- $srcset_url = $exactdn_url . ' ' . (int) $width . 'w, ';
1307
- $new_srcset_attr = $this->get_attribute( $new_tag, $this->srcset_attr );
1308
- if ( $new_srcset_attr && false === strpos( $new_srcset_attr, ' ' . (int) $width . 'w' ) && ! preg_match( '/\s(1|2|3)x/', $new_srcset_attr ) ) {
 
 
1309
  $this->debug_message( 'src not in srcset, adding' );
1310
- $this->set_attribute( $new_tag, $this->srcset_attr, $srcset_url . $new_srcset_attr, true );
 
 
 
 
1311
  }
1312
  }
1313
 
@@ -1351,9 +1352,39 @@ if ( ! class_exists( 'ExactDN' ) ) {
1351
  $content = str_replace( $tag, $new_tag, $content );
1352
  }
1353
  } elseif ( ! $lazy && $this->validate_image_url( $src, true ) ) {
1354
- $this->debug_message( "found a potential exactdn src url to insert into srcset: $src" );
1355
- // Find the width attribute.
1356
- $width = $this->get_attribute( $images['img_tag'][ $index ], 'width' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1357
  if ( $width ) {
1358
  $this->debug_message( 'found the width' );
1359
  // Insert new image src into the srcset as well, if we have a width.
@@ -1363,20 +1394,27 @@ if ( ! class_exists( 'ExactDN' ) ) {
1363
  false !== strpos( $src, $width ) &&
1364
  false !== strpos( $src, $this->exactdn_domain )
1365
  ) {
1366
- $new_tag = $tag;
1367
  $exactdn_url = $src;
1368
 
1369
- $this->debug_message( 'checking to see if srcset width already exists' );
1370
- $srcset_url = $exactdn_url . ' ' . (int) $width . 'w, ';
1371
- $new_srcset_attr = $this->get_attribute( $new_tag, $this->srcset_attr );
1372
- if ( $new_srcset_attr && false === strpos( $new_srcset_attr, ' ' . (int) $width . 'w' ) && ! preg_match( '/\s(1|2|3)x/', $new_srcset_attr ) ) {
1373
- $this->debug_message( 'src not in srcset, adding' );
1374
- $this->set_attribute( $new_tag, $this->srcset_attr, $srcset_url . $new_srcset_attr, true );
1375
- // Replace original tag with modified version.
1376
- $content = str_replace( $tag, $new_tag, $content );
1377
- }
 
 
 
 
1378
  }
1379
  }
 
 
 
 
1380
  } elseif ( $lazy && ! empty( $placeholder_src ) && $this->validate_image_url( $placeholder_src ) ) {
1381
  $this->debug_message( "parsing $placeholder_src for $src" );
1382
  $new_tag = $tag;
@@ -1396,8 +1434,8 @@ if ( ! class_exists( 'ExactDN' ) ) {
1396
  if ( ! empty( $exactdn_url ) ) {
1397
  $src = $exactdn_url;
1398
  }
1399
- // This is just completely disabled now, no reason to do this with the lazy loader auto-scaling, and I don't know when it ever kicks in anymore...
1400
- if ( false && ! is_feed() && $srcset_fill && ( ! defined( 'EXACTDN_PREVENT_SRCSET_FILL' ) || ! EXACTDN_PREVENT_SRCSET_FILL ) && false !== strpos( $src, $this->exactdn_domain ) ) {
1401
  if ( ! $this->get_attribute( $images['img_tag'][ $index ], $this->srcset_attr ) && ! $this->get_attribute( $images['img_tag'][ $index ], 'sizes' ) ) {
1402
  $this->debug_message( "srcset filling with $src" );
1403
  $zoom = false;
@@ -1520,10 +1558,13 @@ if ( ! class_exists( 'ExactDN' ) ) {
1520
  continue;
1521
  }
1522
  $full_link_url = $link_url;
1523
- // Check for relative urls that start with a slash.
1524
  if (
1525
  '/' === substr( $link_url, 0, 1 ) &&
1526
- '/' !== substr( $link_url, 1, 1 )
 
 
 
1527
  ) {
1528
  $full_link_url = '//' . $this->upload_domain . $link_url;
1529
  }
@@ -1566,7 +1607,7 @@ if ( ! class_exists( 'ExactDN' ) ) {
1566
  $srcset = $this->get_attribute( $source, 'srcset' );
1567
  if ( $srcset ) {
1568
  $new_srcset = $this->srcset_replace( $srcset );
1569
- if ( $new_srcset ) {
1570
  $new_source = str_replace( $srcset, $new_srcset, $source );
1571
  $picture = str_replace( $source, $new_source, $picture );
1572
  }
@@ -1582,44 +1623,6 @@ if ( ! class_exists( 'ExactDN' ) ) {
1582
  return $content;
1583
  }
1584
 
1585
- /**
1586
- * Replaces images within a srcset attribute with their ExactDN derivatives.
1587
- *
1588
- * @param string $srcset A valid srcset attribute from an img element.
1589
- * @return bool|string False if no changes were made, or the new srcset if any ExactDN images replaced the originals.
1590
- */
1591
- function srcset_replace( $srcset ) {
1592
- $this->debug_message( '<b>' . __METHOD__ . '()</b>' );
1593
- $srcset_urls = explode( ' ', $srcset );
1594
- $modified = false;
1595
- if ( $this->is_iterable( $srcset_urls ) && count( $srcset_urls ) > 1 ) {
1596
- $this->debug_message( 'parsing srcset urls' );
1597
- foreach ( $srcset_urls as $srcurl ) {
1598
- if ( is_numeric( substr( $srcurl, 0, 1 ) ) ) {
1599
- continue;
1600
- }
1601
- $trailing = ' ';
1602
- if ( ',' === substr( $srcurl, -1 ) ) {
1603
- $trailing = ',';
1604
- $srcurl = rtrim( $srcurl, ',' );
1605
- }
1606
- $this->debug_message( "looking for $srcurl from srcset" );
1607
- if ( $this->validate_image_url( $srcurl ) ) {
1608
- $srcset = str_replace( $srcurl . $trailing, $this->generate_url( $srcurl ) . $trailing, $srcset );
1609
- $this->debug_message( "replaced $srcurl in srcset" );
1610
- $modified = true;
1611
- }
1612
- }
1613
- } elseif ( $this->validate_image_url( $srcset ) ) {
1614
- return $this->generate_url( $srcset );
1615
- }
1616
- if ( $modified ) {
1617
- return $srcset;
1618
- } else {
1619
- return false;
1620
- }
1621
- }
1622
-
1623
  /**
1624
  * Parse page content looking for elements with CSS background-image properties.
1625
  *
@@ -1648,6 +1651,19 @@ if ( ! class_exists( 'ExactDN' ) ) {
1648
  }
1649
  $this->debug_message( "checking style attr for background-image: $style" );
1650
  $bg_image_url = $this->get_background_image_url( $style );
 
 
 
 
 
 
 
 
 
 
 
 
 
1651
  if ( $this->validate_image_url( $bg_image_url ) ) {
1652
  /** This filter is already documented in class-exactdn.php */
1653
  if ( apply_filters( 'exactdn_skip_image', false, $bg_image_url, $element ) ) {
@@ -1671,7 +1687,7 @@ if ( ! class_exists( 'ExactDN' ) ) {
1671
  }
1672
  $exactdn_bg_image_url = $this->generate_url( $bg_image_url, $args );
1673
  if ( $bg_image_url !== $exactdn_bg_image_url ) {
1674
- $new_style = str_replace( $bg_image_url, $exactdn_bg_image_url, $style );
1675
  $element = str_replace( $style, $new_style, $element );
1676
  }
1677
  }
@@ -2002,8 +2018,16 @@ if ( ! class_exists( 'ExactDN' ) ) {
2002
  $image_args['width'] = $image_meta['width'];
2003
  $image_args['height'] = $image_meta['height'];
2004
 
 
 
 
 
 
2005
  // NOTE: it will constrain an image to $content_width which is expected behavior in core, so far as I can see.
2006
  list( $image_args['width'], $image_args['height'] ) = image_constrain_size_for_editor( $image_args['width'], $image_args['height'], $size, 'display' );
 
 
 
2007
 
2008
  $has_size_meta = true;
2009
  $this->debug_message( 'image args constrained: ' . $this->implode( ',', $image_args ) );
@@ -2119,8 +2143,16 @@ if ( ! class_exists( 'ExactDN' ) ) {
2119
  $has_size_meta = true;
2120
  }
2121
 
 
 
 
 
 
2122
  list( $width, $height ) = image_constrain_size_for_editor( $width, $height, $size );
2123
  $this->debug_message( "constrained to w$width by h$height" );
 
 
 
2124
 
2125
  // Expose arguments to a filter before passing to ExactDN.
2126
  $exactdn_args = array(
@@ -2163,6 +2195,49 @@ if ( ! class_exists( 'ExactDN' ) ) {
2163
  return $image;
2164
  }
2165
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2166
  /**
2167
  * Filters an array of image `srcset` values, replacing each URL with its ExactDN equivalent.
2168
  *
@@ -2200,6 +2275,7 @@ if ( ! class_exists( 'ExactDN' ) ) {
2200
  return $sources;
2201
  }
2202
 
 
2203
  $upload_dir = wp_get_upload_dir();
2204
  $resize_existing = defined( 'EXACTDN_RESIZE_EXISTING' ) && EXACTDN_RESIZE_EXISTING;
2205
  $w_descriptor = true;
@@ -2272,7 +2348,10 @@ if ( ! class_exists( 'ExactDN' ) ) {
2272
  * @param array|bool $multipliers Array of multipliers to use or false to bypass.
2273
  */
2274
  $multipliers = apply_filters( 'exactdn_srcset_multipliers', array( .2, .4, .6, .8, 1, 2, 3, 1920 ) );
2275
- $url = trailingslashit( $upload_dir['baseurl'] ) . $image_meta['file'];
 
 
 
2276
  if ( ! $w_descriptor ) {
2277
  $this->debug_message( 'using x descriptors instead of w' );
2278
  $multipliers = array_filter( $multipliers, 'is_int' );
@@ -2985,6 +3064,9 @@ if ( ! class_exists( 'ExactDN' ) ) {
2985
  if ( false !== strpos( $uri, 'ct_render_shortcode=' ) || false !== strpos( $uri, 'action=oxy_render' ) ) {
2986
  return true;
2987
  }
 
 
 
2988
  if ( false !== strpos( $uri, 'et_fb=' ) ) {
2989
  return true;
2990
  }
@@ -2997,6 +3079,9 @@ if ( ! class_exists( 'ExactDN' ) ) {
2997
  if ( false !== strpos( $uri, 'tatsu=' ) ) {
2998
  return true;
2999
  }
 
 
 
3000
  return $skip;
3001
  }
3002
 
@@ -3276,6 +3361,8 @@ if ( ! class_exists( 'ExactDN' ) ) {
3276
  if ( $this->exactdn_domain === $image_url_parts['host'] ) {
3277
  $this->debug_message( 'url already has exactdn domain' );
3278
  $exactdn_url = add_query_arg( $args, $image_url );
 
 
3279
  return $this->url_scheme( $exactdn_url, $scheme );
3280
  }
3281
 
@@ -3321,6 +3408,8 @@ if ( ! class_exists( 'ExactDN' ) ) {
3321
  if ( $args ) {
3322
  if ( is_array( $args ) ) {
3323
  $exactdn_url = add_query_arg( $args, $exactdn_url );
 
 
3324
  } else {
3325
  // You can pass a query string for complicated requests, although this should have been converted to an array already.
3326
  $exactdn_url .= '?' . $args;
445
  $this->set_option( 'exactdn_all_the_things', true );
446
  delete_option( 'exactdn_never_been_active' );
447
  }
 
 
 
 
 
 
 
448
  if ( function_exists( 'envira_flush_all_cache' ) ) {
449
  envira_flush_all_cache();
450
  }
913
  $this->filtering_the_content = true;
914
  $this->debug_message( 'filtering the content' );
915
  $content_width = $this->get_content_width();
916
+ $this->debug_message( "configured content_width: $content_width" );
917
  }
918
  $resize_existing = defined( 'EXACTDN_RESIZE_EXISTING' ) && EXACTDN_RESIZE_EXISTING;
919
 
1035
  }
1036
 
1037
  $is_relative = false;
1038
+ // Check for relative URLs that start with a slash.
1039
  if (
1040
  '/' === substr( $src, 0, 1 ) &&
1041
  '/' !== substr( $src, 1, 1 ) &&
1294
  );
1295
  }
1296
 
1297
+ $srcset_url = false;
1298
  // Insert new image src into the srcset as well, if we have a width.
1299
  if ( false !== $width && false === strpos( $width, '%' ) && $width ) {
1300
+ $srcset_url = $exactdn_url . ' ' . (int) $width . 'w, ';
1301
+ }
1302
+ $srcset_attr = $this->get_attribute( $new_tag, $this->srcset_attr );
1303
+ if ( $srcset_attr ) {
1304
+ $new_srcset_attr = $srcset_attr;
1305
+ if ( $srcset_url && false === strpos( $srcset_attr, ' ' . (int) $width . 'w' ) && ! preg_match( '/\s(1|2|3)x/', $srcset_attr ) ) {
1306
  $this->debug_message( 'src not in srcset, adding' );
1307
+ $new_srcset_attr = $srcset_url . $new_srcset_attr;
1308
+ }
1309
+ $new_srcset_attr = $this->srcset_replace( $new_srcset_attr );
1310
+ if ( $new_srcset_attr && $new_srcset_attr !== $srcset_attr ) {
1311
+ $this->set_attribute( $new_tag, $this->srcset_attr, $new_srcset_attr, true );
1312
  }
1313
  }
1314
 
1352
  $content = str_replace( $tag, $new_tag, $content );
1353
  }
1354
  } elseif ( ! $lazy && $this->validate_image_url( $src, true ) ) {
1355
+ $this->debug_message( "found a potential exactdn src url to wrangle, and maybe insert into srcset: $src" );
1356
+
1357
+ $args = array();
1358
+ $new_tag = $tag;
1359
+ $width = $this->get_attribute( $images['img_tag'][ $index ], 'width' );
1360
+ $height = $this->get_attribute( $images['img_tag'][ $index ], 'height' );
1361
+ // Making sure the width/height are numeric.
1362
+ if ( false === strpos( $new_tag, 'srcset' ) && strpos( $src, '?' ) && (int) $width > 2 && (int) $height > 2 ) {
1363
+ $url_params = urldecode( $this->parse_url( $src, PHP_URL_QUERY ) );
1364
+ if ( $url_params && false !== strpos( $url_params, 'resize=' ) ) {
1365
+ $this->debug_message( 'existing resize param' );
1366
+ } elseif ( $url_params && false !== strpos( $url_params, 'fit=' ) ) {
1367
+ $this->debug_message( 'existing fit param' );
1368
+ } elseif ( $url_params && false === strpos( $url_params, 'w=' ) && false === strpos( $url_params, 'h=' ) && false === strpos( $url_params, 'crop=' ) ) {
1369
+ $this->debug_message( 'no size params, so add the width/height' );
1370
+ $args = array();
1371
+ $transform = 'fit';
1372
+ // Or optionally as crop/resize.
1373
+ if ( strpos( $new_tag, 'img-crop' ) ) {
1374
+ $transform = 'resize';
1375
+ }
1376
+ $args[ $transform ] = $width . ',' . $height;
1377
+ }
1378
+ }
1379
+ if ( $args ) {
1380
+ $args = apply_filters( 'exactdn_post_image_args', $args, compact( 'new_tag', 'src', 'src', 'width', 'height' ) );
1381
+ $new_src = $this->generate_url( $src, $args );
1382
+ if ( $new_src && $src !== $new_src ) {
1383
+ $new_tag = str_replace( $src, $new_src, $new_tag );
1384
+ }
1385
+ }
1386
+
1387
+ $srcset_url = false;
1388
  if ( $width ) {
1389
  $this->debug_message( 'found the width' );
1390
  // Insert new image src into the srcset as well, if we have a width.
1394
  false !== strpos( $src, $width ) &&
1395
  false !== strpos( $src, $this->exactdn_domain )
1396
  ) {
 
1397
  $exactdn_url = $src;
1398
 
1399
+ $srcset_url = $exactdn_url . ' ' . (int) $width . 'w, ';
1400
+ }
1401
+ }
1402
+ $srcset_attr = $this->get_attribute( $new_tag, $this->srcset_attr );
1403
+ if ( $srcset_attr ) {
1404
+ $new_srcset_attr = $srcset_attr;
1405
+ if ( $srcset_url && false === strpos( $srcset_attr, ' ' . (int) $width . 'w' ) && ! preg_match( '/\s(1|2|3)x/', $srcset_attr ) ) {
1406
+ $this->debug_message( 'src not in srcset, adding' );
1407
+ $new_srcset_attr = $srcset_url . $new_srcset_attr;
1408
+ }
1409
+ $new_srcset_attr = $this->srcset_replace( $new_srcset_attr );
1410
+ if ( $new_srcset_attr && $new_srcset_attr !== $srcset_attr ) {
1411
+ $this->set_attribute( $new_tag, $this->srcset_attr, $new_srcset_attr, true );
1412
  }
1413
  }
1414
+ if ( $new_tag && $new_tag !== $tag ) {
1415
+ // Replace original tag with modified version.
1416
+ $content = str_replace( $tag, $new_tag, $content );
1417
+ }
1418
  } elseif ( $lazy && ! empty( $placeholder_src ) && $this->validate_image_url( $placeholder_src ) ) {
1419
  $this->debug_message( "parsing $placeholder_src for $src" );
1420
  $new_tag = $tag;
1434
  if ( ! empty( $exactdn_url ) ) {
1435
  $src = $exactdn_url;
1436
  }
1437
+ // This is disabled by default, not much reason to do this with the lazy loader auto-scaling.
1438
+ if ( ! is_feed() && $srcset_fill && defined( 'EIO_SRCSET_FILL' ) && EIO_SRCSET_FILL && false !== strpos( $src, $this->exactdn_domain ) ) {
1439
  if ( ! $this->get_attribute( $images['img_tag'][ $index ], $this->srcset_attr ) && ! $this->get_attribute( $images['img_tag'][ $index ], 'sizes' ) ) {
1440
  $this->debug_message( "srcset filling with $src" );
1441
  $zoom = false;
1558
  continue;
1559
  }
1560
  $full_link_url = $link_url;
1561
+ // Check for relative URLs that start with a slash.
1562
  if (
1563
  '/' === substr( $link_url, 0, 1 ) &&
1564
+ '/' !== substr( $link_url, 1, 1 ) &&
1565
+ false === strpos( $this->upload_domain, 'amazonaws.com' ) &&
1566
+ false === strpos( $this->upload_domain, 'digitaloceanspaces.com' ) &&
1567
+ false === strpos( $this->upload_domain, 'storage.googleapis.com' )
1568
  ) {
1569
  $full_link_url = '//' . $this->upload_domain . $link_url;
1570
  }
1607
  $srcset = $this->get_attribute( $source, 'srcset' );
1608
  if ( $srcset ) {
1609
  $new_srcset = $this->srcset_replace( $srcset );
1610
+ if ( $new_srcset && $new_srcset !== $srcset ) {
1611
  $new_source = str_replace( $srcset, $new_srcset, $source );
1612
  $picture = str_replace( $source, $new_source, $picture );
1613
  }
1623
  return $content;
1624
  }
1625
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1626
  /**
1627
  * Parse page content looking for elements with CSS background-image properties.
1628
  *
1651
  }
1652
  $this->debug_message( "checking style attr for background-image: $style" );
1653
  $bg_image_url = $this->get_background_image_url( $style );
1654
+ $orig_bg_url = $bg_image_url;
1655
+
1656
+ // Check for relative URLs that start with a slash.
1657
+ if (
1658
+ '/' === substr( $bg_image_url, 0, 1 ) &&
1659
+ '/' !== substr( $bg_image_url, 1, 1 ) &&
1660
+ false === strpos( $this->upload_domain, 'amazonaws.com' ) &&
1661
+ false === strpos( $this->upload_domain, 'digitaloceanspaces.com' ) &&
1662
+ false === strpos( $this->upload_domain, 'storage.googleapis.com' )
1663
+ ) {
1664
+ $bg_image_url = '//' . $this->upload_domain . $bg_image_url;
1665
+ }
1666
+
1667
  if ( $this->validate_image_url( $bg_image_url ) ) {
1668
  /** This filter is already documented in class-exactdn.php */
1669
  if ( apply_filters( 'exactdn_skip_image', false, $bg_image_url, $element ) ) {
1687
  }
1688
  $exactdn_bg_image_url = $this->generate_url( $bg_image_url, $args );
1689
  if ( $bg_image_url !== $exactdn_bg_image_url ) {
1690
+ $new_style = str_replace( $orig_bg_url, $exactdn_bg_image_url, $style );
1691
  $element = str_replace( $style, $new_style, $element );
1692
  }
1693
  }
2018
  $image_args['width'] = $image_meta['width'];
2019
  $image_args['height'] = $image_meta['height'];
2020
 
2021
+ global $content_width;
2022
+ if ( defined( 'EXACTDN_CONTENT_WIDTH' ) && ! empty( $content_width ) ) {
2023
+ $real_content_width = $content_width;
2024
+ $content_width = EXACTDN_CONTENT_WIDTH;
2025
+ }
2026
  // NOTE: it will constrain an image to $content_width which is expected behavior in core, so far as I can see.
2027
  list( $image_args['width'], $image_args['height'] ) = image_constrain_size_for_editor( $image_args['width'], $image_args['height'], $size, 'display' );
2028
+ if ( defined( 'EXACTDN_CONTENT_WIDTH' ) && ! empty( $real_content_width ) ) {
2029
+ $content_width = $real_content_width;
2030
+ }
2031
 
2032
  $has_size_meta = true;
2033
  $this->debug_message( 'image args constrained: ' . $this->implode( ',', $image_args ) );
2143
  $has_size_meta = true;
2144
  }
2145
 
2146
+ global $content_width;
2147
+ if ( defined( 'EXACTDN_CONTENT_WIDTH' ) && ! empty( $content_width ) ) {
2148
+ $real_content_width = $content_width;
2149
+ $content_width = EXACTDN_CONTENT_WIDTH;
2150
+ }
2151
  list( $width, $height ) = image_constrain_size_for_editor( $width, $height, $size );
2152
  $this->debug_message( "constrained to w$width by h$height" );
2153
+ if ( defined( 'EXACTDN_CONTENT_WIDTH' ) && ! empty( $real_content_width ) ) {
2154
+ $content_width = $real_content_width;
2155
+ }
2156
 
2157
  // Expose arguments to a filter before passing to ExactDN.
2158
  $exactdn_args = array(
2195
  return $image;
2196
  }
2197
 
2198
+ /**
2199
+ * Replaces images within a srcset attribute with Easy IO URLs.
2200
+ *
2201
+ * @param string $srcset A valid srcset attribute from an img element.
2202
+ * @return string The srcset attribute with Easy IO URLs.
2203
+ */
2204
+ function srcset_replace( $srcset ) {
2205
+ $this->debug_message( '<b>' . __METHOD__ . '()</b>' );
2206
+ $srcset_urls = explode( ' ', $srcset );
2207
+ if ( $this->is_iterable( $srcset_urls ) && count( $srcset_urls ) > 1 ) {
2208
+ $this->debug_message( 'parsing srcset urls' );
2209
+ foreach ( $srcset_urls as $srcurl ) {
2210
+ if ( is_numeric( substr( $srcurl, 0, 1 ) ) ) {
2211
+ continue;
2212
+ }
2213
+ $trailing = ' ';
2214
+ if ( ',' === substr( $srcurl, -1 ) ) {
2215
+ $trailing = ',';
2216
+ $srcurl = rtrim( $srcurl, ',' );
2217
+ }
2218
+ $this->debug_message( "looking for $srcurl from srcset" );
2219
+ $new_srcurl = $srcurl;
2220
+ // Check for relative URLs that start with a slash.
2221
+ if (
2222
+ '/' === substr( $srcurl, 0, 1 ) &&
2223
+ '/' !== substr( $srcurl, 1, 1 ) &&
2224
+ false === strpos( $this->upload_domain, 'amazonaws.com' ) &&
2225
+ false === strpos( $this->upload_domain, 'digitaloceanspaces.com' ) &&
2226
+ false === strpos( $this->upload_domain, 'storage.googleapis.com' )
2227
+ ) {
2228
+ $new_srcurl = '//' . $this->upload_domain . $new_srcurl;
2229
+ }
2230
+ if ( $this->validate_image_url( $new_srcurl ) ) {
2231
+ $srcset = str_replace( $srcurl . $trailing, $this->generate_url( $new_srcurl ) . $trailing, $srcset );
2232
+ $this->debug_message( "replaced $srcurl in srcset" );
2233
+ }
2234
+ }
2235
+ } elseif ( $this->validate_image_url( $srcset ) ) {
2236
+ return $this->generate_url( $srcset );
2237
+ }
2238
+ return $srcset;
2239
+ }
2240
+
2241
  /**
2242
  * Filters an array of image `srcset` values, replacing each URL with its ExactDN equivalent.
2243
  *
2275
  return $sources;
2276
  }
2277
 
2278
+ $this->debug_message( "image_src = $image_src" );
2279
  $upload_dir = wp_get_upload_dir();
2280
  $resize_existing = defined( 'EXACTDN_RESIZE_EXISTING' ) && EXACTDN_RESIZE_EXISTING;
2281
  $w_descriptor = true;
2348
  * @param array|bool $multipliers Array of multipliers to use or false to bypass.
2349
  */
2350
  $multipliers = apply_filters( 'exactdn_srcset_multipliers', array( .2, .4, .6, .8, 1, 2, 3, 1920 ) );
2351
+
2352
+ $this->debug_message( "building url from {$upload_dir['baseurl']} and {$image_meta['file']}" );
2353
+ $url = trailingslashit( $upload_dir['baseurl'] ) . $image_meta['file'];
2354
+
2355
  if ( ! $w_descriptor ) {
2356
  $this->debug_message( 'using x descriptors instead of w' );
2357
  $multipliers = array_filter( $multipliers, 'is_int' );
3064
  if ( false !== strpos( $uri, 'ct_render_shortcode=' ) || false !== strpos( $uri, 'action=oxy_render' ) ) {
3065
  return true;
3066
  }
3067
+ if ( false !== strpos( $uri, 'elementor-preview=' ) ) {
3068
+ return true;
3069
+ }
3070
  if ( false !== strpos( $uri, 'et_fb=' ) ) {
3071
  return true;
3072
  }
3079
  if ( false !== strpos( $uri, 'tatsu=' ) ) {
3080
  return true;
3081
  }
3082
+ if ( false !== strpos( $uri, 'tve=true' ) ) {
3083
+ return true;
3084
+ }
3085
  return $skip;
3086
  }
3087
 
3361
  if ( $this->exactdn_domain === $image_url_parts['host'] ) {
3362
  $this->debug_message( 'url already has exactdn domain' );
3363
  $exactdn_url = add_query_arg( $args, $image_url );
3364
+ $exactdn_url = str_replace( '&#038;', '&', $exactdn_url );
3365
+ $exactdn_url = str_replace( '#038;', '&', $exactdn_url );
3366
  return $this->url_scheme( $exactdn_url, $scheme );
3367
  }
3368
 
3408
  if ( $args ) {
3409
  if ( is_array( $args ) ) {
3410
  $exactdn_url = add_query_arg( $args, $exactdn_url );
3411
+ $exactdn_url = str_replace( '&#038;', '&', $exactdn_url );
3412
+ $exactdn_url = str_replace( '#038;', '&', $exactdn_url );
3413
  } else {
3414
  // You can pass a query string for complicated requests, although this should have been converted to an array already.
3415
  $exactdn_url .= '?' . $args;
common.php CHANGED
@@ -14,7 +14,7 @@ if ( ! defined( 'ABSPATH' ) ) {
14
  exit;
15
  }
16
 
17
- define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '625' );
18
 
19
  // Initialize a couple globals.
20
  $eio_debug = '';
@@ -2134,13 +2134,13 @@ function ewww_image_optimizer_notice_exactdn_domain_mismatch() {
2134
  );
2135
  ?>
2136
  <br>
2137
- <?php
2138
- printf(
2139
- /* translators: %s: settings page */
2140
- esc_html__( 'Please visit the %s to refresh the Easy IO settings and verify activation status.', 'ewww-image-optimizer' ),
2141
- '<a href="' . esc_url( ewww_image_optimizer_get_settings_link() ) . '">' . esc_html__( 'settings page', 'ewww-image-optimizer' ) . '</a>'
2142
- );
2143
- ?>
2144
  </p>
2145
  </div>
2146
  <?php
@@ -4753,6 +4753,7 @@ function ewww_image_optimizer_exactdn_activate_site_ajax() {
4753
  if ( get_current_blog_id() !== $blog_id ) {
4754
  switch_to_blog( $blog_id );
4755
  }
 
4756
  if ( get_option( 'ewww_image_optimizer_exactdn' ) ) {
4757
  die( wp_json_encode( array( 'success' => esc_html__( 'Easy IO setup and verification is complete.', 'ewww-image-optimizer' ) ) ) );
4758
  }
@@ -4772,6 +4773,7 @@ function ewww_image_optimizer_exactdn_activate_site_ajax() {
4772
  $exactdn = new ExactDN();
4773
  }
4774
  if ( $exactdn->get_exactdn_domain() ) {
 
4775
  die( wp_json_encode( array( 'success' => esc_html__( 'Easy IO setup and verification is complete.', 'ewww-image-optimizer' ) ) ) );
4776
  }
4777
  restore_current_blog();
@@ -4813,6 +4815,7 @@ function ewww_image_optimizer_exactdn_register_site_ajax() {
4813
  $switch = true;
4814
  switch_to_blog( $blog_id );
4815
  }
 
4816
  if ( get_option( 'ewww_image_optimizer_exactdn' ) ) {
4817
  if ( ! empty( $switch ) ) {
4818
  restore_current_blog();
@@ -4900,6 +4903,7 @@ function ewww_image_optimizer_initialize_site( $new_site ) {
4900
  * @return array The results of the http POST request.
4901
  */
4902
  function ewww_image_optimizer_register_site_post() {
 
4903
  // Get the site URL for a given blog.
4904
  $eio_base = new EIO_Base();
4905
  $site_url = $eio_base->content_url();
@@ -4908,6 +4912,7 @@ function ewww_image_optimizer_register_site_post() {
4908
  if ( empty( $key ) ) {
4909
  return new WP_Error( 'missing_key', __( 'No API key for Easy IO registration', 'ewww-image-optimizer' ) );
4910
  }
 
4911
  $url = 'https://optimize.exactlywww.com/exactdn/create.php';
4912
  add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
4913
  $result = wp_remote_post(
@@ -12116,6 +12121,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
12116
  if ( PHP_OS !== 'WINNT' && ! ewww_image_optimizer_full_cloud() && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
12117
  ewww_image_optimizer_find_nix_binary( 'nice', 'n' );
12118
  }
 
12119
  $allow_help_html = array(
12120
  'a' => array(
12121
  'class' => array(),
@@ -12130,6 +12136,15 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
12130
  ),
12131
  );
12132
 
 
 
 
 
 
 
 
 
 
12133
  if ( 'network-multisite-over' === $network ) {
12134
  ob_start();
12135
  }
@@ -13476,7 +13491,7 @@ AddType image/webp .webp</pre>
13476
  <?php ob_end_clean(); ?>
13477
  <div id='ewww-resize-settings'>
13478
  <table class='form-table'>
13479
- <?php echo ( empty( $exactdn_sub_folder ) ? wp_kses_post( $exactdn_settings_row ) : '' ); ?>
13480
  <?php endif; ?>
13481
  <!-- RIGHT HERE is where we begin/clear buffer for network-singlesite (non-override version). -->
13482
  <!-- Though the buffer will need to be started right the form begins. -->
@@ -13914,7 +13929,7 @@ function ewww_image_optimizer_remove_cloud_key( $redirect = true ) {
13914
  */
13915
  function ewww_image_optimizer_remove_easyio() {
13916
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
13917
- $permissions = apply_filters( 'ewww_image_optimizer_admin_permissions', '' );
13918
  if ( false === current_user_can( $permissions ) ) {
13919
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
13920
  }
14
  exit;
15
  }
16
 
17
+ define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '630' );
18
 
19
  // Initialize a couple globals.
20
  $eio_debug = '';
2134
  );
2135
  ?>
2136
  <br>
2137
+ <?php
2138
+ printf(
2139
+ /* translators: %s: settings page */
2140
+ esc_html__( 'Please visit the %s to refresh the Easy IO settings and verify activation status.', 'ewww-image-optimizer' ),
2141
+ '<a href="' . esc_url( ewww_image_optimizer_get_settings_link() ) . '">' . esc_html__( 'settings page', 'ewww-image-optimizer' ) . '</a>'
2142
+ );
2143
+ ?>
2144
  </p>
2145
  </div>
2146
  <?php
4753
  if ( get_current_blog_id() !== $blog_id ) {
4754
  switch_to_blog( $blog_id );
4755
  }
4756
+ ewwwio_debug_message( "activating site $blog_id" );
4757
  if ( get_option( 'ewww_image_optimizer_exactdn' ) ) {
4758
  die( wp_json_encode( array( 'success' => esc_html__( 'Easy IO setup and verification is complete.', 'ewww-image-optimizer' ) ) ) );
4759
  }
4773
  $exactdn = new ExactDN();
4774
  }
4775
  if ( $exactdn->get_exactdn_domain() ) {
4776
+ ewwwio_debug_message( 'activated site ' . $exactdn->content_url() . ' got domain ' . $exactdn->get_exactdn_domain() );
4777
  die( wp_json_encode( array( 'success' => esc_html__( 'Easy IO setup and verification is complete.', 'ewww-image-optimizer' ) ) ) );
4778
  }
4779
  restore_current_blog();
4815
  $switch = true;
4816
  switch_to_blog( $blog_id );
4817
  }
4818
+ ewwwio_debug_message( "registering site $blog_id" );
4819
  if ( get_option( 'ewww_image_optimizer_exactdn' ) ) {
4820
  if ( ! empty( $switch ) ) {
4821
  restore_current_blog();
4903
  * @return array The results of the http POST request.
4904
  */
4905
  function ewww_image_optimizer_register_site_post() {
4906
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
4907
  // Get the site URL for a given blog.
4908
  $eio_base = new EIO_Base();
4909
  $site_url = $eio_base->content_url();
4912
  if ( empty( $key ) ) {
4913
  return new WP_Error( 'missing_key', __( 'No API key for Easy IO registration', 'ewww-image-optimizer' ) );
4914
  }
4915
+ ewwwio_debug_message( "registering $site_url on Easy IO" );
4916
  $url = 'https://optimize.exactlywww.com/exactdn/create.php';
4917
  add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
4918
  $result = wp_remote_post(
12121
  if ( PHP_OS !== 'WINNT' && ! ewww_image_optimizer_full_cloud() && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
12122
  ewww_image_optimizer_find_nix_binary( 'nice', 'n' );
12123
  }
12124
+
12125
  $allow_help_html = array(
12126
  'a' => array(
12127
  'class' => array(),
12136
  ),
12137
  );
12138
 
12139
+ $allow_settings_html = wp_kses_allowed_html( 'post' );
12140
+ $allow_settings_html['input'] = array(
12141
+ 'type' => true,
12142
+ 'id' => true,
12143
+ 'name' => true,
12144
+ 'value' => true,
12145
+ 'readonly' => true,
12146
+ );
12147
+
12148
  if ( 'network-multisite-over' === $network ) {
12149
  ob_start();
12150
  }
13491
  <?php ob_end_clean(); ?>
13492
  <div id='ewww-resize-settings'>
13493
  <table class='form-table'>
13494
+ <?php echo ( empty( $exactdn_sub_folder ) ? wp_kses( $exactdn_settings_row, $allow_settings_html ) : '' ); ?>
13495
  <?php endif; ?>
13496
  <!-- RIGHT HERE is where we begin/clear buffer for network-singlesite (non-override version). -->
13497
  <!-- Though the buffer will need to be started right the form begins. -->
13929
  */
13930
  function ewww_image_optimizer_remove_easyio() {
13931
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
13932
+ $permissions = apply_filters( 'ewww_image_optimizer_admin_permissions', 'manage_options' );
13933
  if ( false === current_user_can( $permissions ) ) {
13934
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
13935
  }
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: 6.2.5
17
  Requires at least: 5.5
18
  Requires PHP: 7.1
19
  Author URI: https://ewww.io/
13
  Plugin URI: https://wordpress.org/plugins/ewww-image-optimizer/
14
  Description: Reduce file sizes for images within WordPress including NextGEN Gallery and GRAND FlAGallery. Uses jpegtran, optipng/pngout, and gifsicle.
15
  Author: Exactly WWW
16
+ Version: 6.3.0
17
  Requires at least: 5.5
18
  Requires PHP: 7.1
19
  Author URI: https://ewww.io/
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: optimize, image, convert, webp, resize, compress, lazy load, optimization,
5
  Requires at least: 5.5
6
  Tested up to: 5.8
7
  Requires PHP: 7.1
8
- Stable tag: 6.2.5
9
  License: GPLv3
10
 
11
  Smaller Images, Faster Sites, Happier Visitors. Comprehensive image optimization that doesn't require a degree in rocket science.
@@ -137,6 +137,15 @@ That's not a question, but since I made it up, I'll answer it. See this resource
137
  * Feature requests can be viewed and submitted on our [feedback portal](https://feedback.ewww.io/b/features)
138
  * If you would like to help translate this plugin in your language, [join the team](https://translate.wordpress.org/projects/wp-plugins/ewww-image-optimizer/)
139
 
 
 
 
 
 
 
 
 
 
140
  = 6.2.5 =
141
  * added: Easy IO and Lazy Load support for AJAX responses from FacetWP
142
  * changed: Vimeo videos excluded from iframe lazy load
5
  Requires at least: 5.5
6
  Tested up to: 5.8
7
  Requires PHP: 7.1
8
+ Stable tag: 6.3.0
9
  License: GPLv3
10
 
11
  Smaller Images, Faster Sites, Happier Visitors. Comprehensive image optimization that doesn't require a degree in rocket science.
137
  * Feature requests can be viewed and submitted on our [feedback portal](https://feedback.ewww.io/b/features)
138
  * If you would like to help translate this plugin in your language, [join the team](https://translate.wordpress.org/projects/wp-plugins/ewww-image-optimizer/)
139
 
140
+ = 6.3.0 =
141
+ * added: EIO_LAZY_FOLD override to configure number of images above-the-fold that will be skipped by Lazy Load
142
+ * added: Easy IO URLs for custom (non-WP) srcset markup
143
+ * added: Easy IO support for CSS background images with relative URLs
144
+ * fixed: Easy IO scaling not working on full-size images without srcset/responsive markup
145
+ * fixed: WebP and Lazy Load function skip images dynamically created by Brizy builder
146
+ * fixed: Easy IO conflict on Elementor preview pages
147
+ * fixed: EXACTDN_CONTENT_WIDTH not effective at overriding $content_width during image_downsize filter
148
+
149
  = 6.2.5 =
150
  * added: Easy IO and Lazy Load support for AJAX responses from FacetWP
151
  * changed: Vimeo videos excluded from iframe lazy load