EWWW Image Optimizer - Version 4.3.0

Version Description

  • added: Alt WebP enables instant conversion with ExactDN, no need for bulk optimize
  • added: links within settings and other notices for contextual help
  • added: auto-convert large PNG images to JPG during upload, define EWWW_IMAGE_OPTIMIZER_DISABLE_AUTOCONVERT to skip
  • added: use file modification time to add query strings on JS/CSS files for cache invalidation on ExactDN
  • added: use EXACTDN_EXCLUDE in wp-config.php to bypass ExactDN for JS, CSS, etc.
  • added: NextGEN image urls properly rewritten for ExactDN
  • added: NextGEN dynamic thumbs included during manual/bulk optimization
  • added: auto-installer for Cloud plugin when running EWWW IO on a "banned" webhost
  • added: suggested privacy policy text for users of the API and ExactDN
  • added: detect wordpress.com sites and disable exec function and binaries
  • changed: resizing uses the primary media dimensions unless the "other" dimensions are configured
  • changed: Resize Other Images removed from GUI, configure via Overrides tab
  • changed: filter NextGEN quality to prevent oversized thumbs
  • changed: allow crop via filter even when one dimension is the same as the original
  • changed: auto-rotate function disabled with EWWW_IMAGE_OPTIMIZER_DISABLE_AUTOROTATE
  • changed: one-click copy for debug info, and debug collapsed by default in media library and bulk results
  • changed: bulk operations for batches of NextGEN images now use the bulk optimizer page instead of loading inline
  • fixed: thumbs not generated during WP/LR Sync
  • fixed: uploading images in the Gutenberg editor uses the wrong resize dimensions
  • fixed: unique filename function producing names with a hyphen and no digits
  • fixed: encoded ampersands within the path portion of a url prevent ExactDN parsing
  • fixed: entering a decimal for bulk delay does nothing
  • fixed: if urls on a localized WPML domain are using the default domain, ExactDN ignores them
  • fixed: toggle for plugin status and bulk status generate admin-ajax.php 403 errors
  • fixed: PNGOUT installer confirmation notice was missing
  • deprecated: PHP 5.4 support will be removed in the next major release (version 4.4)
Download this release

Release Info

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

Code changes from version 4.2.3 to 4.3.0

aux-optimize.php CHANGED
@@ -74,22 +74,8 @@ function ewww_image_optimizer_aux_images() {
74
  esc_html__( 'This will allow us to assist you more quickly.', 'ewww-image-optimizer' );
75
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
76
  ewww_image_optimizer_options( 'debug-silent' );
77
- ?>
78
- <script type="text/javascript">
79
- function selectText(containerid) {
80
- var debug_node = document.getElementById(containerid);
81
- if (document.selection) {
82
- var range = document.body.createTextRange();
83
- range.moveToElementText(debug_node);
84
- range.select();
85
- } else if (window.getSelection) {
86
- window.getSelection().selectAllChildren(debug_node);
87
- }
88
- }
89
- </script>
90
- <?php
91
  global $ewww_debug;
92
- $output .= '<p style="clear:both"><b>' . esc_html__( 'Debugging Information', 'ewww-image-optimizer' ) . ':</b> <button onclick="selectText(' . "'ewww-debug-info'" . ')">' . esc_html__( 'Select All', 'ewww-image-optimizer' ) . '</button>';
93
  if ( is_file( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'debug.log' ) ) {
94
  $debug_log_url = plugins_url( '/debug.log', __FILE__ );
95
  $output .= "&emsp;<a href='$debug_log_url'>" . esc_html( 'View Debug Log', 'ewww-image-optimizer' ) . "</a> - <a href='admin.php?action=ewww_image_optimizer_delete_debug_log'>" . esc_html( 'Remove Debug Log', 'ewww-image-optimizer' ) . '</a>';
74
  esc_html__( 'This will allow us to assist you more quickly.', 'ewww-image-optimizer' );
75
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
76
  ewww_image_optimizer_options( 'debug-silent' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  global $ewww_debug;
78
+ $output .= '<p style="clear:both"><b>' . esc_html__( 'Debugging Information', 'ewww-image-optimizer' ) . ':</b> <button id="ewww-copy-debug" class="button button-secondary">' . esc_html__( 'Copy', 'ewww-image-optimizer' ) . '</button>';
79
  if ( is_file( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'debug.log' ) ) {
80
  $debug_log_url = plugins_url( '/debug.log', __FILE__ );
81
  $output .= "&emsp;<a href='$debug_log_url'>" . esc_html( 'View Debug Log', 'ewww-image-optimizer' ) . "</a> - <a href='admin.php?action=ewww_image_optimizer_delete_debug_log'>" . esc_html( 'Remove Debug Log', 'ewww-image-optimizer' ) . '</a>';
bulk.php CHANGED
@@ -88,21 +88,21 @@ function ewww_image_optimizer_bulk_head_output() {
88
  <div id="ewww-bulk-widgets" class="metabox-holder" style="display:none">
89
  <div class="meta-box-sortables">
90
  <div id="ewww-bulk-last" class="postbox">
91
- <button type="button" class="handlediv button-link" aria-expanded="true">
92
  <span class="screen-reader-text"><?php esc_html_e( 'Click to toggle', 'ewww-image-optimizer' ); ?></span>
93
- <span class="toggle-indicator" aria-hidden="true"></span>
94
  </button>
95
- <h2 class="hndle"><span><?php esc_html_e( 'Last Batch Optimized', 'ewww-image-optimizer' ); ?></span></h2>
96
  <div class="inside"></div>
97
  </div>
98
  </div>
99
  <div class="meta-box-sortables">
100
  <div id="ewww-bulk-status" class="postbox">
101
- <button type="button" class="handlediv button-link" aria-expanded="true">
102
  <span class="screen-reader-text"><?php esc_html_e( 'Click to toggle', 'ewww-image-optimizer' ); ?></span>
103
- <span class="toggle-indicator" aria-hidden="true"></span>
104
  </button>
105
- <h2 class="hndle"><span><?php esc_html_e( 'Optimization Log', 'ewww-image-optimizer' ); ?></span></h2>
106
  <div class="inside"></div>
107
  </div>
108
  </div>
@@ -242,7 +242,7 @@ function ewww_image_optimizer_count_optimized( $gallery ) {
242
  break;
243
  case 'ngg':
244
  // See if we were given attachment IDs to work with via GET/POST.
245
- if ( ! empty( $_REQUEST['ewww_inline'] ) || get_option( 'ewww_image_optimizer_bulk_ngg_resume' ) ) {
246
  // Retrieve the attachment IDs that were pre-loaded in the database.
247
  $attachment_ids = get_option( 'ewww_image_optimizer_bulk_ngg_attachments' );
248
  array_walk( $attachment_ids, 'intval' );
@@ -257,7 +257,8 @@ function ewww_image_optimizer_count_optimized( $gallery ) {
257
  // Creating a database storage object from the 'registry' object.
258
  $storage = $registry->get_utility( 'I_Gallery_Storage' );
259
  // Get an array of sizes available for the $image.
260
- $sizes = $storage->get_image_sizes();
 
261
  $offset = 0;
262
  while ( $attachments = $wpdb->get_col( "SELECT meta_data FROM $wpdb->nggpictures $attachment_query LIMIT $offset, $max_query" ) ) { // WPCS: unprepared SQL ok.
263
  foreach ( $attachments as $attachment ) {
@@ -273,8 +274,9 @@ function ewww_image_optimizer_count_optimized( $gallery ) {
273
  if ( empty( $meta['ewww_image_optimizer'] ) ) {
274
  $unoptimized_full++;
275
  }
276
- if ( ewww_image_optimizer_iterable( $sizes ) ) {
277
- foreach ( $sizes as $size ) {
 
278
  if ( 'full' !== $size ) {
279
  $resize_count++;
280
  if ( empty( $meta[ $size ]['ewww_image_optimizer'] ) ) {
@@ -1645,7 +1647,9 @@ function ewww_image_optimizer_bulk_loop( $hook = '', $delay = 0 ) {
1645
  update_option( 'ewww_image_optimizer_bulk_attachments', $attachments, false );
1646
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
1647
  global $ewww_debug;
1648
- $output['results'] .= '<div style="background-color:#ffff99;">' . $ewww_debug . '</div>';
 
 
1649
  }
1650
  if ( ! empty( $next_image->file ) ) {
1651
  $next_file = esc_html( $next_image->file );
88
  <div id="ewww-bulk-widgets" class="metabox-holder" style="display:none">
89
  <div class="meta-box-sortables">
90
  <div id="ewww-bulk-last" class="postbox">
91
+ <button type="button" class="ewww-handlediv button-link" aria-expanded="true">
92
  <span class="screen-reader-text"><?php esc_html_e( 'Click to toggle', 'ewww-image-optimizer' ); ?></span>
93
+ <span class="toggle-indicator" aria-hidden="false"></span>
94
  </button>
95
+ <h2 class="ewww-hndle"><span><?php esc_html_e( 'Last Batch Optimized', 'ewww-image-optimizer' ); ?></span></h2>
96
  <div class="inside"></div>
97
  </div>
98
  </div>
99
  <div class="meta-box-sortables">
100
  <div id="ewww-bulk-status" class="postbox">
101
+ <button type="button" class="ewww-handlediv button-link" aria-expanded="true">
102
  <span class="screen-reader-text"><?php esc_html_e( 'Click to toggle', 'ewww-image-optimizer' ); ?></span>
103
+ <span class="toggle-indicator" aria-hidden="false"></span>
104
  </button>
105
+ <h2 class="ewww-hndle"><span><?php esc_html_e( 'Optimization Log', 'ewww-image-optimizer' ); ?></span></h2>
106
  <div class="inside"></div>
107
  </div>
108
  </div>
242
  break;
243
  case 'ngg':
244
  // See if we were given attachment IDs to work with via GET/POST.
245
+ if ( ! empty( $_REQUEST['doaction'] ) || get_option( 'ewww_image_optimizer_bulk_ngg_resume' ) ) {
246
  // Retrieve the attachment IDs that were pre-loaded in the database.
247
  $attachment_ids = get_option( 'ewww_image_optimizer_bulk_ngg_attachments' );
248
  array_walk( $attachment_ids, 'intval' );
257
  // Creating a database storage object from the 'registry' object.
258
  $storage = $registry->get_utility( 'I_Gallery_Storage' );
259
  // Get an array of sizes available for the $image.
260
+ $sizes = $storage->get_image_sizes();
261
+ global $ewwwngg;
262
  $offset = 0;
263
  while ( $attachments = $wpdb->get_col( "SELECT meta_data FROM $wpdb->nggpictures $attachment_query LIMIT $offset, $max_query" ) ) { // WPCS: unprepared SQL ok.
264
  foreach ( $attachments as $attachment ) {
274
  if ( empty( $meta['ewww_image_optimizer'] ) ) {
275
  $unoptimized_full++;
276
  }
277
+ $ngg_sizes = $ewwwngg->maybe_get_more_sizes( $sizes, $meta );
278
+ if ( ewww_image_optimizer_iterable( $ngg_sizes ) ) {
279
+ foreach ( $ngg_sizes as $size ) {
280
  if ( 'full' !== $size ) {
281
  $resize_count++;
282
  if ( empty( $meta[ $size ]['ewww_image_optimizer'] ) ) {
1647
  update_option( 'ewww_image_optimizer_bulk_attachments', $attachments, false );
1648
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
1649
  global $ewww_debug;
1650
+ $debug_button = esc_html__( 'Show Debug Output', 'ewww-image-optimizer' );
1651
+ $debug_id = uniqid();
1652
+ $output['results'] .= "<button type='button' class='ewww-show-debug-meta button button-secondary' data-id='$debug_id'>$debug_button</button><div class='ewww-debug-meta-$debug_id' style='background-color:#ffff99;display:none;'>$ewww_debug</div>";
1653
  }
1654
  if ( ! empty( $next_image->file ) ) {
1655
  $next_file = esc_html( $next_image->file );
changelog.txt CHANGED
@@ -1,3 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  = 4.2.3 =
2
  * added: skip resizing for images with noresize in the filename
3
  * added: notice about plugins that remove query strings when ExactDN is active
1
+ = 4.3.0 =
2
+ * added: Alt WebP enables instant conversion with ExactDN, no need for bulk optimize
3
+ * added: links within settings and other notices for contextual help
4
+ * added: auto-convert large PNG images to JPG during upload, define EWWW_IMAGE_OPTIMIZER_DISABLE_AUTOCONVERT to skip
5
+ * added: use file modification time to add query strings on JS/CSS files for cache invalidation on ExactDN
6
+ * added: use EXACTDN_EXCLUDE in wp-config.php to bypass ExactDN for JS, CSS, etc.
7
+ * added: NextGEN image urls properly rewritten for ExactDN
8
+ * added: NextGEN dynamic thumbs included during manual/bulk optimization
9
+ * added: auto-installer for Cloud plugin when running EWWW IO on a "banned" webhost
10
+ * added: suggested privacy policy text for users of the API and ExactDN
11
+ * added: detect wordpress.com sites and disable exec function and binaries
12
+ * changed: resizing uses the primary media dimensions unless the "other" dimensions are configured
13
+ * changed: Resize Other Images removed from GUI, configure via Overrides tab
14
+ * changed: filter NextGEN quality to prevent oversized thumbs
15
+ * changed: allow crop via filter even when one dimension is the same as the original
16
+ * changed: auto-rotate function disabled with EWWW_IMAGE_OPTIMIZER_DISABLE_AUTOROTATE
17
+ * changed: one-click copy for debug info, and debug collapsed by default in media library and bulk results
18
+ * changed: bulk operations for batches of NextGEN images now use the bulk optimizer page instead of loading inline
19
+ * fixed: thumbs not generated during WP/LR Sync
20
+ * fixed: uploading images in the Gutenberg editor uses the wrong resize dimensions
21
+ * fixed: unique filename function producing names with a hyphen and no digits
22
+ * fixed: encoded ampersands within the path portion of a url prevent ExactDN parsing
23
+ * fixed: entering a decimal for bulk delay does nothing
24
+ * fixed: if urls on a localized WPML domain are using the default domain, ExactDN ignores them
25
+ * fixed: toggle for plugin status and bulk status generate admin-ajax.php 403 errors
26
+ * fixed: PNGOUT installer confirmation notice was missing
27
+ * deprecated: PHP 5.4 support will be removed in the next major release (version 4.4)
28
+
29
  = 4.2.3 =
30
  * added: skip resizing for images with noresize in the filename
31
  * added: notice about plugins that remove query strings when ExactDN is active
classes/class-ewww-flag.php CHANGED
@@ -125,21 +125,21 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
125
  <div id="ewww-bulk-widgets" class="metabox-holder" style="display:none">
126
  <div class="meta-box-sortables">
127
  <div id="ewww-bulk-last" class="postbox">
128
- <button type="button" class="handlediv button-link" aria-expanded="true">
129
  <span class="screen-reader-text"><?php esc_html_e( 'Click to toggle', 'ewww-image-optimizer' ); ?></span>
130
  <span class="toggle-indicator" aria-hidden="true"></span>
131
  </button>
132
- <h2 class="hndle"><span><?php esc_html_e( 'Last Image Optimized', 'ewww-image-optimizer' ); ?></span></h2>
133
  <div class="inside"></div>
134
  </div>
135
  </div>
136
  <div class="meta-box-sortables">
137
  <div id="ewww-bulk-status" class="postbox">
138
- <button type="button" class="handlediv button-link" aria-expanded="true">
139
  <span class="screen-reader-text"><?php esc_html_e( 'Click to toggle', 'ewww-image-optimizer' ); ?></span>
140
  <span class="toggle-indicator" aria-hidden="true"></span>
141
  </button>
142
- <h2 class="hndle"><span><?php esc_html_e( 'Optimization Log', 'ewww-image-optimizer' ); ?></span></h2>
143
  <div class="inside"></div>
144
  </div>
145
  </div>
@@ -691,9 +691,10 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
691
  // Get the metadata.
692
  $meta = new flagMeta( $id );
693
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) && ewww_image_optimizer_function_exists( 'print_r' ) ) {
694
- $print_meta = print_r( $meta->image->meta_data, true );
695
- $print_meta = preg_replace( array( '/ /', '/\n+/' ), array( '&nbsp;', '<br />' ), esc_html( $print_meta ) );
696
- echo '<div style="background-color:#ffff99;font-size: 10px;padding: 10px;margin:-10px -10px 10px;line-height: 1.1em">' . $print_meta . '</div>';
 
697
  }
698
  // Get the image path from the meta.
699
  $file_path = $meta->image->imagePath;
125
  <div id="ewww-bulk-widgets" class="metabox-holder" style="display:none">
126
  <div class="meta-box-sortables">
127
  <div id="ewww-bulk-last" class="postbox">
128
+ <button type="button" class="ewww-handlediv button-link" aria-expanded="true">
129
  <span class="screen-reader-text"><?php esc_html_e( 'Click to toggle', 'ewww-image-optimizer' ); ?></span>
130
  <span class="toggle-indicator" aria-hidden="true"></span>
131
  </button>
132
+ <h2 class="ewww-hndle"><span><?php esc_html_e( 'Last Image Optimized', 'ewww-image-optimizer' ); ?></span></h2>
133
  <div class="inside"></div>
134
  </div>
135
  </div>
136
  <div class="meta-box-sortables">
137
  <div id="ewww-bulk-status" class="postbox">
138
+ <button type="button" class="ewww-handlediv button-link" aria-expanded="true">
139
  <span class="screen-reader-text"><?php esc_html_e( 'Click to toggle', 'ewww-image-optimizer' ); ?></span>
140
  <span class="toggle-indicator" aria-hidden="true"></span>
141
  </button>
142
+ <h2 class="ewww-hndle"><span><?php esc_html_e( 'Optimization Log', 'ewww-image-optimizer' ); ?></span></h2>
143
  <div class="inside"></div>
144
  </div>
145
  </div>
691
  // Get the metadata.
692
  $meta = new flagMeta( $id );
693
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) && ewww_image_optimizer_function_exists( 'print_r' ) ) {
694
+ $print_meta = print_r( $meta->image->meta_data, true );
695
+ $print_meta = preg_replace( array( '/ /', '/\n+/' ), array( '&nbsp;', '<br />' ), esc_html( $print_meta ) );
696
+ $debug_button = esc_html__( 'Show Metadata', 'ewww-image-optimizer' );
697
+ echo "<button type='button' class='ewww-show-debug-meta button button-secondary' data-id='$id'>$debug_button</button><div id='ewww-debug-meta-$id' style='background-color:#ffff99;font-size: 10px;padding: 10px;margin:3px -10px 10px;line-height: 1.1em;display: none;'>$print_meta</div>";
698
  }
699
  // Get the image path from the meta.
700
  $file_path = $meta->image->imagePath;
classes/class-ewww-image.php CHANGED
@@ -87,6 +87,12 @@ class EWWW_Image {
87
  * @var int $level
88
  */
89
  public $level = 0;
 
 
 
 
 
 
90
 
91
  /**
92
  * Creates an image record, either from a pending record in the database, or from a file path.
@@ -175,6 +181,7 @@ class EWWW_Image {
175
  $this->converted = ewww_image_optimizer_relative_path_replace( $new_image['converted'] );
176
  $this->gallery = ( empty( $gallery ) ? $new_image['gallery'] : $gallery );
177
  $this->backup = $new_image['backup'];
 
178
  }
179
 
180
  /**
@@ -465,12 +472,13 @@ class EWWW_Image {
465
  /**
466
  * Converts a file using built-in PHP functions.
467
  *
468
- * @access private
469
  *
470
  * @param string $file The name of the file to convert.
 
471
  * @return string The name of the new file.
472
  */
473
- private function convert( $file ) {
474
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
475
  if ( empty( $file ) ) {
476
  ewwwio_debug_message( 'no file provided to convert' );
@@ -493,27 +501,6 @@ class EWWW_Image {
493
  ewwwio_debug_message( "cannot convert mimetype: $type" );
494
  return false;
495
  }
496
-
497
- // Just in case, run through the constants and utility checks, someday to be replaced with a proper object (or transient) that we can reference.
498
- if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_CLOUD' ) || ! EWWW_IMAGE_OPTIMIZER_CLOUD ) {
499
- ewww_image_optimizer_define_noexec();
500
- if ( EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
501
- $nice = '';
502
- } else {
503
- // Check to see if 'nice' exists.
504
- $nice = ewww_image_optimizer_find_nix_binary( 'nice', 'n' );
505
- }
506
- }
507
- $skip = ewww_image_optimizer_skip_tools();
508
- // If the user has disabled the utility checks.
509
- if ( EWWW_IMAGE_OPTIMIZER_CLOUD ) {
510
- $skip['jpegtran'] = true;
511
- $skip['optipng'] = true;
512
- $skip['gifsicle'] = true;
513
- $skip['pngout'] = true;
514
- $skip['pngquant'] = true;
515
- $skip['webp'] = true;
516
- }
517
  switch ( $type ) {
518
  case 'image/jpeg':
519
  $png_size = 0;
@@ -715,7 +702,9 @@ class EWWW_Image {
715
  default:
716
  return false;
717
  } // End switch().
718
- $this->replace_url( $newfile, $file );
 
 
719
  return $newfile;
720
  }
721
 
@@ -735,7 +724,7 @@ class EWWW_Image {
735
  // Set the increment to 1 ( but allow the user to override it ).
736
  $filenum = apply_filters( 'ewww_image_optimizer_converted_filename_suffix', $this->increment );
737
  // But it must be only letters, numbers, or underscores.
738
- $filenum = ( preg_match( '/^[\w\d]*$/', $filenum ) ? $filenum : 1 );
739
  $suffix = ( ! empty( $filenum ) ? '-' . $filenum : '' );
740
  $dimensions = '';
741
  $default_hidpi_suffix = apply_filters( 'ewww_image_optimizer_hidpi_suffix', '@2x' );
87
  * @var int $level
88
  */
89
  public $level = 0;
90
+ /**
91
+ * Raw db record.
92
+ *
93
+ * @var array $record
94
+ */
95
+ public $record = array();
96
 
97
  /**
98
  * Creates an image record, either from a pending record in the database, or from a file path.
181
  $this->converted = ewww_image_optimizer_relative_path_replace( $new_image['converted'] );
182
  $this->gallery = ( empty( $gallery ) ? $new_image['gallery'] : $gallery );
183
  $this->backup = $new_image['backup'];
184
+ $this->record = $new_image;
185
  }
186
 
187
  /**
472
  /**
473
  * Converts a file using built-in PHP functions.
474
  *
475
+ * @access public
476
  *
477
  * @param string $file The name of the file to convert.
478
+ * @param bool $replace_url Default true. Run function to update database with new url.
479
  * @return string The name of the new file.
480
  */
481
+ public function convert( $file, $replace_url = true ) {
482
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
483
  if ( empty( $file ) ) {
484
  ewwwio_debug_message( 'no file provided to convert' );
501
  ewwwio_debug_message( "cannot convert mimetype: $type" );
502
  return false;
503
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
504
  switch ( $type ) {
505
  case 'image/jpeg':
506
  $png_size = 0;
702
  default:
703
  return false;
704
  } // End switch().
705
+ if ( $replace_url ) {
706
+ $this->replace_url( $newfile, $file );
707
+ }
708
  return $newfile;
709
  }
710
 
724
  // Set the increment to 1 ( but allow the user to override it ).
725
  $filenum = apply_filters( 'ewww_image_optimizer_converted_filename_suffix', $this->increment );
726
  // But it must be only letters, numbers, or underscores.
727
+ $filenum = ( preg_match( '/^[\w\d]+$/', $filenum ) ? $filenum : 1 );
728
  $suffix = ( ! empty( $filenum ) ? '-' . $filenum : '' );
729
  $dimensions = '';
730
  $default_hidpi_suffix = apply_filters( 'ewww_image_optimizer_hidpi_suffix', '@2x' );
classes/class-ewww-nextcellent.php CHANGED
@@ -458,21 +458,21 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
458
  <div id="ewww-bulk-widgets" class="metabox-holder" style="display:none">
459
  <div class="meta-box-sortables">
460
  <div id="ewww-bulk-last" class="postbox">
461
- <button type="button" class="handlediv button-link" aria-expanded="true">
462
  <span class="screen-reader-text"><?php esc_html_e( 'Click to toggle', 'ewww-image-optimizer' ); ?></span>
463
  <span class="toggle-indicator" aria-hidden="true"></span>
464
  </button>
465
- <h2 class="hndle"><span><?php esc_html_e( 'Last Image Optimized', 'ewww-image-optimizer' ); ?></span></h2>
466
  <div class="inside"></div>
467
  </div>
468
  </div>
469
  <div class="meta-box-sortables">
470
  <div id="ewww-bulk-status" class="postbox">
471
- <button type="button" class="handlediv button-link" aria-expanded="true">
472
  <span class="screen-reader-text"><?php esc_html_e( 'Click to toggle', 'ewww-image-optimizer' ); ?></span>
473
  <span class="toggle-indicator" aria-hidden="true"></span>
474
  </button>
475
- <h2 class="hndle"><span><?php esc_html_e( 'Optimization Log', 'ewww-image-optimizer' ); ?></span></h2>
476
  <div class="inside"></div>
477
  </div>
478
  </div>
458
  <div id="ewww-bulk-widgets" class="metabox-holder" style="display:none">
459
  <div class="meta-box-sortables">
460
  <div id="ewww-bulk-last" class="postbox">
461
+ <button type="button" class="ewww-handlediv button-link" aria-expanded="true">
462
  <span class="screen-reader-text"><?php esc_html_e( 'Click to toggle', 'ewww-image-optimizer' ); ?></span>
463
  <span class="toggle-indicator" aria-hidden="true"></span>
464
  </button>
465
+ <h2 class="ewww-hndle"><span><?php esc_html_e( 'Last Image Optimized', 'ewww-image-optimizer' ); ?></span></h2>
466
  <div class="inside"></div>
467
  </div>
468
  </div>
469
  <div class="meta-box-sortables">
470
  <div id="ewww-bulk-status" class="postbox">
471
+ <button type="button" class="ewww-handlediv button-link" aria-expanded="true">
472
  <span class="screen-reader-text"><?php esc_html_e( 'Click to toggle', 'ewww-image-optimizer' ); ?></span>
473
  <span class="toggle-indicator" aria-hidden="true"></span>
474
  </button>
475
+ <h2 class="ewww-hndle"><span><?php esc_html_e( 'Optimization Log', 'ewww-image-optimizer' ); ?></span></h2>
476
  <div class="inside"></div>
477
  </div>
478
  </div>
classes/class-ewww-nextgen.php CHANGED
@@ -22,6 +22,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
22
  */
23
  public function __construct() {
24
  add_filter( 'ngg_manage_images_number_of_columns', array( $this, 'ewww_manage_images_number_of_columns' ) );
 
25
  add_filter( 'ngg_manage_images_row_actions', array( $this, 'ewww_manage_images_row_actions' ) );
26
  if ( ewww_image_optimizer_test_background_opt() ) {
27
  add_action( 'ngg_added_new_image', array( $this, 'queue_new_image' ) );
@@ -35,7 +36,9 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
35
  add_action( 'admin_action_ewww_ngg_manual', array( $this, 'ewww_ngg_manual' ) );
36
  add_action( 'admin_enqueue_scripts', array( $this, 'ewww_ngg_manual_actions_script' ) );
37
  add_action( 'admin_menu', array( $this, 'ewww_ngg_bulk_menu' ) );
 
38
  add_action( 'admin_head', array( $this, 'ewww_ngg_bulk_actions_script' ) );
 
39
  add_action( 'admin_enqueue_scripts', array( $this, 'ewww_ngg_bulk_script' ), 20 );
40
  add_action( 'wp_ajax_bulk_ngg_preview', array( $this, 'ewww_ngg_bulk_preview' ) );
41
  add_action( 'wp_ajax_bulk_ngg_init', array( $this, 'ewww_ngg_bulk_init' ) );
@@ -43,6 +46,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
43
  add_action( 'wp_ajax_bulk_ngg_loop', array( $this, 'ewww_ngg_bulk_loop' ) );
44
  add_action( 'wp_ajax_bulk_ngg_cleanup', array( $this, 'ewww_ngg_bulk_cleanup' ) );
45
  add_action( 'ngg_generated_image', array( $this, 'ewww_ngg_generated_image' ), 10, 2 );
 
46
  }
47
 
48
  /**
@@ -52,7 +56,70 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
52
  if ( ! defined( 'NGGFOLDER' ) ) {
53
  return;
54
  }
55
- add_submenu_page( NGGFOLDER, esc_html__( 'Bulk Optimize', 'ewww-image-optimizer' ), esc_html__( 'Bulk Optimize', 'ewww-image-optimizer' ), apply_filters( 'ewww_image_optimizer_manual_permissions', '' ), 'ewww-ngg-bulk', array( &$this, 'ewww_ngg_bulk_preview' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  }
57
 
58
  /**
@@ -120,6 +187,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
120
  ewwwio_debug_message( "image id: $image_id" );
121
  // Get an array of sizes available for the $image.
122
  $sizes = $storage->get_image_sizes();
 
123
  // Run the optimizer on the image for each $size.
124
  if ( ewww_image_optimizer_iterable( $sizes ) ) {
125
  foreach ( $sizes as $size ) {
@@ -130,7 +198,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
130
  }
131
  // Get the absolute path.
132
  $file_path = $storage->get_image_abspath( $image, $size );
133
- ewwwio_debug_message( "optimizing (nextgen): $file_path" );
134
  $ewww_image = new EWWW_Image( $image_id, 'nextgen', $file_path );
135
  $ewww_image->resize = $size;
136
  // Optimize the image and grab the results.
@@ -143,10 +211,10 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
143
  } else {
144
  $image->meta_data[ $size ]['ewww_image_optimizer'] = $res[1];
145
  }
146
- nggdb::update_image_meta( $image_id, $image->meta_data );
147
- ewwwio_debug_message( 'storing results for full size image' );
148
  }
149
  }
 
 
150
  return $image;
151
  }
152
 
@@ -317,6 +385,19 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
317
  );
318
  }
319
 
 
 
 
 
 
 
 
 
 
 
 
 
 
320
  /**
321
  * Filter for ngg_manage_images_number_of_columns hook, changed in NGG 2.0.50ish.
322
  *
@@ -325,8 +406,8 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
325
  */
326
  function ewww_manage_images_number_of_columns( $count ) {
327
  $count++;
328
- add_filter( "ngg_manage_images_column_{$count}_header", array( &$this, 'ewww_manage_images_columns' ) );
329
- add_filter( "ngg_manage_images_column_{$count}_content", array( &$this, 'ewww_manage_image_custom_column' ), 10, 2 );
330
  return $count;
331
  }
332
 
@@ -340,9 +421,8 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
340
  if ( is_array( $columns ) ) {
341
  $columns['ewww_image_optimizer'] = esc_html__( 'Image Optimizer', 'ewww-image-optimizer' );
342
  return $columns;
343
- } else {
344
- return esc_html__( 'Image Optimizer', 'ewww-image-optimizer' );
345
  }
 
346
  }
347
 
348
  /**
@@ -369,9 +449,10 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
369
  }
370
  $output = "<div id='ewww-nextgen-status-$image->pid'>";
371
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) && ewww_image_optimizer_function_exists( 'print_r' ) ) {
372
- $print_meta = print_r( $image->meta_data, true );
373
- $print_meta = preg_replace( array( '/ /', '/\n+/' ), array( '&nbsp;', '<br />' ), esc_html( $print_meta ) );
374
- $output .= '<div style="background-color:#ffff99;font-size: 10px;padding: 10px;margin:-10px -10px 10px;line-height: 1.1em">' . $print_meta . '</div>';
 
375
  }
376
  $msg = '';
377
  // Get the absolute path.
@@ -421,6 +502,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
421
  // If we have metadata, populate db from meta.
422
  if ( ! empty( $image->meta_data['ewww_image_optimizer'] ) ) {
423
  $sizes = $storage->get_image_sizes();
 
424
  if ( ewww_image_optimizer_iterable( $sizes ) ) {
425
  foreach ( $sizes as $size ) {
426
  if ( 'full' === $size ) {
@@ -527,7 +609,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
527
  return;
528
  }
529
  // If there is no media to optimize, do nothing.
530
- if ( empty( $_REQUEST['doaction'] ) || ! is_array( $_REQUEST['doaction'] ) ) {
531
  return;
532
  }
533
  }
@@ -537,16 +619,8 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
537
  echo '<p>' . esc_html__( 'You do not appear to have uploaded any images yet.', 'ewww-image-optimizer' ) . '</p>';
538
  return;
539
  }
540
- if ( ! empty( $_REQUEST['ewww_inline'] ) ) {
541
- ?>
542
- <div class="wrap" style="padding: 2em;">
543
- <?php
544
- } else {
545
- ?>
546
- <div class="wrap">
547
- <?php
548
- }
549
  ?>
 
550
  <h1><?php esc_html_e( 'Bulk Optimize', 'ewww-image-optimizer' ); ?></h1>
551
  <?php
552
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
@@ -573,21 +647,21 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
573
  <div id="ewww-bulk-widgets" class="metabox-holder" style="display:none">
574
  <div class="meta-box-sortables">
575
  <div id="ewww-bulk-last" class="postbox">
576
- <button type="button" class="handlediv button-link" aria-expanded="true">
577
  <span class="screen-reader-text"><?php esc_html_e( 'Click to toggle', 'ewww-image-optimizer' ); ?></span>
578
  <span class="toggle-indicator" aria-hidden="true"></span>
579
  </button>
580
- <h2 class="hndle"><span><?php esc_html_e( 'Last Image Optimized', 'ewww-image-optimizer' ); ?></span></h2>
581
  <div class="inside"></div>
582
  </div>
583
  </div>
584
  <div class="meta-box-sortables">
585
  <div id="ewww-bulk-status" class="postbox">
586
- <button type="button" class="handlediv button-link" aria-expanded="true">
587
  <span class="screen-reader-text"><?php esc_html_e( 'Click to toggle', 'ewww-image-optimizer' ); ?></span>
588
  <span class="toggle-indicator" aria-hidden="true"></span>
589
  </button>
590
- <h2 class="hndle"><span><?php esc_html_e( 'Optimization Log', 'ewww-image-optimizer' ); ?></span></h2>
591
  <div class="inside"></div>
592
  </div>
593
  </div>
@@ -603,27 +677,24 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
603
  <form id="ewww-bulk-start" class="ewww-bulk-form" method="post" action="">
604
  <input type="submit" class="button-secondary action" value="<?php echo $button_text; ?>" />
605
  </form>
 
 
 
 
 
 
 
 
 
 
606
  <?php
607
- // If there is a previous bulk operation to resume, give the user the option to reset the resume flag.
608
- if ( ! empty( $resume ) ) {
609
- ?>
610
- <p class="ewww-bulk-info"><?php esc_html_e( 'If you would like to start over again, press the Reset Status button to reset the bulk operation status.', 'ewww-image-optimizer' ); ?></p>
611
- <form id="ewww-bulk-reset" class="ewww-bulk-form" method="post" action="">
612
- <?php wp_nonce_field( 'ewww-image-optimizer-bulk-reset', 'ewww_wpnonce' ); ?>
613
- <input type="hidden" name="ewww_reset" value="1">
614
- <input type="submit" class="button-secondary action" value="<?php esc_attr_e( 'Reset Status', 'ewww-image-optimizer' ); ?>" />
615
- </form>
616
- <?php
617
- }
618
- echo '</div></div>';
619
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
620
- global $ewww_debug;
621
- echo '<div style="background-color:#ffff99;">' . $ewww_debug . '</div>';
622
- }
623
- if ( ! empty( $_REQUEST['ewww_inline'] ) ) {
624
- wp_die();
625
- }
626
- return;
627
  }
628
 
629
  /**
@@ -631,6 +702,14 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
631
  */
632
  function ewww_ngg_style_remove() {
633
  wp_deregister_style( 'jquery-ui-nextgen' );
 
 
 
 
 
 
 
 
634
  }
635
 
636
  /**
@@ -641,13 +720,16 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
641
  * @param string $hook Identifier for the page being loaded.
642
  */
643
  function ewww_ngg_bulk_script( $hook ) {
644
- if ( strpos( $hook, 'ewww-ngg-bulk' ) === false && strpos( $hook, 'nggallery-manage-gallery' ) === false ) {
 
 
 
645
  return;
646
  }
647
- if ( strpos( $hook, 'nggallery-manage-gallery' ) && ( empty( $_REQUEST['bulkaction'] ) || 'bulk_optimize' != $_REQUEST['bulkaction'] ) ) {
648
  return;
649
  }
650
- if ( strpos( $hook, 'nggallery-manage-gallery' ) && ( empty( $_REQUEST['doaction'] ) || ! is_array( $_REQUEST['doaction'] ) ) ) {
651
  return;
652
  }
653
  $images = null;
@@ -659,23 +741,26 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
659
  $resume = get_option( 'ewww_image_optimizer_bulk_ngg_resume' );
660
  // If we've been given a bulk action to perform.
661
  if ( ! empty( $_REQUEST['doaction'] ) ) {
662
-
663
  // If we are optimizing a specific group of images.
664
- if ( 'manage-images' == $_REQUEST['page'] && 'bulk_optimize' == $_REQUEST['bulkaction'] ) {
 
665
  check_admin_referer( 'ngg_updategallery' );
666
  // Reset the resume status, not allowed here.
667
  update_option( 'ewww_image_optimizer_bulk_ngg_resume', '' );
668
  // Retrieve the image IDs from POST.
669
  $images = array_map( 'intval', $_REQUEST['doaction'] );
 
670
  }
671
  // If we are optimizing a specific group of galleries.
672
- if ( 'manage-galleries' == $_REQUEST['page'] && 'bulk_optimize' == $_REQUEST['bulkaction'] ) {
 
673
  check_admin_referer( 'ngg_bulkgallery' );
674
  global $nggdb;
675
  // Reset the resume status, not allowed here.
676
  update_option( 'ewww_image_optimizer_bulk_ngg_resume', '' );
677
  $ids = array();
678
  $gids = array_map( 'intval', $_REQUEST['doaction'] );
 
679
  // For each gallery we are given.
680
  foreach ( $gids as $gid ) {
681
  // Get a list of IDs.
@@ -686,6 +771,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
686
  $images[] = $image->pid;
687
  }
688
  }
 
689
  }
690
  } elseif ( ! empty( $resume ) ) {
691
  // Otherwise, if we have an operation to resume...
@@ -703,6 +789,14 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
703
  // Replacing the built-in nextgen styling rules for progressbar, partially because the bulk optimize page doesn't work without them.
704
  wp_deregister_style( 'ngg-jqueryui' );
705
  wp_deregister_style( 'ngg-jquery-ui' );
 
 
 
 
 
 
 
 
706
  add_action( 'admin_head', array( &$this, 'ewww_ngg_style_remove' ) );
707
  wp_register_style( 'jquery-ui-nextgen', plugins_url( '/includes/jquery-ui-1.10.1.custom.css', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ) );
708
  // Enqueue the progressbar styling.
@@ -823,7 +917,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
823
  $output['results'] = sprintf( '<p>' . esc_html__( 'Optimized image:', 'ewww-image-optimizer' ) . ' <strong>%s</strong><br>', esc_html( basename( $storage->object->get_image_abspath( $image, 'full' ) ) ) );
824
  // Get an array of sizes available for the $image.
825
  $sizes = $storage->get_image_sizes();
826
- // Run the optimizer on the image for each $size.
827
  if ( ewww_image_optimizer_iterable( $sizes ) ) {
828
  foreach ( $sizes as $size ) {
829
  if ( 'full' === $size ) {
@@ -894,6 +988,42 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
894
  </script>
895
  <?php
896
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
897
  }
898
  // Initialize the plugin and the class.
899
  global $ewwwngg;
22
  */
23
  public function __construct() {
24
  add_filter( 'ngg_manage_images_number_of_columns', array( $this, 'ewww_manage_images_number_of_columns' ) );
25
+ add_filter( 'ngg_manage_images_columns', array( $this, 'manage_images_columns' ) );
26
  add_filter( 'ngg_manage_images_row_actions', array( $this, 'ewww_manage_images_row_actions' ) );
27
  if ( ewww_image_optimizer_test_background_opt() ) {
28
  add_action( 'ngg_added_new_image', array( $this, 'queue_new_image' ) );
36
  add_action( 'admin_action_ewww_ngg_manual', array( $this, 'ewww_ngg_manual' ) );
37
  add_action( 'admin_enqueue_scripts', array( $this, 'ewww_ngg_manual_actions_script' ) );
38
  add_action( 'admin_menu', array( $this, 'ewww_ngg_bulk_menu' ) );
39
+ add_action( 'admin_menu', array( $this, 'ewww_ngg_update_menu' ), PHP_INT_MAX - 1 );
40
  add_action( 'admin_head', array( $this, 'ewww_ngg_bulk_actions_script' ) );
41
+ add_action( 'admin_init', array( $this, 'ewww_ngg_bulk_action_handler' ) );
42
  add_action( 'admin_enqueue_scripts', array( $this, 'ewww_ngg_bulk_script' ), 20 );
43
  add_action( 'wp_ajax_bulk_ngg_preview', array( $this, 'ewww_ngg_bulk_preview' ) );
44
  add_action( 'wp_ajax_bulk_ngg_init', array( $this, 'ewww_ngg_bulk_init' ) );
46
  add_action( 'wp_ajax_bulk_ngg_loop', array( $this, 'ewww_ngg_bulk_loop' ) );
47
  add_action( 'wp_ajax_bulk_ngg_cleanup', array( $this, 'ewww_ngg_bulk_cleanup' ) );
48
  add_action( 'ngg_generated_image', array( $this, 'ewww_ngg_generated_image' ), 10, 2 );
49
+ add_filter( 'ngg_get_image_size_params', array( $this, 'ewww_ngg_quality_param' ), 10, 2 );
50
  }
51
 
52
  /**
56
  if ( ! defined( 'NGGFOLDER' ) ) {
57
  return;
58
  }
59
+ add_submenu_page( NGGFOLDER, esc_html__( 'Bulk Optimize', 'ewww-image-optimizer' ), esc_html__( 'Bulk Optimize', 'ewww-image-optimizer' ), apply_filters( 'ewww_image_optimizer_bulk_permissions', '' ), 'ewww-ngg-bulk', array( &$this, 'ewww_ngg_bulk_preview' ) );
60
+ remove_submenu_page( 'nextgen-gallery', 'ngg_imagify' );
61
+ }
62
+
63
+ /**
64
+ * Removes unnecessary menu items from the NextGEN menu.
65
+ */
66
+ function ewww_ngg_update_menu() {
67
+ if ( ! defined( 'NGGFOLDER' ) ) {
68
+ return;
69
+ }
70
+ remove_submenu_page( NGGFOLDER, 'ngg_imagify' );
71
+ }
72
+
73
+ /**
74
+ * Keep the NextGEN quality level sane and inline with user settings.
75
+ *
76
+ * @param array $params The image sizing parameters.
77
+ * @param string $size The name of the size being processed.
78
+ * @return array The image sizing parameters, sanitized.
79
+ */
80
+ function ewww_ngg_quality_param( $params, $size ) {
81
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
82
+ $settings = C_NextGen_Settings::get_instance();
83
+ if ( is_array( $params ) ) {
84
+ ewwwio_debug_message( 'params is an array' );
85
+ if ( ! empty( $params['quality'] ) && 100 == $params['quality'] ) {
86
+ $wp_quality = (int) apply_filters( 'jpeg_quality', 82, 'image_resize' );
87
+ // If the size is full and the WP default has not been altered, go for higher quality. Otherwise, obey the current WP setting.
88
+ $params['quality'] = 'full' === $size && 82 === $wp_quality ? 90 : $wp_quality;
89
+ ewwwio_debug_message( "setting quality for ngg to {$params['quality']} for $size" );
90
+ }
91
+ }
92
+ if ( empty( $params ) || empty( $params['quality'] ) ) {
93
+ $wp_quality = (int) apply_filters( 'jpeg_quality', 82, 'image_resize' );
94
+ if ( 'full' === $size ) {
95
+ $ngg_quality = (int) $settings->imgQuality;
96
+ } else {
97
+ $ngg_quality = (int) $settings->thumbquality;
98
+ }
99
+ if ( empty( $ngg_quality ) || 100 === $ngg_quality ) {
100
+ $params['quality'] = 'full' === $size && 82 === $wp_quality ? 90 : $wp_quality;
101
+ ewwwio_debug_message( "setting quality for ngg to {$params['quality']} for $size" );
102
+ }
103
+ }
104
+ return $params;
105
+ }
106
+
107
+ /**
108
+ * Looks for more sizes to optimize in the image metadata.
109
+ *
110
+ * @param array $sizes The image sizes NextGEN gave us.
111
+ * @param array $meta The image metadata from NextGEN.
112
+ * @return array The full list of known image sizes for this image.
113
+ */
114
+ function maybe_get_more_sizes( $sizes, $meta ) {
115
+ if ( 2 == count( $sizes ) && ewww_image_optimizer_iterable( $meta ) ) {
116
+ foreach ( $meta as $meta_key => $meta_val ) {
117
+ if ( 0 === strpos( $meta_key, 'ngg0dyn-' ) && is_array( $meta_val ) && ! empty( $meta_val['filename'] ) ) {
118
+ $sizes[] = $meta_key;
119
+ }
120
+ }
121
+ }
122
+ return $sizes;
123
  }
124
 
125
  /**
187
  ewwwio_debug_message( "image id: $image_id" );
188
  // Get an array of sizes available for the $image.
189
  $sizes = $storage->get_image_sizes();
190
+ $sizes = $this->maybe_get_more_sizes( $sizes, $image->meta_data );
191
  // Run the optimizer on the image for each $size.
192
  if ( ewww_image_optimizer_iterable( $sizes ) ) {
193
  foreach ( $sizes as $size ) {
198
  }
199
  // Get the absolute path.
200
  $file_path = $storage->get_image_abspath( $image, $size );
201
+ ewwwio_debug_message( "optimizing (nextgen) $size: $file_path" );
202
  $ewww_image = new EWWW_Image( $image_id, 'nextgen', $file_path );
203
  $ewww_image->resize = $size;
204
  // Optimize the image and grab the results.
211
  } else {
212
  $image->meta_data[ $size ]['ewww_image_optimizer'] = $res[1];
213
  }
 
 
214
  }
215
  }
216
+ ewwwio_debug_message( 'storing results for image' );
217
+ nggdb::update_image_meta( $image_id, $image->meta_data );
218
  return $image;
219
  }
220
 
385
  );
386
  }
387
 
388
+ /**
389
+ * Adds our column to the list for users to toggle via Screen Options.
390
+ *
391
+ * @param array $columns A list of existing column names.
392
+ * @return array The revised list of column names.
393
+ */
394
+ function manage_images_columns( $columns ) {
395
+ if ( is_array( $columns ) ) {
396
+ $columns['ewww_image_optimizer'] = esc_html__( 'Image Optimizer', 'ewww-image-optimizer' );
397
+ }
398
+ return $columns;
399
+ }
400
+
401
  /**
402
  * Filter for ngg_manage_images_number_of_columns hook, changed in NGG 2.0.50ish.
403
  *
406
  */
407
  function ewww_manage_images_number_of_columns( $count ) {
408
  $count++;
409
+ add_filter( "ngg_manage_images_column_{$count}_header", array( $this, 'ewww_manage_images_columns' ) );
410
+ add_filter( "ngg_manage_images_column_{$count}_content", array( $this, 'ewww_manage_image_custom_column' ), 10, 2 );
411
  return $count;
412
  }
413
 
421
  if ( is_array( $columns ) ) {
422
  $columns['ewww_image_optimizer'] = esc_html__( 'Image Optimizer', 'ewww-image-optimizer' );
423
  return $columns;
 
 
424
  }
425
+ return esc_html__( 'Image Optimizer', 'ewww-image-optimizer' );
426
  }
427
 
428
  /**
449
  }
450
  $output = "<div id='ewww-nextgen-status-$image->pid'>";
451
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) && ewww_image_optimizer_function_exists( 'print_r' ) ) {
452
+ $print_meta = print_r( $image->meta_data, true );
453
+ $print_meta = preg_replace( array( '/ /', '/\n+/' ), array( '&nbsp;', '<br />' ), esc_html( $print_meta ) );
454
+ $debug_button = esc_html__( 'Show Metadata', 'ewww-image-optimizer' );
455
+ $output .= "<button type='button' class='ewww-show-debug-meta button button-secondary' data-id='{$image->pid}' style='background-color:#a9c524;'>$debug_button</button><div id='ewww-debug-meta-{$image->pid}' style='background-color:#ffff99;font-size: 10px;padding: 10px;margin:3px -10px 10px;line-height: 1.1em;display: none;'>$print_meta</div>";
456
  }
457
  $msg = '';
458
  // Get the absolute path.
502
  // If we have metadata, populate db from meta.
503
  if ( ! empty( $image->meta_data['ewww_image_optimizer'] ) ) {
504
  $sizes = $storage->get_image_sizes();
505
+ $sizes = $this->maybe_get_more_sizes( $sizes, $image->meta_data );
506
  if ( ewww_image_optimizer_iterable( $sizes ) ) {
507
  foreach ( $sizes as $size ) {
508
  if ( 'full' === $size ) {
609
  return;
610
  }
611
  // If there is no media to optimize, do nothing.
612
+ if ( ! is_array( $_REQUEST['doaction'] ) ) {
613
  return;
614
  }
615
  }
619
  echo '<p>' . esc_html__( 'You do not appear to have uploaded any images yet.', 'ewww-image-optimizer' ) . '</p>';
620
  return;
621
  }
 
 
 
 
 
 
 
 
 
622
  ?>
623
+ <div class="wrap">
624
  <h1><?php esc_html_e( 'Bulk Optimize', 'ewww-image-optimizer' ); ?></h1>
625
  <?php
626
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
647
  <div id="ewww-bulk-widgets" class="metabox-holder" style="display:none">
648
  <div class="meta-box-sortables">
649
  <div id="ewww-bulk-last" class="postbox">
650
+ <button type="button" class="ewww-handlediv button-link" aria-expanded="true">
651
  <span class="screen-reader-text"><?php esc_html_e( 'Click to toggle', 'ewww-image-optimizer' ); ?></span>
652
  <span class="toggle-indicator" aria-hidden="true"></span>
653
  </button>
654
+ <h2 class="ewww-hndle"><span><?php esc_html_e( 'Last Image Optimized', 'ewww-image-optimizer' ); ?></span></h2>
655
  <div class="inside"></div>
656
  </div>
657
  </div>
658
  <div class="meta-box-sortables">
659
  <div id="ewww-bulk-status" class="postbox">
660
+ <button type="button" class="ewww-handlediv button-link" aria-expanded="true">
661
  <span class="screen-reader-text"><?php esc_html_e( 'Click to toggle', 'ewww-image-optimizer' ); ?></span>
662
  <span class="toggle-indicator" aria-hidden="true"></span>
663
  </button>
664
+ <h2 class="ewww-hndle"><span><?php esc_html_e( 'Optimization Log', 'ewww-image-optimizer' ); ?></span></h2>
665
  <div class="inside"></div>
666
  </div>
667
  </div>
677
  <form id="ewww-bulk-start" class="ewww-bulk-form" method="post" action="">
678
  <input type="submit" class="button-secondary action" value="<?php echo $button_text; ?>" />
679
  </form>
680
+ <?php
681
+ // If there is a previous bulk operation to resume, give the user the option to reset the resume flag.
682
+ if ( ! empty( $resume ) ) {
683
+ ?>
684
+ <p class="ewww-bulk-info"><?php esc_html_e( 'If you would like to start over again, press the Reset Status button to reset the bulk operation status.', 'ewww-image-optimizer' ); ?></p>
685
+ <form id="ewww-bulk-reset" class="ewww-bulk-form" method="post" action="">
686
+ <?php wp_nonce_field( 'ewww-image-optimizer-bulk-reset', 'ewww_wpnonce' ); ?>
687
+ <input type="hidden" name="ewww_reset" value="1">
688
+ <input type="submit" class="button-secondary action" value="<?php esc_attr_e( 'Reset Status', 'ewww-image-optimizer' ); ?>" />
689
+ </form>
690
  <?php
691
+ }
692
+ echo '</div></div>';
693
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
694
+ global $ewww_debug;
695
+ echo '<p><strong>' . esc_html__( 'Debugging Information', 'ewww-image-optimizer' ) . ':</strong></p><div style="background-color:#ffff99;">' . $ewww_debug . '</div>';
696
+ }
697
+ return;
 
 
 
 
 
 
 
 
 
 
 
 
 
698
  }
699
 
700
  /**
702
  */
703
  function ewww_ngg_style_remove() {
704
  wp_deregister_style( 'jquery-ui-nextgen' );
705
+ wp_deregister_style( 'ngg_progressbar' );
706
+ wp_deregister_style( 'nextgen_admin_css' );
707
+ wp_deregister_style( 'pc-autoupdate-admin' );
708
+ wp_deregister_script( 'nextgen_admin_js_atp' );
709
+ wp_deregister_script( 'nextgen_admin_js' );
710
+ wp_deregister_script( 'ngg_progressbar' );
711
+ wp_deregister_script( 'frame_event_publisher' );
712
+ wp_deregister_script( 'pc-autoupdate-admin' );
713
  }
714
 
715
  /**
720
  * @param string $hook Identifier for the page being loaded.
721
  */
722
  function ewww_ngg_bulk_script( $hook ) {
723
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
724
+ ewwwio_debug_message( $hook );
725
+ /* if ( strpos( $hook, 'ewww-ngg-bulk' ) === false && strpos( $hook, 'nggallery-manage-gallery' ) === false ) { */
726
+ if ( strpos( $hook, 'ewww-ngg-bulk' ) === false ) {
727
  return;
728
  }
729
+ if ( ! empty( $_REQUEST['bulkaction'] ) && 'bulk_optimize' != $_REQUEST['bulkaction'] ) {
730
  return;
731
  }
732
+ if ( ! empty( $_REQUEST['doaction'] ) && ! is_array( $_REQUEST['doaction'] ) ) {
733
  return;
734
  }
735
  $images = null;
741
  $resume = get_option( 'ewww_image_optimizer_bulk_ngg_resume' );
742
  // If we've been given a bulk action to perform.
743
  if ( ! empty( $_REQUEST['doaction'] ) ) {
 
744
  // If we are optimizing a specific group of images.
745
+ if ( 'images' == $_REQUEST['bulk_type'] && 'bulk_optimize' == $_REQUEST['bulkaction'] ) {
746
+ ewwwio_debug_message( 'detected bulk action from manage images' );
747
  check_admin_referer( 'ngg_updategallery' );
748
  // Reset the resume status, not allowed here.
749
  update_option( 'ewww_image_optimizer_bulk_ngg_resume', '' );
750
  // Retrieve the image IDs from POST.
751
  $images = array_map( 'intval', $_REQUEST['doaction'] );
752
+ ewwwio_debug_message( 'requested images: ' . implode( ',', $images ) );
753
  }
754
  // If we are optimizing a specific group of galleries.
755
+ if ( 'galleries' == $_REQUEST['bulk_type'] && 'bulk_optimize' == $_REQUEST['bulkaction'] ) {
756
+ ewwwio_debug_message( 'detected bulk action from manage galleries' );
757
  check_admin_referer( 'ngg_bulkgallery' );
758
  global $nggdb;
759
  // Reset the resume status, not allowed here.
760
  update_option( 'ewww_image_optimizer_bulk_ngg_resume', '' );
761
  $ids = array();
762
  $gids = array_map( 'intval', $_REQUEST['doaction'] );
763
+ ewwwio_debug_message( 'requested galleries: ' . implode( ',', $gids ) );
764
  // For each gallery we are given.
765
  foreach ( $gids as $gid ) {
766
  // Get a list of IDs.
771
  $images[] = $image->pid;
772
  }
773
  }
774
+ ewwwio_debug_message( 'requested images: ' . implode( ',', $images ) );
775
  }
776
  } elseif ( ! empty( $resume ) ) {
777
  // Otherwise, if we have an operation to resume...
789
  // Replacing the built-in nextgen styling rules for progressbar, partially because the bulk optimize page doesn't work without them.
790
  wp_deregister_style( 'ngg-jqueryui' );
791
  wp_deregister_style( 'ngg-jquery-ui' );
792
+ wp_deregister_style( 'ngg_progressbar' );
793
+ wp_deregister_style( 'nextgen_admin_css' );
794
+ wp_deregister_style( 'pc-autoupdate-admin' );
795
+ wp_deregister_script( 'nextgen_admin_js_atp' );
796
+ wp_deregister_script( 'nextgen_admin_js' );
797
+ wp_deregister_script( 'ngg_progressbar' );
798
+ wp_deregister_script( 'frame_event_publisher' );
799
+ wp_deregister_script( 'pc-autoupdate-admin' );
800
  add_action( 'admin_head', array( &$this, 'ewww_ngg_style_remove' ) );
801
  wp_register_style( 'jquery-ui-nextgen', plugins_url( '/includes/jquery-ui-1.10.1.custom.css', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ) );
802
  // Enqueue the progressbar styling.
917
  $output['results'] = sprintf( '<p>' . esc_html__( 'Optimized image:', 'ewww-image-optimizer' ) . ' <strong>%s</strong><br>', esc_html( basename( $storage->object->get_image_abspath( $image, 'full' ) ) ) );
918
  // Get an array of sizes available for the $image.
919
  $sizes = $storage->get_image_sizes();
920
+ $sizes = $this->maybe_get_more_sizes( $sizes, $image->meta_data );
921
  if ( ewww_image_optimizer_iterable( $sizes ) ) {
922
  foreach ( $sizes as $size ) {
923
  if ( 'full' === $size ) {
988
  </script>
989
  <?php
990
  }
991
+
992
+ /**
993
+ * Handles the bulk actions POST.
994
+ */
995
+ function ewww_ngg_bulk_action_handler() {
996
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
997
+ // If the requested page is blank, or not a bulk_optimize, do nothing.
998
+ if ( empty( $_REQUEST['page'] ) || empty( $_REQUEST['bulkaction'] ) || 'bulk_optimize' != $_REQUEST['bulkaction'] ) {
999
+ return;
1000
+ }
1001
+ // If there is no media to optimize, do nothing.
1002
+ if ( empty( $_REQUEST['doaction'] ) || ! is_array( $_REQUEST['doaction'] ) ) {
1003
+ return;
1004
+ }
1005
+ // If the requested page does not matche, do nothing.
1006
+ if ( 'manage-galleries' !== $_REQUEST['page'] && 'manage-images' != $_REQUEST['page'] ) {
1007
+ return;
1008
+ }
1009
+
1010
+ $type = 'images';
1011
+ if ( 'manage-galleries' === $_REQUEST['page'] ) {
1012
+ $type = 'galleries';
1013
+ }
1014
+ wp_redirect( add_query_arg(
1015
+ array(
1016
+ 'page' => 'ewww-ngg-bulk',
1017
+ '_wpnonce' => $_REQUEST['_wpnonce'],
1018
+ 'bulk_type' => $type,
1019
+ 'bulkaction' => 'bulk_optimize',
1020
+ 'doaction' => $_REQUEST['doaction'],
1021
+ ),
1022
+ admin_url( 'admin.php' )
1023
+ ) );
1024
+ ewwwio_memory( __FUNCTION__ );
1025
+ exit();
1026
+ }
1027
  }
1028
  // Initialize the plugin and the class.
1029
  global $ewwwngg;
classes/class-ewwwio-alt-webp.php ADDED
@@ -0,0 +1,699 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Implements WebP rewriting using page parsing and JS functionality.
4
+ *
5
+ * @link https://ewww.io
6
+ * @package EWWW_Image_Optimizer
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ /**
14
+ * Enables EWWW IO to filter the page content and replace img elements with WebP markup.
15
+ */
16
+ class EWWWIO_Alt_Webp extends EWWWIO_Page_Parser {
17
+
18
+ /**
19
+ * The Alt WebP inline script contents. Current length 12696.
20
+ *
21
+ * @access private
22
+ * @var string $inline_script
23
+ */
24
+ private $inline_script = 'var Arrive=function(d,t,c){"use strict";if(d.MutationObserver&&"undefined"!=typeof HTMLElement){var a,e,i=0,u=(a=HTMLElement.prototype.matches||HTMLElement.prototype.webkitMatchesSelector||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelector,{matchesSelector:function(t,e){return t instanceof HTMLElement&&a.call(t,e)},addMethod:function(t,e,a){var i=t[e];t[e]=function(){return a.length==arguments.length?a.apply(this,arguments):"function"==typeof i?i.apply(this,arguments):void 0}},callCallbacks:function(t){for(var e,a=0;e=t[a];a++)e.callback.call(e.elem)},checkChildNodesRecursively:function(t,e,a,i){for(var r,n=0;r=t[n];n++)a(r,e,i)&&i.push({callback:e.callback,elem:r}),0<r.childNodes.length&&u.checkChildNodesRecursively(r.childNodes,e,a,i)},mergeArrays:function(t,e){var a,i={};for(a in t)i[a]=t[a];for(a in e)i[a]=e[a];return i},toElementsArray:function(t){return void 0===t||"number"==typeof t.length&&t!==d||(t=[t]),t}}),h=((e=function(){this._eventsBucket=[],this._beforeAdding=null,this._beforeRemoving=null}).prototype.addEvent=function(t,e,a,i){var r={target:t,selector:e,options:a,callback:i,firedElems:[]};return this._beforeAdding&&this._beforeAdding(r),this._eventsBucket.push(r),r},e.prototype.removeEvent=function(t){for(var e,a=this._eventsBucket.length-1;e=this._eventsBucket[a];a--)t(e)&&(this._beforeRemoving&&this._beforeRemoving(e),this._eventsBucket.splice(a,1))},e.prototype.beforeAdding=function(t){this._beforeAdding=t},e.prototype.beforeRemoving=function(t){this._beforeRemoving=t},e),s=function(r,n){var s=new h,o=this,l={fireOnAttributesModification:!1};return s.beforeAdding(function(e){var t,a=e.target;e.selector,e.callback;a!==d.document&&a!==d||(a=document.getElementsByTagName("html")[0]),t=new MutationObserver(function(t){n.call(this,t,e)});var i=r(e.options);t.observe(a,i),e.observer=t,e.me=o}),s.beforeRemoving(function(t){t.observer.disconnect()}),this.bindEvent=function(t,e,a){e=u.mergeArrays(l,e);for(var i=u.toElementsArray(this),r=0;r<i.length;r++)s.addEvent(i[r],t,e,a)},this.unbindEvent=function(){var a=u.toElementsArray(this);s.removeEvent(function(t){for(var e=0;e<a.length;e++)if(this===c||t.target===a[e])return!0;return!1})},this.unbindEventWithSelectorOrCallback=function(a){var t,i=u.toElementsArray(this),r=a;t="function"==typeof a?function(t){for(var e=0;e<i.length;e++)if((this===c||t.target===i[e])&&t.callback===r)return!0;return!1}:function(t){for(var e=0;e<i.length;e++)if((this===c||t.target===i[e])&&t.selector===a)return!0;return!1},s.removeEvent(t)},this.unbindEventWithSelectorAndCallback=function(a,i){var r=u.toElementsArray(this);s.removeEvent(function(t){for(var e=0;e<r.length;e++)if((this===c||t.target===r[e])&&t.selector===a&&t.callback===i)return!0;return!1})},this},r=new function(){var l={fireOnAttributesModification:!1,onceOnly:!1,existing:!1};function n(t,e,a){if(u.matchesSelector(t,e.selector)&&(t._id===c&&(t._id=i++),-1==e.firedElems.indexOf(t._id))){if(e.options.onceOnly){if(0!==e.firedElems.length)return;e.me.unbindEventWithSelectorAndCallback.call(e.target,e.selector,e.callback)}e.firedElems.push(t._id),a.push({callback:e.callback,elem:t})}}var d=(r=new s(function(t){var e={attributes:!1,childList:!0,subtree:!0};return t.fireOnAttributesModification&&(e.attributes=!0),e},function(t,r){t.forEach(function(t){var e=t.addedNodes,a=t.target,i=[];null!==e&&0<e.length?u.checkChildNodesRecursively(e,r,n,i):"attributes"===t.type&&n(a,r,i)&&i.push({callback:r.callback,elem:node}),u.callCallbacks(i)})})).bindEvent;return r.bindEvent=function(t,e,a){void 0===a?(a=e,e=l):e=u.mergeArrays(l,e);var i=u.toElementsArray(this);if(e.existing){for(var r=[],n=0;n<i.length;n++)for(var s=i[n].querySelectorAll(t),o=0;o<s.length;o++)r.push({callback:a,elem:s[o]});if(e.onceOnly&&r.length)return a.call(r[0].elem);setTimeout(u.callCallbacks,1,r)}d.call(this,t,e,a)},r},o=new function(){var i={};function r(t,e){return u.matchesSelector(t,e.selector)}var n=(o=new s(function(t){return{childList:!0,subtree:!0}},function(t,i){t.forEach(function(t){var e=t.removedNodes,a=(t.target,[]);null!==e&&0<e.length&&u.checkChildNodesRecursively(e,i,r,a),u.callCallbacks(a)})})).bindEvent;return o.bindEvent=function(t,e,a){void 0===a?(a=e,e=i):e=u.mergeArrays(i,e),n.call(this,t,e,a)},o};t&&g(t.fn),g(HTMLElement.prototype),g(NodeList.prototype),g(HTMLCollection.prototype),g(HTMLDocument.prototype),g(Window.prototype);var n={};return l(r,n,"unbindAllArrive"),l(o,n,"unbindAllLeave"),n}function l(t,e,a){u.addMethod(e,a,t.unbindEvent),u.addMethod(e,a,t.unbindEventWithSelectorOrCallback),u.addMethod(e,a,t.unbindEventWithSelectorAndCallback)}function g(t){t.arrive=r.bindEvent,l(r,t,"unbindArrive"),t.leave=o.bindEvent,l(o,t,"unbindLeave")}}(window,"undefined"==typeof jQuery?null:jQuery,void 0);function check_webp_feature(t,e){var a=new Image;a.onload=function(){var t=0<a.width&&0<a.height;!0,e(t)},a.onerror=function(){e(!1)},a.src="data:image/webp;base64,"+{alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"}[t]}function ewww_load_images(i){jQuery(document).arrive(".ewww_webp",function(){ewww_load_images(i)}),function(s){function a(t,e){for(var a=["align","alt","border","crossorigin","height","hspace","ismap","longdesc","usemap","vspace","width","accesskey","class","contenteditable","contextmenu","dir","draggable","dropzone","hidden","id","lang","spellcheck","style","tabindex","title","translate","sizes","data-caption","data-attachment-id","data-permalink","data-orig-size","data-comments-opened","data-image-meta","data-image-title","data-image-description","data-event-trigger","data-highlight-color","data-highlight-opacity","data-highlight-border-color","data-highlight-border-width","data-highlight-border-opacity","data-no-lazy","data-lazy","data-large_image_width","data-large_image_height"],i=0,r=a.length;i<r;i++){var n=s(t).attr("data-"+a[i]);void 0!==n&&!1!==n&&s(e).attr(a[i],n)}return e}i&&(s(".batch-image img, .image-wrapper a, .ngg-pro-masonry-item a, .ngg-galleria-offscreen-seo-wrapper a").each(function(){var t;void 0!==(t=s(this).attr("data-webp"))&&!1!==t&&s(this).attr("data-src",t),void 0!==(t=s(this).attr("data-webp-thumbnail"))&&!1!==t&&s(this).attr("data-thumbnail",t)}),s(".image-wrapper a, .ngg-pro-masonry-item a").each(function(){var t=s(this).attr("data-webp");void 0!==t&&!1!==t&&s(this).attr("href",t)}),s(".rev_slider ul li").each(function(){void 0!==(e=s(this).attr("data-webp-thumb"))&&!1!==e&&s(this).attr("data-thumb",e);for(var t=1;t<11;){var e;void 0!==(e=s(this).attr("data-webp-param"+t))&&!1!==e&&s(this).attr("data-param"+t,e),t++}}),s(".rev_slider img").each(function(){var t=s(this).attr("data-webp-lazyload");void 0!==t&&!1!==t&&s(this).attr("data-lazyload",t)}),s("div.woocommerce-product-gallery__image").each(function(){var t=s(this).attr("data-webp-thumb");void 0!==t&&!1!==t&&s(this).attr("data-thumb",t)})),s("img.ewww_webp_lazy_retina").each(function(){var t;i?void 0!==(t=s(this).attr("data-srcset-webp"))&&!1!==t&&s(this).attr("data-srcset",t):void 0!==(t=s(this).attr("data-srcset-img"))&&!1!==t&&s(this).attr("data-srcset",t);s(this).removeClass("ewww_webp_lazy_retina")}),s("video").each(function(){var t;i?void 0!==(t=s(this).attr("data-poster-webp"))&&!1!==t&&s(this).attr("poster",t):void 0!==(t=s(this).attr("data-poster-image"))&&!1!==t&&s(this).attr("poster",t)}),s("img.ewww_webp_lazy_load").each(function(){var t;i?(s(this).attr("data-lazy-src",s(this).attr("data-lazy-webp-src")),void 0!==(t=s(this).attr("data-srcset-webp"))&&!1!==t&&s(this).attr("srcset",t),void 0!==(t=s(this).attr("data-lazy-srcset-webp"))&&!1!==t&&s(this).attr("data-lazy-srcset",t)):(s(this).attr("data-lazy-src",s(this).attr("data-lazy-img-src")),void 0!==(t=s(this).attr("data-srcset"))&&!1!==t&&s(this).attr("srcset",t),void 0!==(t=s(this).attr("data-lazy-srcset-img"))&&!1!==t&&s(ewww_img).attr("data-lazy-srcset",t));s(this).removeClass("ewww_webp_lazy_load")}),s(".ewww_webp_lazy_hueman").each(function(){var t,e=document.createElement("img");(s(e).attr("src",s(this).attr("data-src")),i)?(s(e).attr("data-src",s(this).attr("data-webp-src")),void 0!==(t=s(this).attr("data-srcset-webp"))&&!1!==t&&s(e).attr("data-srcset",t)):(s(e).attr("data-src",s(this).attr("data-img")),void 0!==(t=s(this).attr("data-srcset-img"))&&!1!==t&&s(e).attr("data-srcset",t));e=a(this,e),s(this).after(e),s(this).removeClass("ewww_webp_lazy_hueman")}),s(".ewww_webp").each(function(){var t=document.createElement("img");if(i){if(s(t).attr("src",s(this).attr("data-webp")),void 0!==(e=s(this).attr("data-srcset-webp"))&&!1!==e&&s(t).attr("srcset",e),void 0!==(e=s(this).attr("data-webp-orig-file"))&&!1!==e)s(t).attr("data-orig-file",e);else void 0!==(e=s(this).attr("data-orig-file"))&&!1!==e&&s(t).attr("data-orig-file",e);if(void 0!==(e=s(this).attr("data-webp-medium-file"))&&!1!==e)s(t).attr("data-medium-file",e);else void 0!==(e=s(this).attr("data-medium-file"))&&!1!==e&&s(t).attr("data-medium-file",e);if(void 0!==(e=s(this).attr("data-webp-large-file"))&&!1!==e)s(t).attr("data-large-file",e);else void 0!==(e=s(this).attr("data-large-file"))&&!1!==e&&s(t).attr("data-large-file",e);if(void 0!==(e=s(this).attr("data-webp-large_image"))&&!1!==e)s(t).attr("data-large_image",e);else void 0!==(e=s(this).attr("data-large_image"))&&!1!==e&&s(t).attr("data-large_image",e);if(void 0!==(e=s(this).attr("data-webp-src"))&&!1!==e)s(t).attr("data-src",e);else void 0!==(e=s(this).attr("data-src"))&&!1!==e&&s(t).attr("data-src",e)}else{var e;s(t).attr("src",s(this).attr("data-img")),void 0!==(e=s(this).attr("data-srcset-img"))&&!1!==e&&s(t).attr("srcset",e),void 0!==(e=s(this).attr("data-orig-file"))&&!1!==e&&s(t).attr("data-orig-file",e),void 0!==(e=s(this).attr("data-medium-file"))&&!1!==e&&s(t).attr("data-medium-file",e),void 0!==(e=s(this).attr("data-large-file"))&&!1!==e&&s(t).attr("data-large-file",e),void 0!==(e=s(this).attr("data-large_image"))&&!1!==e&&s(t).attr("data-large_image",e),void 0!==(e=s(this).attr("data-src"))&&!1!==e&&s(t).attr("data-src",e)}t=a(this,t),s(this).after(t),s(this).removeClass("ewww_webp")})}(jQuery),jQuery.fn.isotope&&jQuery.fn.imagesLoaded&&(jQuery(".fusion-posts-container-infinite").imagesLoaded(function(){jQuery(".fusion-posts-container-infinite").hasClass("isotope")&&jQuery(".fusion-posts-container-infinite").isotope()}),jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").imagesLoaded(function(){jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").isotope()}))}"undefined"!=typeof jQuery&&check_webp_feature("alpha",ewww_load_images);var ewww_ngg_galleries_timer=0,ewww_ngg_galleries=setInterval(function(){"undefined"!=typeof galleries&&"undefined"!=typeof jQuery&&(check_webp_feature("alpha",ewww_ngg_plus_parse_galleries),clearInterval(ewww_ngg_galleries)),1e3<(ewww_ngg_galleries_timer+=25)&&clearInterval(ewww_ngg_galleries)},25);function ewww_ngg_plus_parse_galleries(t){t&&jQuery.each(galleries,function(t,e){galleries[t].images_list=ewww_ngg_plus_parse_image_list(e.images_list)})}function ewww_ngg_plus_load_galleries(t){var r;t&&((r=jQuery)(window).on("ngg.galleria.themeadded",function(t,e){console.log(e),window.ngg_galleria._create_backup=window.ngg_galleria.create,window.ngg_galleria.create=function(t,e){var a=r(t).data("id");return console.log(a),galleries["gallery_"+a].images_list=ewww_ngg_plus_parse_image_list(galleries["gallery_"+a].images_list),window.ngg_galleria._create_backup(t,e)}}),r(window).on("override_nplModal_methods",function(t,i){i._set_events_backup=i.set_events,i.set_events=function(){return r("#npl_content").bind("npl_images_ready",function(t,e){var a=i.fetch_images.gallery_image_cache[e];a=ewww_ngg_plus_parse_image_list(a)}),i._set_events_backup()}}))}function ewww_ngg_plus_parse_image_list(r){var t;return(t=jQuery).each(r,function(a,i){void 0!==i["image-webp"]&&(r[a].image=i["image-webp"],delete r[a]["image-webp"]),void 0!==i["thumb-webp"]&&(r[a].thumb=i["thumb-webp"],delete r[a]["thumb-webp"]),void 0!==i.full_image_webp&&(r[a].full_image=i.full_image_webp,delete r[a].full_image_webp),void 0!==i.srcsets&&t.each(i.srcsets,function(t,e){void 0!==i.srcsets[t+"-webp"]&&(r[a].srcsets[t]=i.srcsets[t+"-webp"],delete r[a].srcsets[t+"-webp"])}),void 0!==i.full_srcsets&&t.each(i.full_srcsets,function(t,e){void 0!==i.full_srcsets[t+"-webp"]&&(r[a].full_srcsets[t]=i.full_srcsets[t+"-webp"],delete r[a].full_srcsets[t+"-webp"])})}),r}check_webp_feature("alpha",ewww_ngg_plus_load_galleries);';
25
+
26
+
27
+ /**
28
+ * Indicates if we are filtering ExactDN urls.
29
+ *
30
+ * @access protected
31
+ * @var bool $parsing_exactdn
32
+ */
33
+ protected $parsing_exactdn = false;
34
+
35
+ /**
36
+ * Allowed paths for "forced" WebP.
37
+ *
38
+ * @access protected
39
+ * @var array $webp_paths
40
+ */
41
+ protected $webp_paths = array();
42
+
43
+ /**
44
+ * Register (once) actions and filters for Alt WebP.
45
+ */
46
+ function __construct() {
47
+ global $ewwwio_alt_webp;
48
+ if ( is_object( $ewwwio_alt_webp ) ) {
49
+ return 'you are doing it wrong';
50
+ }
51
+ if ( ewww_image_optimizer_ce_webp_enabled() ) {
52
+ return false;
53
+ }
54
+ // Start an output buffer before any output starts.
55
+ add_action( 'template_redirect', array( $this, 'buffer_start' ), 0 );
56
+ // Filter for NextGEN image urls within JS.
57
+ add_filter( 'ngg_pro_lightbox_images_queue', array( $this, 'ngg_pro_lightbox_images_queue' ), 11 );
58
+
59
+ $this->home_url = trailingslashit( get_site_url() );
60
+ ewwwio_debug_message( "home url: $this->home_url" );
61
+ $this->relative_home_url = preg_replace( '/https?:/', '', $this->home_url );
62
+ ewwwio_debug_message( "relative home url: $this->relative_home_url" );
63
+
64
+ $this->webp_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' );
65
+ if ( ! is_array( $this->webp_paths ) ) {
66
+ $this->webp_paths = array();
67
+ }
68
+ ewwwio_debug_message( 'forcing any images matching these patterns to webp: ' . implode( ',', $this->webp_paths ) );
69
+ if ( class_exists( 'ExactDN' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
70
+ global $exactdn;
71
+ $this->exactdn_domain = $exactdn->get_exactdn_domain();
72
+ if ( $this->exactdn_domain ) {
73
+ $this->parsing_exactdn = true;
74
+ ewwwio_debug_message( 'parsing an exactdn page' );
75
+ }
76
+ }
77
+
78
+ // Load the appropriate JS.
79
+ if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
80
+ // Load the non-minified, non-inline version of the webp rewrite script.
81
+ add_action( 'wp_enqueue_scripts', array( $this, 'debug_script' ) );
82
+ } elseif ( defined( 'EWWW_IMAGE_OPTIMIZER_WEBP_EXTERNAL_SCRIPT' ) && EWWW_IMAGE_OPTIMIZER_WEBP_EXTERNAL_SCRIPT ) {
83
+ // Load the minified, non-inline version of the webp rewrite script.
84
+ add_action( 'wp_enqueue_scripts', array( $this, 'min_external_script' ) );
85
+ } else {
86
+ // Loads jQuery and the minified inline webp rewrite script.
87
+ if ( function_exists( 'wp_add_inline_script' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_inline_fallback' ) ) {
88
+ add_action( 'wp_enqueue_scripts', array( $this, 'load_jquery' ) );
89
+ } else {
90
+ add_action( 'wp_head', array( $this, 'inline_script' ) );
91
+ }
92
+ }
93
+ }
94
+
95
+
96
+ /**
97
+ * Starts an output buffer and registers the callback function to do WebP replacement.
98
+ */
99
+ function buffer_start() {
100
+ ob_start( array( $this, 'filter_page_output' ) );
101
+ }
102
+
103
+ /**
104
+ * Copies attributes from the original img element to the noscript element.
105
+ *
106
+ * @param string $image The full text of the img element.
107
+ * @param string $nscript A noscript element that will be given all the (known) attributes of $image.
108
+ * @param string $prefix Optional. Value to prepend to all attribute names. Default 'data-'.
109
+ * @return string The modified noscript tag.
110
+ */
111
+ function attr_copy( $image, $nscript, $prefix = 'data-' ) {
112
+ if ( ! is_string( $image ) || ! is_string( $nscript ) ) {
113
+ return $nscript;
114
+ }
115
+ $attributes = array(
116
+ 'align',
117
+ 'alt',
118
+ 'border',
119
+ 'crossorigin',
120
+ 'height',
121
+ 'hspace',
122
+ 'ismap',
123
+ 'longdesc',
124
+ 'usemap',
125
+ 'vspace',
126
+ 'width',
127
+ 'accesskey',
128
+ 'class',
129
+ 'contenteditable',
130
+ 'contextmenu',
131
+ 'dir',
132
+ 'draggable',
133
+ 'dropzone',
134
+ 'hidden',
135
+ 'id',
136
+ 'lang',
137
+ 'spellcheck',
138
+ 'style',
139
+ 'tabindex',
140
+ 'title',
141
+ 'translate',
142
+ 'sizes',
143
+ 'data-caption',
144
+ 'data-lazy-type',
145
+ 'data-attachment-id',
146
+ 'data-permalink',
147
+ 'data-orig-size',
148
+ 'data-comments-opened',
149
+ 'data-image-meta',
150
+ 'data-image-title',
151
+ 'data-image-description',
152
+ 'data-event-trigger',
153
+ 'data-highlight-color',
154
+ 'data-highlight-opacity',
155
+ 'data-highlight-border-color',
156
+ 'data-highlight-border-width',
157
+ 'data-highlight-border-opacity',
158
+ 'data-no-lazy',
159
+ 'data-lazy',
160
+ 'data-large_image_width',
161
+ 'data-large_image_height',
162
+ );
163
+ foreach ( $attributes as $attribute ) {
164
+ $attr_value = $this->get_attribute( $image, $attribute );
165
+ if ( $attr_value ) {
166
+ $this->set_attribute( $nscript, $prefix . $attribute, $attr_value );
167
+ }
168
+ }
169
+ return $nscript;
170
+ }
171
+
172
+ /**
173
+ * Replaces images within a srcset attribute with their .webp derivatives.
174
+ *
175
+ * @param string $srcset A valid srcset attribute from an img element.
176
+ * @return bool|string False if no changes were made, or the new srcset if any WebP images replaced the originals.
177
+ */
178
+ function srcset_replace( $srcset ) {
179
+ $srcset_urls = explode( ' ', $srcset );
180
+ $found_webp = false;
181
+ if ( ewww_image_optimizer_iterable( $srcset_urls ) && count( $srcset_urls ) > 1 ) {
182
+ ewwwio_debug_message( 'parsing srcset urls' );
183
+ foreach ( $srcset_urls as $srcurl ) {
184
+ if ( is_numeric( substr( $srcurl, 0, 1 ) ) ) {
185
+ continue;
186
+ }
187
+ $trailing = ' ';
188
+ if ( ',' === substr( $srcurl, -1 ) ) {
189
+ $trailing = ',';
190
+ $srcurl = rtrim( $srcurl, ',' );
191
+ }
192
+ ewwwio_debug_message( "looking for $srcurl from srcset" );
193
+ if ( $this->validate_image_url( $srcurl ) ) {
194
+ $srcset = str_replace( $srcurl . $trailing, $this->generate_url( $srcurl ) . $trailing, $srcset );
195
+ ewwwio_debug_message( "replaced $srcurl in srcset" );
196
+ $found_webp = true;
197
+ }
198
+ }
199
+ } elseif ( $this->validate_image_url( $srcset ) ) {
200
+ return $this->generate_url( $srcset );
201
+ }
202
+ if ( $found_webp ) {
203
+ return $srcset;
204
+ } else {
205
+ return false;
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Replaces images with the Jetpack data attributes with their .webp derivatives.
211
+ *
212
+ * @param string $image The full text of the img element.
213
+ * @param string $nscript A noscript element that will be assigned the jetpack data attributes.
214
+ * @return string The modified noscript tag.
215
+ */
216
+ function jetpack_replace( $image, $nscript ) {
217
+ $data_orig_file = $this->get_attribute( $image, 'data-orig-file' );
218
+ if ( $data_orig_file ) {
219
+ ewwwio_debug_message( "looking for data-orig-file: $data_orig_file" );
220
+ if ( $this->validate_image_url( $data_orig_file ) ) {
221
+ $this->set_attribute( $nscript, 'data-webp-orig-file', $this->generate_url( $data_orig_file ) );
222
+ ewwwio_debug_message( "replacing $data_orig_file in data-orig-file" );
223
+ }
224
+ $this->set_attribute( $nscript, 'data-orig-file', $data_orig_file );
225
+ }
226
+ $data_medium_file = $this->get_attribute( $image, 'data-medium-file' );
227
+ if ( $data_medium_file ) {
228
+ ewwwio_debug_message( "looking for data-medium-file: $data_medium_file" );
229
+ if ( $this->validate_image_url( $data_medium_file ) ) {
230
+ $this->set_attribute( $nscript, 'data-webp-medium-file', $this->generate_url( $data_medium_file ) );
231
+ ewwwio_debug_message( "replacing $data_medium_file in data-medium-file" );
232
+ }
233
+ $this->set_attribute( $nscript, 'data-medium-file', $data_medium_file );
234
+ }
235
+ $data_large_file = $this->get_attribute( $image, 'data-large-file' );
236
+ if ( $data_large_file ) {
237
+ ewwwio_debug_message( "looking for data-large-file: $data_large_file" );
238
+ if ( $this->validate_image_url( $data_large_file ) ) {
239
+ $this->set_attribute( $nscript, 'data-webp-large-file', $this->generate_url( $data_large_file ) );
240
+ ewwwio_debug_message( "replacing $data_large_file in data-large-file" );
241
+ }
242
+ $this->set_attribute( $nscript, 'data-large-file', $data_large_file );
243
+ }
244
+ return $nscript;
245
+ }
246
+
247
+ /**
248
+ * Replaces images with the WooCommerce data attributes with their .webp derivatives.
249
+ *
250
+ * @param string $image The full text of the img element.
251
+ * @param string $nscript A noscript element that will be assigned the WooCommerce data attributes.
252
+ * @return string The modified noscript tag.
253
+ */
254
+ function woocommerce_replace( $image, $nscript ) {
255
+ $data_large_image = $this->get_attribute( $image, 'data-large_image' );
256
+ if ( $data_large_image ) {
257
+ ewwwio_debug_message( "looking for data-large_image: $data_large_image" );
258
+ if ( $this->validate_image_url( $data_large_image ) ) {
259
+ $this->set_attribute( $nscript, 'data-webp-large_image', $this->generate_url( $data_large_image ) );
260
+ ewwwio_debug_message( "replacing $data_large_image in data-large_image" );
261
+ }
262
+ $this->set_attribute( $nscript, 'data-large_image', $data_large_image );
263
+ }
264
+ $data_src = $this->get_attribute( $image, 'data-src' );
265
+ if ( $data_src ) {
266
+ ewwwio_debug_message( "looking for data-src: $data_src" );
267
+ if ( $this->validate_image_url( $data_src ) ) {
268
+ $this->set_attribute( $nscript, 'data-webp-src', $this->generate_url( $data_src ) );
269
+ ewwwio_debug_message( "replacing $data_src in data-src" );
270
+ }
271
+ $this->set_attribute( $nscript, 'data-src', $data_src );
272
+ }
273
+ return $nscript;
274
+ }
275
+
276
+ /**
277
+ * Search for img elements and rewrite them with noscript elements for WebP replacement.
278
+ *
279
+ * Any img elements or elements that may be used in place of img elements by JS are checked to see
280
+ * if WebP derivatives exist. The element is then wrapped within a noscript element for fallback,
281
+ * and noscript element receives a copy of the attributes from the img along with webp replacement
282
+ * values for those attributes.
283
+ *
284
+ * @param string $buffer The full HTML page generated since the output buffer was started.
285
+ * @return string The altered buffer containing the full page with WebP images inserted.
286
+ */
287
+ function filter_page_output( $buffer ) {
288
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
289
+ // If this is an admin page, don't filter it.
290
+ if ( ( empty( $buffer ) || is_admin() ) ) {
291
+ return $buffer;
292
+ }
293
+ // If Cache Enabler's WebP option is enabled, don't filter it.
294
+ if ( ewww_image_optimizer_ce_webp_enabled() ) {
295
+ return $buffer;
296
+ }
297
+ $uri = $_SERVER['REQUEST_URI'];
298
+ // Based on the uri, if this is a cornerstone editing page, don't filter the response.
299
+ if ( ! empty( $_GET['cornerstone'] ) || strpos( $uri, 'cornerstone-endpoint' ) !== false ) {
300
+ return $buffer;
301
+ }
302
+ if ( ! empty( $_GET['et_fb'] ) ) {
303
+ return $buffer;
304
+ }
305
+ if ( ! empty( $_GET['tatsu'] ) ) {
306
+ return $buffer;
307
+ }
308
+ if ( ! empty( $_POST['action'] ) && 'tatsu_get_concepts' === $_POST['action'] ) {
309
+ return $buffer;
310
+ }
311
+ // If this is XML (not XHTML), don't modify the page.
312
+ if ( preg_match( '/<\?xml/', $buffer ) ) {
313
+ return $buffer;
314
+ }
315
+ if ( strpos( $buffer, 'amp-boilerplate' ) ) {
316
+ ewwwio_debug_message( 'AMP page processing' );
317
+ return $buffer;
318
+ }
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
+
327
+ $images = $this->get_images_from_html( $buffer, false );
328
+ if ( empty( $noscript_images ) && ewww_image_optimizer_iterable( $images[0] ) ) {
329
+ foreach ( $images[0] as $index => $image ) {
330
+ $file = $images['img_url'][ $index ];
331
+ ewwwio_debug_message( "parsing an image: $file" );
332
+ // If a CDN path match was found, or .webp image existsence is confirmed, and this is not a lazy-load 'dummy' image.
333
+ if ( $this->validate_image_url( $file ) ) {
334
+ ewwwio_debug_message( 'found a webp image or forced path' );
335
+ $nscript = '<noscript>';
336
+ $this->set_attribute( $nscript, 'data-img', $file );
337
+ $this->set_attribute( $nscript, 'data-webp', $this->generate_url( $file ) );
338
+ $srcset = $this->get_attribute( $image, 'srcset' );
339
+ if ( $srcset ) {
340
+ $srcset_webp = $this->srcset_replace( $srcset );
341
+ if ( $srcset_webp ) {
342
+ $this->set_attribute( $nscript, 'data-srcset-webp', $srcset_webp );
343
+ }
344
+ $this->set_attribute( $nscript, 'data-srcset-img', $srcset );
345
+ }
346
+ if ( $this->get_attribute( $image, 'data-orig-file' ) && $this->get_attribute( $image, 'data-medium-file' ) && $this->get_attribute( $image, 'data-large-file' ) ) {
347
+ $nscript = $this->jetpack_replace( $image, $nscript );
348
+ }
349
+ if ( $this->get_attribute( $image, 'data-large_image' ) && $this->get_attribute( $image, 'data-src' ) ) {
350
+ $nscript = $this->woocommerce_replace( $image, $nscript );
351
+ }
352
+ $nscript = $this->attr_copy( $image, $nscript );
353
+ $this->set_attribute( $nscript, 'class', 'ewww_webp' );
354
+ $buffer = str_replace( $image, $nscript . $image . '</noscript>', $buffer );
355
+ }
356
+ // NOTE: lazy loads are shutoff for now, since they don't work consistently
357
+ // WP Retina 2x lazy loads.
358
+ if ( false && empty( $file ) && $image->getAttribute( 'data-srcset' ) && strpos( $image->getAttribute( 'class' ), 'lazyload' ) ) {
359
+ $srcset = $image->getAttribute( 'data-srcset' );
360
+ $srcset_webp = $this->srcset_replace( $srcset );
361
+ if ( $srcset_webp ) {
362
+ $nimage = $html->createElement( 'img' );
363
+ $nimage->setAttribute( 'data-srcset-webp', $srcset_webp );
364
+ $nimage->setAttribute( 'data-srcset-img', $srcset );
365
+ ewww_image_optimizer_webp_attr_copy( $image, $nimage, '' );
366
+ $nimage->setAttribute( 'class', $image->getAttribute( 'class' ) . ' ewww_webp_lazy_retina' );
367
+ $image->parentNode->replaceChild( $nimage, $image );
368
+ }
369
+ }
370
+ // Hueman theme lazy-loads.
371
+ if ( false && ! empty( $file ) && strpos( $file, 'image/gif;base64,R0lGOD' ) && $image->getAttribute( 'data-src' ) && $image->getAttribute( 'data-srcset' ) ) {
372
+ $dummy = $file;
373
+ $file = $image->getAttribute( 'data-src' );
374
+ ewwwio_debug_message( "checking webp for hueman data-src: $file" );
375
+ $filepath = ABSPATH . str_replace( $home_url, '', $file );
376
+ if ( $valid_path || is_file( $filepath . '.webp' ) ) {
377
+ ewwwio_debug_message( "found webp for Hueman lazyload: $filepath" );
378
+ $nscript = $html->createElement( 'noscript' );
379
+ $nscript->setAttribute( 'data-src', $dummy );
380
+ $nscript->setAttribute( 'data-img', $file );
381
+ $nscript->setAttribute( 'data-webp-src', $file . '.webp' );
382
+ $image->setAttribute( 'src', $file );
383
+ if ( $image->getAttribute( 'data-srcset' ) ) {
384
+ $srcset = $image->getAttribute( 'data-srcset' );
385
+ $srcset_webp = ewww_image_optimizer_webp_srcset_replace( $srcset );
386
+ if ( $srcset_webp ) {
387
+ $nscript->setAttribute( 'data-srcset-webp', $srcset_webp );
388
+ }
389
+ $nscript->setAttribute( 'data-srcset-img', $srcset );
390
+ }
391
+ ewww_image_optimizer_webp_attr_copy( $image, $nscript );
392
+ $nscript->setAttribute( 'class', 'ewww_webp_lazy_hueman' );
393
+ $image->parentNode->replaceChild( $nscript, $image );
394
+ $nscript->appendChild( $image );
395
+ }
396
+ }
397
+ // Lazy Load plugin (and hopefully Cherry variant) and BJ Lazy Load.
398
+ if ( false && ! empty( $file ) && ( strpos( $file, 'image/gif;base64,R0lGOD' ) || strpos( $file, 'lazy-load/images/1x1' ) ) && $image->getAttribute( 'data-lazy-src' ) && ! empty( $image->nextSibling ) && 'noscript' == $image->nextSibling->nodeName ) {
399
+ $dummy = $file;
400
+ $nimage = $html->createElement( 'img' );
401
+ $nimage->setAttribute( 'src', $dummy );
402
+ $file = $image->getAttribute( 'data-lazy-src' );
403
+ ewwwio_debug_message( "checking webp for Lazy Load data-lazy-src: $file" );
404
+ $filepath = ABSPATH . str_replace( $home_url, '', $file );
405
+ if ( $valid_path || is_file( $filepath . '.webp' ) ) {
406
+ ewwwio_debug_message( "found webp for Lazy Load: $filepath" );
407
+ $nimage->setAttribute( 'data-lazy-img-src', $file );
408
+ $nimage->setAttribute( 'data-lazy-webp-src', $file . '.webp' );
409
+ if ( $image->getAttribute( 'srcset' ) ) {
410
+ $srcset = $image->getAttribute( 'srcset' );
411
+ $srcset_webp = ewww_image_optimizer_webp_srcset_replace( $srcset, $home_url, $valid_path );
412
+ if ( $srcset_webp ) {
413
+ $nimage->setAttribute( 'data-srcset-webp', $srcset_webp );
414
+ }
415
+ $nimage->setAttribute( 'data-srcset', $srcset );
416
+ }
417
+ if ( $image->getAttribute( 'data-lazy-srcset' ) ) {
418
+ $srcset = $image->getAttribute( 'data-lazy-srcset' );
419
+ $srcset_webp = ewww_image_optimizer_webp_srcset_replace( $srcset, $home_url, $valid_path );
420
+ if ( $srcset_webp ) {
421
+ $nimage->setAttribute( 'data-lazy-srcset-webp', $srcset_webp );
422
+ }
423
+ $nimage->setAttribute( 'data-lazy-srcset-img', $srcset );
424
+ }
425
+ ewww_image_optimizer_webp_attr_copy( $image, $nimage, '' );
426
+ $nimage->setAttribute( 'class', $image->getAttribute( 'class' ) . ' ewww_webp_lazy_load' );
427
+ $image->parentNode->replaceChild( $nimage, $image );
428
+ }
429
+ } // End if().
430
+ // Rev Slider data-lazyload attribute on image elements.
431
+ if ( $this->get_attribute( $image, 'data-lazyload' ) ) {
432
+ $lazyload = $this->get_attribute( $image, 'data-lazyload' );
433
+ if ( $lazyload ) {
434
+ if ( $this->validate_image_url( $lazyload ) ) {
435
+ $this->set_attribute( $image, 'data-webp-lazyload', $this->generate_url( $lazyload ) );
436
+ ewwwio_debug_message( "replacing with webp for data-lazyload: $lazyload" );
437
+ $buffer = str_replace( $images[0][ $index ], $image, $buffer );
438
+ }
439
+ }
440
+ }
441
+ } // End foreach().
442
+ } // End if().
443
+ // Images listed as picture/source elements. Mostly for NextGEN, but should work anywhere.
444
+ $pictures = $this->get_picture_tags_from_html( $buffer );
445
+ if ( ewww_image_optimizer_iterable( $pictures ) ) {
446
+ foreach ( $pictures as $index => $picture ) {
447
+ $sources = $this->get_elements_from_html( $picture, 'source' );
448
+ if ( ewww_image_optimizer_iterable( $sources ) ) {
449
+ foreach ( $sources as $source ) {
450
+ ewwwio_debug_message( "parsing a picture source: $source" );
451
+ $srcset = $this->get_attribute( $source, 'srcset' );
452
+ if ( $srcset ) {
453
+ $srcset_webp = $this->srcset_replace( $srcset );
454
+ if ( $srcset_webp ) {
455
+ $source_webp = str_replace( $srcset, $srcset_webp, $source );
456
+ $this->set_attribute( $source_webp, 'type', 'image/webp' );
457
+ $picture = str_replace( $source, $source_webp . $source, $picture );
458
+ }
459
+ }
460
+ }
461
+ if ( $picture != $pictures[ $index ] ) {
462
+ ewwwio_debug_message( 'found webp for picture element' );
463
+ $buffer = str_replace( $pictures[ $index ], $picture, $buffer );
464
+ }
465
+ }
466
+ }
467
+ }
468
+ // NextGEN slides listed as 'a' elements.
469
+ $links = $this->get_elements_from_html( $buffer, 'a' );
470
+ if ( ewww_image_optimizer_iterable( $links ) ) {
471
+ foreach ( $links as $index => $link ) {
472
+ ewwwio_debug_message( "parsing a link $link" );
473
+ $file = $this->get_attribute( $link, 'data-src' );
474
+ $thumb = $this->get_attribute( $link, 'data-thumbnail' );
475
+ if ( $file && $thumb ) {
476
+ ewwwio_debug_message( "checking webp for ngg data-src: $file" );
477
+ if ( $this->validate_image_url( $file ) ) {
478
+ $this->set_attribute( $link, 'data-webp', $this->generate_url( $file ) );
479
+ ewwwio_debug_message( "found webp for ngg data-src: $file" );
480
+ }
481
+ ewwwio_debug_message( "checking webp for ngg data-thumbnail: $thumb" );
482
+ if ( $this->validate_image_url( $thumb ) ) {
483
+ $this->set_attribute( $link, 'data-webp-thumbnail', $this->generate_url( $thumb ) );
484
+ ewwwio_debug_message( "found webp for ngg data-thumbnail: $thumb" );
485
+ }
486
+ }
487
+ if ( $link != $links[ $index ] ) {
488
+ $buffer = str_replace( $links[ $index ], $link, $buffer );
489
+ }
490
+ }
491
+ }
492
+ // Revolution Slider 'li' elements.
493
+ $listitems = $this->get_elements_from_html( $buffer, 'li' );
494
+ if ( ewww_image_optimizer_iterable( $listitems ) ) {
495
+ foreach ( $listitems as $index => $listitem ) {
496
+ ewwwio_debug_message( 'parsing a listitem' );
497
+ if ( $this->get_attribute( $listitem, 'data-title' ) === 'Slide' && ( $this->get_attribute( $listitem, 'data-lazyload' ) || $this->get_attribute( $listitem, 'data-thumb' ) ) ) {
498
+ $thumb = $this->get_attribute( $listitem, 'data-thumb' );
499
+ ewwwio_debug_message( "checking webp for revslider data-thumb: $thumb" );
500
+ if ( $this->validate_image_url( $thumb ) ) {
501
+ $this->set_attribute( $listitem, 'data-webp-thumb', $this->generate_url( $thumb ) );
502
+ ewwwio_debug_message( "found webp for revslider data-thumb: $thumb" );
503
+ }
504
+ $param_num = 1;
505
+ while ( $param_num < 11 ) {
506
+ $parameter = $this->get_attribute( $listitem, 'data-param' . $param_num );
507
+ if ( $parameter ) {
508
+ ewwwio_debug_message( "checking webp for revslider data-param$param_num: $parameter" );
509
+ if ( strpos( $parameter, 'http' ) === 0 ) {
510
+ ewwwio_debug_message( "looking for $parameter" );
511
+ if ( $this->validate_image_url( $parameter ) ) {
512
+ $this->set_attribute( $listitem, 'data-webp-param' . $param_num, $this->generate_url( $parameter ) );
513
+ ewwwio_debug_message( "found webp for data-param$param_num: $parameter" );
514
+ }
515
+ }
516
+ }
517
+ $param_num++;
518
+ }
519
+ if ( $listitem != $listitems[ $index ] ) {
520
+ $buffer = str_replace( $listitems[ $index ], $listitem, $buffer );
521
+ }
522
+ }
523
+ } // End foreach().
524
+ } // End if().
525
+ // WooCommerce thumbs listed as 'div' elements.
526
+ $divs = $this->get_elements_from_html( $buffer, 'div' );
527
+ if ( ewww_image_optimizer_iterable( $divs ) ) {
528
+ foreach ( $divs as $index => $div ) {
529
+ ewwwio_debug_message( 'parsing a div' );
530
+ $thumb = $this->get_attribute( $div, 'data-thumb' );
531
+ $div_class = $this->get_attribute( $div, 'class' );
532
+ if ( $div_class && $thumb && strpos( $div_class, 'woocommerce-product-gallery__image' ) !== false ) {
533
+ ewwwio_debug_message( "checking webp for WC data-thumb: $thumb" );
534
+ if ( $this->validate_image_url( $thumb ) ) {
535
+ $this->set_attribute( $div, 'data-webp-thumb', $this->generate_url( $thumb ) );
536
+ ewwwio_debug_message( "found webp for WC data-thumb: $thumb" );
537
+ $buffer = str_replace( $divs[ $index ], $div, $buffer );
538
+ }
539
+ }
540
+ }
541
+ }
542
+ // Video elements, looking for poster attributes that are images.
543
+ $videos = $this->get_elements_from_html( $buffer, 'video' );
544
+ if ( ewww_image_optimizer_iterable( $videos ) ) {
545
+ foreach ( $videos as $index => $video ) {
546
+ ewwwio_debug_message( 'parsing a video element' );
547
+ $file = $this->get_attribute( $video, 'poster' );
548
+ if ( $file ) {
549
+ ewwwio_debug_message( "checking webp for video poster: $file" );
550
+ if ( $this->validate_image_url( $file ) ) {
551
+ $this->set_attribute( $video, 'data-poster-webp', $this->generate_url( $file ) );
552
+ $this->set_attribute( $video, 'data-poster-image', $file );
553
+ $this->remove_attribute( $video, 'poster' );
554
+ ewwwio_debug_message( "found webp for video poster: $file" );
555
+ $buffer = str_replace( $videos[ $index ], $video, $buffer );
556
+ }
557
+ }
558
+ }
559
+ }
560
+ ewwwio_debug_message( 'all done parsing page for alt webp' );
561
+ if ( true ) { // Set to true for extra logging.
562
+ ewww_image_optimizer_debug_log();
563
+ }
564
+ return $buffer;
565
+ }
566
+
567
+ /**
568
+ * Handle image urls within the NextGEN pro lightbox displays.
569
+ *
570
+ * @param array $images An array of NextGEN images and associate attributes.
571
+ * @return array The array of images with WebP versions added.
572
+ */
573
+ function ngg_pro_lightbox_images_queue( $images ) {
574
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
575
+ if ( ewww_image_optimizer_iterable( $images ) ) {
576
+ foreach ( $images as $index => $image ) {
577
+ if ( ! empty( $image['image'] ) && $this->validate_image_url( $image['image'] ) ) {
578
+ $images[ $index ]['image-webp'] = $this->generate_url( $image['image'] );
579
+ }
580
+ if ( ! empty( $image['thumb'] ) && $this->validate_image_url( $image['thumb'] ) ) {
581
+ $images[ $index ]['thumb-webp'] = $this->generate_url( $image['thumb'] );
582
+ }
583
+ if ( ! empty( $image['full_image'] ) && $this->validate_image_url( $image['full_image'] ) ) {
584
+ $images[ $index ]['full_image_webp'] = $this->generate_url( $image['full_image'] );
585
+ }
586
+ if ( ewww_image_optimizer_iterable( $image['srcsets'] ) ) {
587
+ foreach ( $image['srcsets'] as $size => $srcset ) {
588
+ if ( $this->validate_image_url( $srcset ) ) {
589
+ $images[ $index ]['srcsets'][ $size . '-webp' ] = $this->generate_url( $srcset );
590
+ }
591
+ }
592
+ }
593
+ if ( ewww_image_optimizer_iterable( $image['full_srcsets'] ) ) {
594
+ foreach ( $image['full_srcsets'] as $size => $srcset ) {
595
+ if ( $this->validate_image_url( $srcset ) ) {
596
+ $images[ $index ]['full_srcsets'][ $size . '-webp' ] = $this->generate_url( $srcset );
597
+ }
598
+ }
599
+ }
600
+ }
601
+ }
602
+ return $images;
603
+ }
604
+
605
+ /**
606
+ * Checks if the path is a valid "forced" WebP image.
607
+ *
608
+ * @param string $image The image file.
609
+ * @return bool True if the file matches a forced path, false otherwise.
610
+ */
611
+ function validate_image_url( $image ) {
612
+ ewwwio_debug_message( "webp validation for $image" );
613
+ if ( strpos( $image, 'assets/images/dummy.png' ) || strpos( $image, 'base64,R0lGOD' ) || strpos( $image, 'lazy-load/images/1x1' ) || strpos( $image, 'assets/images/transparent.png' ) ) {
614
+ ewwwio_debug_message( 'lazy load placeholder' );
615
+ return false;
616
+ }
617
+ if ( $this->parsing_exactdn && false !== strpos( $image, $this->exactdn_domain ) ) {
618
+ ewwwio_debug_message( 'exactdn image' );
619
+ return true;
620
+ }
621
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) && $this->webp_paths ) {
622
+ // Check the image for configured CDN paths.
623
+ foreach ( $this->webp_paths as $webp_path ) {
624
+ if ( strpos( $image, $webp_path ) !== false ) {
625
+ ewwwio_debug_message( 'forced cdn image' );
626
+ return true;
627
+ }
628
+ }
629
+ }
630
+ if ( 0 === strpos( $image, $this->relative_home_url ) ) {
631
+ $imagepath = str_replace( $this->relative_home_url, ABSPATH, $image );
632
+ } elseif ( 0 === strpos( $image, $this->home_url ) ) {
633
+ $imagepath = str_replace( $this->home_url, ABSPATH, $image );
634
+ } else {
635
+ ewwwio_debug_message( 'not a valid local image' );
636
+ return false;
637
+ }
638
+ if ( is_file( $imagepath . '.webp' ) ) {
639
+ ewwwio_debug_message( 'local .webp image found' );
640
+ return true;
641
+ }
642
+ return false;
643
+ }
644
+
645
+ /**
646
+ * Generate a WebP url.
647
+ *
648
+ * Adds .webp to the end, or adds a webp parameter for ExactDN urls.
649
+ *
650
+ * @param string $url The image url.
651
+ * @return string The WebP version of the image url.
652
+ */
653
+ function generate_url( $url ) {
654
+ if ( $this->parsing_exactdn && false !== strpos( $url, $this->exactdn_domain ) ) {
655
+ return add_query_arg( 'webp', 1, $url );
656
+ } else {
657
+ return $url . '.webp';
658
+ }
659
+ return $url;
660
+ }
661
+
662
+ /**
663
+ * Load full webp script when SCRIPT_DEBUG is enabled.
664
+ */
665
+ function debug_script() {
666
+ if ( ! ewww_image_optimizer_ce_webp_enabled() ) {
667
+ wp_enqueue_script( 'ewww-webp-load-script', plugins_url( '/includes/load_webp.js', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ), array( 'jquery' ), EWWW_IMAGE_OPTIMIZER_VERSION );
668
+ }
669
+ }
670
+
671
+ /**
672
+ * Load minified webp script when EWWW_IMAGE_OPTIMIZER_WEBP_EXTERNAL_SCRIPT is set.
673
+ */
674
+ function min_external_script() {
675
+ if ( ! ewww_image_optimizer_ce_webp_enabled() ) {
676
+ wp_enqueue_script( 'ewww-webp-load-script', plugins_url( '/includes/load_webp.min.js', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ), array( 'jquery' ), EWWW_IMAGE_OPTIMIZER_VERSION );
677
+ }
678
+ }
679
+
680
+ /**
681
+ * Enqueue script dependency for alt webp rewriting when running inline.
682
+ */
683
+ function load_jquery() {
684
+ wp_enqueue_script( 'jquery' );
685
+ ewwwio_debug_message( 'loading webp script with wp_add_inline_script' );
686
+ wp_add_inline_script( 'jquery-migrate', $this->inline_script );
687
+ }
688
+
689
+ /**
690
+ * Load minified inline version of webp script (from jscompress.com).
691
+ */
692
+ function inline_script() {
693
+ ewwwio_debug_message( 'loading webp script without wp_add_inline_script' );
694
+ echo "<script>$this->inline_script</script>";
695
+ }
696
+ }
697
+
698
+ global $ewwwio_alt_webp;
699
+ $ewwwio_alt_webp = new EWWWIO_Alt_Webp();
classes/class-ewwwio-gd-editor.php CHANGED
@@ -94,10 +94,6 @@ if ( class_exists( 'Bbpp_Animated_Gif' ) ) {
94
  }
95
  $metadata = parent::multi_resize( $sizes );
96
  ewwwio_debug_message( 'image editor (AGR gd) multi resize' );
97
- if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
98
- ewwwio_debug_message( print_r( $metadata, true ) );
99
- ewwwio_debug_message( print_r( $this, true ) );
100
- }
101
  $info = pathinfo( $this->file );
102
  $dir = $info['dirname'];
103
  if ( ewww_image_optimizer_iterable( $metadata ) ) {
94
  }
95
  $metadata = parent::multi_resize( $sizes );
96
  ewwwio_debug_message( 'image editor (AGR gd) multi resize' );
 
 
 
 
97
  $info = pathinfo( $this->file );
98
  $dir = $info['dirname'];
99
  if ( ewww_image_optimizer_iterable( $metadata ) ) {
classes/class-ewwwio-install-cloud.php ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Functions to install the Cloud version of the plugin.
4
+ *
5
+ * Portions thanks to TGMPA: http://tgmpluginactivation.com/
6
+ *
7
+ * @package EWWW_Image_Optimizer
8
+ * @since 4.3.0
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
+
15
+ /**
16
+ * Installs the Cloud version of the plugin.
17
+ *
18
+ * @since 3.5.1
19
+ */
20
+ class EWWWIO_Install_Cloud {
21
+
22
+ /**
23
+ * URL for Cloud plugin.
24
+ *
25
+ * @access private
26
+ * @var string $plugin_url
27
+ */
28
+ private $plugin_url = '';
29
+
30
+ /**
31
+ * Slug for Cloud plugin.
32
+ *
33
+ * @access private
34
+ * @var string $plugin_slug
35
+ */
36
+ private $plugin_slug = 'ewww-image-optimizer-cloud';
37
+
38
+ /**
39
+ * Slug for Core plugin.
40
+ *
41
+ * @access private
42
+ * @var string $core_slug
43
+ */
44
+ private $core_slug = 'ewww-image-optimizer';
45
+
46
+ /**
47
+ * Folder where plugins are installed.
48
+ *
49
+ * @access private
50
+ * @var string $plugins_folder
51
+ */
52
+ private $plugins_folder = '';
53
+
54
+ /**
55
+ * Get things going.
56
+ */
57
+ public function __construct() {
58
+ // Installation routine for cloud plugin.
59
+ add_action( 'admin_action_ewwwio_install_cloud_plugin', array( $this, 'install_cloud_plugin' ) );
60
+
61
+ $this->plugins_folder = trailingslashit( dirname( dirname( __DIR__ ) ) );
62
+
63
+ $this->plugin_file_rel = $this->plugin_slug . '/' . $this->plugin_slug . '.php';
64
+ $this->plugin_file = $this->plugins_folder . $this->plugin_file_rel;
65
+
66
+ $this->core_plugin_file_rel = $this->core_slug . '/' . $this->core_slug . '.php';
67
+ $this->core_plugin_file = $this->plugins_folder . $this->core_plugin_file_rel;
68
+ }
69
+
70
+ /**
71
+ * Run the installer.
72
+ */
73
+ public function install_cloud_plugin() {
74
+ $permissions = apply_filters( 'ewww_image_optimizer_admin_permissions', 'install_plugins' );
75
+ if ( false === current_user_can( $permissions ) ) {
76
+ wp_die( esc_html__( 'You do not have permission to install image optimizer utilities.', 'ewww-image-optimizer' ) );
77
+ }
78
+
79
+ if ( ! function_exists( 'get_plugins' ) ) {
80
+ require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
81
+ }
82
+ if ( ! is_readable( $this->plugins_folder ) || ! is_writable( $this->plugins_folder ) ) {
83
+ wp_die( esc_html__( 'The plugins folder is not writable, you may install the EWWW Image Optimizer Cloud manually.', 'ewww-image-optimizer' ) );
84
+ return;
85
+ }
86
+ if ( ! is_file( $this->plugin_file ) ) {
87
+ if ( is_dir( dirname( $this->plugin_file ) ) ) {
88
+ wp_die( esc_html__( 'A partial installation already exists. Please remove it and try again.', 'ewww-image-optimizer' ) );
89
+ }
90
+ $this->plugin_url = $this->get_download_url();
91
+ if ( ! class_exists( 'Plugin_Upgrader', false ) ) {
92
+ require_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
93
+ }
94
+ $upgrader = new Plugin_Upgrader( new Automatic_Upgrader_Skin() );
95
+ $upgraded = $upgrader->install( $this->plugin_url );
96
+ if ( is_wp_error( $upgraded ) ) {
97
+ wp_die( esc_html( $upgraded->get_error_message() ) );
98
+ }
99
+ }
100
+
101
+ if ( is_file( $this->plugin_file ) ) {
102
+ $core_active = $this->is_plugin_active( $this->core_plugin_file_rel );
103
+ // If not plugin active.
104
+ if ( ! $this->is_plugin_active( $this->plugin_file_rel ) ) {
105
+ $network_wide = false;
106
+ if ( 'multi' === $core_active ) {
107
+ $network_wide = true;
108
+ }
109
+ if ( $core_active ) {
110
+ deactivate_plugins( $this->core_plugin_file_rel, true, $network_wide );
111
+ }
112
+ $activate = activate_plugin( $this->plugin_file_rel, '', $network_wide );
113
+ if ( is_wp_error( $activate ) ) {
114
+ wp_die( esc_html( $activate->get_error_message() ) );
115
+ }
116
+ if ( $network_wide ) {
117
+ $redirect_url = admin_url( 'network/plugins.php?ewwwio_cloud_activated=1' );
118
+ } else {
119
+ $redirect_url = admin_url( 'plugins.php?ewwwio_cloud_activated=1' );
120
+ }
121
+ wp_redirect( $redirect_url );
122
+ exit( 0 );
123
+ } else {
124
+ wp_redirect( admin_url( 'plugins.php' ) );
125
+ exit( 0 );
126
+ }
127
+ }
128
+ wp_redirect( admin_url( 'plugins.php' ) );
129
+ exit( 0 );
130
+ }
131
+
132
+ /**
133
+ * Get the download URL from WP.org.
134
+ *
135
+ * @return string The url for the latest version.
136
+ */
137
+ protected function get_download_url() {
138
+ $url = '';
139
+ if ( ! function_exists( 'plugins_api' ) ) {
140
+ require_once( ABSPATH . 'wp-admin/includes/plugin-install.php' );
141
+ }
142
+ $response = plugins_api( 'plugin_information', array(
143
+ 'slug' => $this->plugin_slug,
144
+ 'fields' => array(
145
+ 'sections' => false,
146
+ 'short_description' => false,
147
+ 'downloaded' => false,
148
+ 'rating' => false,
149
+ 'ratings' => false,
150
+ 'tags' => false,
151
+ 'homepage' => false,
152
+ 'donate_link' => false,
153
+ 'added' => false,
154
+ ),
155
+ ) );
156
+ if ( is_wp_error( $response ) ) {
157
+ wp_die( esc_html( $response->get_error_message() ) );
158
+ } else {
159
+ $url = $response->download_link;
160
+ }
161
+ return $url;
162
+ }
163
+
164
+ /**
165
+ * Check if a plugin is active.
166
+ *
167
+ * @param string $file Plugin file basename.
168
+ * @return bool|string True or 'multi' if active, false otherwise.
169
+ */
170
+ function is_plugin_active( $file ) {
171
+ if ( is_multisite() && is_plugin_active_for_network( $file ) ) {
172
+ return 'multi';
173
+ }
174
+ if ( is_plugin_active( $file ) ) {
175
+ return true;
176
+ }
177
+ return false;
178
+ }
179
+ }
180
+
181
+ $ewwwio_install_cloud = new EWWWIO_Install_Cloud;
classes/class-ewwwio-page-parser.php ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Implements basic page parsing functions.
4
+ *
5
+ * @link https://ewww.io
6
+ * @package EWWW_Image_Optimizer
7
+ */
8
+
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
+ *
29
+ * @param string $content Some HTML.
30
+ * @param bool $hyperlinks Default true. Should we include encasing hyperlinks in our search.
31
+ * @return array An array of $images matches, where $images[0] is
32
+ * an array of full matches, and the link_url, img_tag,
33
+ * and img_url keys are arrays of those matches.
34
+ */
35
+ function get_images_from_html( $content, $hyperlinks = true ) {
36
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
37
+ $images = array();
38
+
39
+ if ( $hyperlinks ) {
40
+ $search_pattern = '#(?:<a[^>]+?href\s*=\s*["\'](?P<link_url>[^\s]+?)["\'][^>]*?>\s*)?(?P<img_tag><img[^>]*?\s+?src\s*=\s*["\'](?P<img_url>[^\s]+?)["\'].*?>){1}(?:\s*</a>)?#is';
41
+ } else {
42
+ $search_pattern = '#(?P<img_tag><img[^>]*?\s+?src\s*=\s*["\'](?P<img_url>[^\s]+?)["\'].*?>)#is';
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
+ }
50
+ }
51
+ return $images;
52
+ }
53
+ return array();
54
+ }
55
+
56
+ /**
57
+ * Match all images wrapped in <noscript> tags in a block of HTML.
58
+ *
59
+ * @param string $content Some HTML.
60
+ * @return array An array of $images matches, where $images[0] is
61
+ * an array of full matches, and the noscript_tag, img_tag,
62
+ * and img_url keys are arrays of those matches.
63
+ */
64
+ function get_noscript_images_from_html( $content ) {
65
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
66
+ $images = array();
67
+
68
+ if ( preg_match_all( '#(?P<noscript_tag><noscript[^>]*?>\s*)(?P<img_tag><img[^>]*?\s+?src\s*=\s*["\'](?P<img_url>[^\s]+?)["\'].*?>){1}(?:\s*</noscript>)?#is', $content, $images ) ) {
69
+ foreach ( $images as $key => $unused ) {
70
+ // Simplify the output as much as possible, mostly for confirming test results.
71
+ if ( is_numeric( $key ) && $key > 0 ) {
72
+ unset( $images[ $key ] );
73
+ }
74
+ }
75
+ return $images;
76
+ }
77
+ return array();
78
+ }
79
+
80
+ /**
81
+ * Match all sources wrapped in <picture> tags in a block of HTML.
82
+ *
83
+ * @param string $content Some HTML.
84
+ * @return array An array of $pictures matches, containing full elements with ending tags.
85
+ */
86
+ function get_picture_tags_from_html( $content ) {
87
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
88
+ $pictures = array();
89
+ if ( preg_match_all( '#(?:<picture[^>]*?>\s*)(?:<source[^>]*?>)+(?:.*?</picture>)?#is', $content, $pictures ) ) {
90
+ return $pictures[0];
91
+ }
92
+ return array();
93
+ }
94
+
95
+ /**
96
+ * Match all elements by tag name in a block of HTML. Does not retrieve contents or closing tags.
97
+ *
98
+ * @param string $content Some HTML.
99
+ * @param string $tag_name The name of the elements to retrieve.
100
+ * @return array An array of $elements.
101
+ */
102
+ function get_elements_from_html( $content, $tag_name ) {
103
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
104
+ if ( ! ctype_alpha( $tag_name ) ) {
105
+ return array();
106
+ }
107
+ if ( preg_match_all( '#<' . $tag_name . '[^>]+?>#is', $content, $elements ) ) {
108
+ return $elements[0];
109
+ }
110
+ return array();
111
+ }
112
+
113
+ /**
114
+ * Try to determine height and width from strings WP appends to resized image filenames.
115
+ *
116
+ * @param string $src The image URL.
117
+ * @return array An array consisting of width and height.
118
+ */
119
+ function get_dimensions_from_filename( $src ) {
120
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
121
+ $width_height_string = array();
122
+ ewwwio_debug_message( "looking for dimensions in $src" );
123
+ if ( preg_match( '#-(\d+)x(\d+)(@2x)?\.(?:' . implode( '|', $this->extensions ) . '){1}(?:\?.+)?$#i', $src, $width_height_string ) ) {
124
+ $width = (int) $width_height_string[1];
125
+ $height = (int) $width_height_string[2];
126
+
127
+ if ( strpos( $src, '@2x' ) ) {
128
+ $width = 2 * $width;
129
+ $height = 2 * $height;
130
+ }
131
+ if ( $width && $height ) {
132
+ ewwwio_debug_message( "found w$width h$height" );
133
+ return array( $width, $height );
134
+ }
135
+ }
136
+ return array( false, false );
137
+ }
138
+
139
+ /**
140
+ * Get an attribute from an HTML element.
141
+ *
142
+ * @param string $element The HTML element to parse.
143
+ * @param string $name The name of the attribute to search for.
144
+ * @return string The value of the attribute, or an empty string if not found.
145
+ */
146
+ function get_attribute( $element, $name ) {
147
+ if ( preg_match( '#' . $name . '\s*=\s*(["\'])([^\1]+?)\1#is', $element, $attr_matches ) ) {
148
+ if ( ! empty( $attr_matches[2] ) ) {
149
+ return $attr_matches[2];
150
+ }
151
+ }
152
+ // If there were not any matches with quotes, look for unquoted attributes, no spaces allowed.
153
+ if ( preg_match( '#' . $name . '\s*=\s*([^\s]+?)#is', $element, $attr_matches ) ) {
154
+ if ( ! empty( $attr_matches[1] ) ) {
155
+ return $attr_matches[1];
156
+ }
157
+ }
158
+ return '';
159
+ }
160
+
161
+ /**
162
+ * Set an attribute on an HTML element.
163
+ *
164
+ * @param string $element The HTML element to modify. Passed by reference.
165
+ * @param string $name The name of the attribute to set.
166
+ * @param string $value The value of the attribute to set.
167
+ * @param bool $replace Default false. True to replace, false to append.
168
+ */
169
+ function set_attribute( &$element, $name, $value, $replace = false ) {
170
+ if ( $replace ) {
171
+ $new_element = preg_replace( '#' . $name . '\s*=\s*(["\'])([^\1]+?)\1#is', "$name=$1$value$1", $element );
172
+ if ( $new_element !== $element ) {
173
+ $element = $new_element;
174
+ return;
175
+ }
176
+ $element = preg_replace( '#' . $name . '\s*=\s*([^\s]+?)#is', '', $element );
177
+ }
178
+ if ( false === strpos( $value, '"' ) ) {
179
+ $element = rtrim( $element, '>' ) . " $name=\"$value\">";
180
+ return;
181
+ }
182
+ $element = rtrim( $element, '>' ) . " $name='$value'>";
183
+ }
184
+
185
+ /**
186
+ * Remove an attribute from an HTML element.
187
+ *
188
+ * @param string $element The HTML element to modify. Passed by reference.
189
+ * @param string $name The name of the attribute to remove.
190
+ */
191
+ function remove_attribute( &$element, $name ) {
192
+ $element = preg_replace( '#' . $name . '\s*=\s*(["\'])([^\1]+?)\1#is', '', $element );
193
+ $element = preg_replace( '#' . $name . '\s*=\s*([^\s]+?)#is', '', $element );
194
+ }
195
+
196
+ /**
197
+ * A wrapper for PHP's parse_url, prepending assumed scheme for network path
198
+ * URLs. PHP versions 5.4.6 and earlier do not correctly parse without scheme.
199
+ *
200
+ * @param string $url The URL to parse.
201
+ * @param integer $component Retrieve specific URL component.
202
+ * @return mixed Result of parse_url.
203
+ */
204
+ function parse_url( $url, $component = -1 ) {
205
+ if ( 0 === strpos( $url, '//' ) ) {
206
+ $url = ( is_ssl() ? 'https:' : 'http:' ) . $url;
207
+ }
208
+ if ( false === strpos( $url, 'http' ) && '/' !== substr( $url, 0, 1 ) ) {
209
+ $url = ( is_ssl() ? 'https://' : 'http://' ) . $url;
210
+ }
211
+ // Because encoded ampersands in the filename break things.
212
+ $url = str_replace( '&#038;', '&', $url );
213
+ return parse_url( $url, $component );
214
+ }
215
+ }
classes/class-exactdn.php CHANGED
@@ -16,7 +16,7 @@ if ( ! defined( 'ABSPATH' ) ) {
16
  class ExactDN {
17
 
18
  /**
19
- * Allowed extensions are currently only images. Might add PDF/CSS/JS at some point.
20
  *
21
  * @access private
22
  * @var array $extensions
@@ -29,6 +29,15 @@ class ExactDN {
29
  'png',
30
  );
31
 
 
 
 
 
 
 
 
 
 
32
  /**
33
  * A list of image sizes registered for attachments.
34
  *
@@ -132,6 +141,10 @@ class ExactDN {
132
  add_filter( 'wp_calculate_image_srcset', array( $this, 'filter_srcset_array' ), 1001, 5 );
133
  add_filter( 'wp_calculate_image_sizes', array( $this, 'filter_sizes' ), 1, 2 ); // Early so themes can still filter.
134
 
 
 
 
 
135
  // DNS prefetching.
136
  add_action( 'wp_head', array( $this, 'dns_prefetch' ) );
137
 
@@ -159,7 +172,7 @@ class ExactDN {
159
 
160
  // Find the "local" domain.
161
  $upload_dir = wp_upload_dir( null, false );
162
- $this->upload_domain = defined( 'EXACTDN_LOCAL_DOMAIN' ) && EXACTDN_LOCAL_DOMAIN ? EXACTDN_LOCAL_DOMAIN : $this->parse_url( $upload_dir['baseurl'], PHP_URL_HOST );
163
  ewwwio_debug_message( "allowing images from here: $this->upload_domain" );
164
  $this->allowed_domains[] = $this->upload_domain;
165
  if ( strpos( $this->upload_domain, 'www' ) === false ) {
@@ -170,7 +183,17 @@ class ExactDN {
170
  $this->allowed_domains[] = $nonwww;
171
  }
172
  }
 
 
 
 
 
 
 
 
173
  $this->allowed_domains = apply_filters( 'exactdn_allowed_domains', $this->allowed_domains );
 
 
174
  }
175
 
176
  /**
@@ -476,6 +499,28 @@ class ExactDN {
476
  return update_option( 'ewww_image_optimizer_exactdn_' . $option_name, $option_value, $autoload );
477
  }
478
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
479
  /**
480
  * Match all images and any relevant <a> tags in a block of HTML.
481
  *
@@ -905,10 +950,15 @@ class ExactDN {
905
  if ( $this->exactdn_domain && $this->upload_domain ) {
906
  $escaped_upload_domain = str_replace( '.', '\.', ltrim( $this->upload_domain, 'w.' ) );
907
  ewwwio_debug_message( $escaped_upload_domain );
908
- // Pre-empt rewriting of wp-includes and wp-content if the extension is php/ashx by using a temporary placeholder.
909
- $content = preg_replace( '#(https?)://(?:www\.)?' . $escaped_upload_domain . '([^"\'?>]+?)?/wp-content/([^"\'?>]+?)\.(php|ashx)#i', '$1://' . $this->upload_domain . '$2/?wpcontent-bypass?/$3.$4', $content );
 
 
 
 
 
910
  $content = str_replace( 'wp-content/themes/jupiter"', '?wpcontent-bypass?/themes/jupiter"', $content );
911
- $content = preg_replace( '#(https?)://(?:www\.)?' . $escaped_upload_domain . '/([^"\'?>]+?)?wp-(includes|content)#i', '$1://' . $this->exactdn_domain . '/$2wp-$3', $content );
912
  $content = str_replace( '?wpcontent-bypass?', 'wp-content', $content );
913
  }
914
  }
@@ -1332,6 +1382,8 @@ class ExactDN {
1332
  is_array( $multipliers )
1333
  /** This filter is already documented in class-exactdn.php */
1334
  && ! apply_filters( 'exactdn_skip_image', false, $url, null )
 
 
1335
  /** Verify basic meta is intact. */
1336
  && isset( $image_meta['width'] ) && isset( $image_meta['height'] ) && isset( $image_meta['file'] )
1337
  /** Verify we have the requested width/height. */
@@ -1601,8 +1653,8 @@ class ExactDN {
1601
  return false;
1602
  }
1603
 
1604
- // Ensure image extension is acceptable.
1605
- if ( ! in_array( strtolower( pathinfo( $url_info['path'], PATHINFO_EXTENSION ) ), $this->extensions ) ) {
1606
  ewwwio_debug_message( 'invalid extension' );
1607
  return false;
1608
  }
@@ -1702,6 +1754,75 @@ class ExactDN {
1702
  return is_array( self::$image_sizes ) ? self::$image_sizes : array();
1703
  }
1704
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1705
  /**
1706
  * Enqueue ExactDN helper script
1707
  */
@@ -1746,6 +1867,14 @@ class ExactDN {
1746
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1747
  $parsed_url = $this->parse_url( $url );
1748
 
 
 
 
 
 
 
 
 
1749
  // Unable to parse.
1750
  if ( ! $parsed_url || ! is_array( $parsed_url ) || empty( $parsed_url['host'] ) || empty( $parsed_url['path'] ) ) {
1751
  ewwwio_debug_message( 'src url no good' );
@@ -1771,8 +1900,9 @@ class ExactDN {
1771
  return $url;
1772
  }
1773
 
 
1774
  // If a resource doesn't have a version string, we add one to help with cache-busting.
1775
- if ( empty( $parsed_url['query'] ) ) {
1776
  $modified = ewww_image_optimizer_function_exists( 'filemtime' ) ? filemtime( get_template_directory() ) : '';
1777
  if ( empty( $modified ) ) {
1778
  $modified = (int) EWWW_IMAGE_OPTIMIZER_VERSION;
@@ -1783,6 +1913,8 @@ class ExactDN {
1783
  * @param string EWWW IO version.
1784
  */
1785
  $parsed_url['query'] = apply_filters( 'exactdn_version_string', "m=$modified" );
 
 
1786
  }
1787
 
1788
  $exactdn_url = '//' . $this->exactdn_domain . '/' . ltrim( $parsed_url['path'], '/' ) . '?' . $parsed_url['query'];
@@ -1906,7 +2038,7 @@ class ExactDN {
1906
  // However some source images are served via PHP so check the no-query-string extension.
1907
  // For future proofing, this is a blacklist of common issues rather than a whitelist.
1908
  $extension = pathinfo( $image_url_parts['path'], PATHINFO_EXTENSION );
1909
- if ( empty( $extension ) || in_array( $extension, array( 'php', 'ashx' ) ) ) {
1910
  ewwwio_debug_message( 'bad extension' );
1911
  return $image_url;
1912
  }
@@ -1942,12 +2074,7 @@ class ExactDN {
1942
  ewwwio_debug_message( "exactdn url with args: $exactdn_url" );
1943
 
1944
  if ( isset( $image_url_parts['scheme'] ) && 'https' == $image_url_parts['scheme'] ) {
1945
- $exactdn_url = add_query_arg(
1946
- array(
1947
- 'ssl' => 1,
1948
- ),
1949
- $exactdn_url
1950
- );
1951
  $scheme = 'https';
1952
  }
1953
 
@@ -1988,6 +2115,11 @@ class ExactDN {
1988
  if ( 0 === strpos( $url, '//' ) ) {
1989
  $url = ( is_ssl() ? 'https:' : 'http:' ) . $url;
1990
  }
 
 
 
 
 
1991
  return parse_url( $url, $component );
1992
  }
1993
 
16
  class ExactDN {
17
 
18
  /**
19
+ * Allowed image extensions.
20
  *
21
  * @access private
22
  * @var array $extensions
29
  'png',
30
  );
31
 
32
+
33
+ /**
34
+ * A list of user-defined exclusions, populated by validate_user_exclusions().
35
+ *
36
+ * @access protected
37
+ * @var array $user_exclusions
38
+ */
39
+ protected $user_exclusions = array();
40
+
41
  /**
42
  * A list of image sizes registered for attachments.
43
  *
141
  add_filter( 'wp_calculate_image_srcset', array( $this, 'filter_srcset_array' ), 1001, 5 );
142
  add_filter( 'wp_calculate_image_sizes', array( $this, 'filter_sizes' ), 1, 2 ); // Early so themes can still filter.
143
 
144
+ // Filter for NextGEN image urls within JS.
145
+ add_filter( 'ngg_pro_lightbox_images_queue', array( $this, 'ngg_pro_lightbox_images_queue' ) );
146
+ add_filter( 'ngg_get_image_url', array( $this, 'ngg_get_image_url' ) );
147
+
148
  // DNS prefetching.
149
  add_action( 'wp_head', array( $this, 'dns_prefetch' ) );
150
 
172
 
173
  // Find the "local" domain.
174
  $upload_dir = wp_upload_dir( null, false );
175
+ $this->upload_domain = defined( 'EXACTDN_LOCAL_DOMAIN' ) && EXACTDN_LOCAL_DOMAIN ? $this->parse_url( EXACTDN_LOCAL_DOMAIN, PHP_URL_HOST ) : $this->parse_url( $upload_dir['baseurl'], PHP_URL_HOST );
176
  ewwwio_debug_message( "allowing images from here: $this->upload_domain" );
177
  $this->allowed_domains[] = $this->upload_domain;
178
  if ( strpos( $this->upload_domain, 'www' ) === false ) {
183
  $this->allowed_domains[] = $nonwww;
184
  }
185
  }
186
+ $wpml_domains = apply_filters( 'wpml_setting', array(), 'language_domains' );
187
+ if ( ewww_image_optimizer_iterable( $wpml_domains ) ) {
188
+ ewwwio_debug_message( 'wpml domains: ' . implode( ',', $wpml_domains ) );
189
+ $this->allowed_domains[] = $this->parse_url( get_option( 'home' ), PHP_URL_HOST );
190
+ foreach ( $wpml_domains as $wpml_domain ) {
191
+ $this->allowed_domains[] = $wpml_domain;
192
+ }
193
+ }
194
  $this->allowed_domains = apply_filters( 'exactdn_allowed_domains', $this->allowed_domains );
195
+ ewwwio_debug_message( 'allowed domains: ' . implode( ',', $this->allowed_domains ) );
196
+ $this->validate_user_exclusions();
197
  }
198
 
199
  /**
499
  return update_option( 'ewww_image_optimizer_exactdn_' . $option_name, $option_value, $autoload );
500
  }
501
 
502
+ /**
503
+ * Validate the user-defined exclusions for "all the things" rewriting.
504
+ */
505
+ function validate_user_exclusions() {
506
+ if ( defined( 'EXACTDN_EXCLUDE' ) && EXACTDN_EXCLUDE ) {
507
+ $user_exclusions = EXACTDN_EXCLUDE;
508
+ }
509
+ if ( ! empty( $user_exclusions ) ) {
510
+ if ( is_string( $user_exclusions ) ) {
511
+ $user_exclusions = array( $user_exclusions );
512
+ }
513
+ if ( is_array( $user_exclusions ) ) {
514
+ foreach ( $user_exclusions as $exclusion ) {
515
+ if ( false !== strpos( $exclusion, 'wp-content' ) ) {
516
+ $exclusion = preg_replace( '#([^"\'?>]+?)?wp-content/#i', '', $exclusion );
517
+ }
518
+ $this->user_exclusions[] = ltrim( $exclusion, '/' );
519
+ }
520
+ }
521
+ }
522
+ }
523
+
524
  /**
525
  * Match all images and any relevant <a> tags in a block of HTML.
526
  *
950
  if ( $this->exactdn_domain && $this->upload_domain ) {
951
  $escaped_upload_domain = str_replace( '.', '\.', ltrim( $this->upload_domain, 'w.' ) );
952
  ewwwio_debug_message( $escaped_upload_domain );
953
+ if ( ! empty( $this->user_exclusions ) ) {
954
+ $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 );
955
+ }
956
+ // Pre-empt rewriting of simple-social-icons SVG (because they aren't allowed in use tags.
957
+ $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 );
958
+ // Pre-empt rewriting of wp-includes and wp-content if the extension is not allowed by using a temporary placeholder.
959
+ $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 );
960
  $content = str_replace( 'wp-content/themes/jupiter"', '?wpcontent-bypass?/themes/jupiter"', $content );
961
+ $content = preg_replace( '#(https?)://(?:www\.)?' . $escaped_upload_domain . '/([^"\'?>]+?)?(nextgen-image|wp-includes|wp-content)/#i', '$1://' . $this->exactdn_domain . '/$2$3/', $content );
962
  $content = str_replace( '?wpcontent-bypass?', 'wp-content', $content );
963
  }
964
  }
1382
  is_array( $multipliers )
1383
  /** This filter is already documented in class-exactdn.php */
1384
  && ! apply_filters( 'exactdn_skip_image', false, $url, null )
1385
+ /** The original url is valid/allowed. */
1386
+ && $this->validate_image_url( $url )
1387
  /** Verify basic meta is intact. */
1388
  && isset( $image_meta['width'] ) && isset( $image_meta['height'] ) && isset( $image_meta['file'] )
1389
  /** Verify we have the requested width/height. */
1653
  return false;
1654
  }
1655
 
1656
+ // Ensure image extension is acceptable, unless it's a dynamic NextGEN image.
1657
+ if ( ! in_array( strtolower( pathinfo( $url_info['path'], PATHINFO_EXTENSION ) ), $this->extensions ) && false === strpos( $url_info['path'], 'nextgen-image/' ) ) {
1658
  ewwwio_debug_message( 'invalid extension' );
1659
  return false;
1660
  }
1754
  return is_array( self::$image_sizes ) ? self::$image_sizes : array();
1755
  }
1756
 
1757
+ /**
1758
+ * Handle image urls within the NextGEN pro lightbox displays.
1759
+ *
1760
+ * @param array $images An array of NextGEN images and associate attributes.
1761
+ * @return array The ExactDNified array of images.
1762
+ */
1763
+ function ngg_pro_lightbox_images_queue( $images ) {
1764
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1765
+ if ( ewww_image_optimizer_iterable( $images ) ) {
1766
+ foreach ( $images as $index => $image ) {
1767
+ if ( ! empty( $image['image'] ) && $this->validate_image_url( $image['image'] ) ) {
1768
+ $images[ $index ]['image'] = $this->generate_url( $image['image'] );
1769
+ }
1770
+ if ( ! empty( $image['thumb'] ) && $this->validate_image_url( $image['thumb'] ) ) {
1771
+ $images[ $index ]['thumb'] = $this->generate_url( $image['thumb'] );
1772
+ }
1773
+ if ( ! empty( $image['full_image'] ) && $this->validate_image_url( $image['full_image'] ) ) {
1774
+ $images[ $index ]['full_image'] = $this->generate_url( $image['full_image'] );
1775
+ }
1776
+ if ( ewww_image_optimizer_iterable( $image['srcsets'] ) ) {
1777
+ foreach ( $image['srcsets'] as $size => $srcset ) {
1778
+ if ( $this->validate_image_url( $srcset ) ) {
1779
+ $images[ $index ]['srcsets'][ $size ] = $this->generate_url( $srcset );
1780
+ }
1781
+ }
1782
+ }
1783
+ if ( ewww_image_optimizer_iterable( $image['full_srcsets'] ) ) {
1784
+ foreach ( $image['full_srcsets'] as $size => $srcset ) {
1785
+ if ( $this->validate_image_url( $srcset ) ) {
1786
+ $images[ $index ]['full_srcsets'][ $size ] = $this->generate_url( $srcset );
1787
+ }
1788
+ }
1789
+ }
1790
+ }
1791
+ }
1792
+ return $images;
1793
+ }
1794
+
1795
+ /**
1796
+ * Handle image urls within NextGEN.
1797
+ *
1798
+ * @param string $image A url for a NextGEN image.
1799
+ * @return string The ExactDNified image url.
1800
+ */
1801
+ function ngg_get_image_url( $image ) {
1802
+ // Don't foul up the admin side of things, unless a plugin wants to.
1803
+ if ( is_admin() &&
1804
+ /**
1805
+ * Provide plugins a way of running ExactDN for images in the WordPress Dashboard (wp-admin).
1806
+ *
1807
+ * @param bool false Stop ExactDN from being run on the Dashboard. Default to false, use true to run in wp-admin.
1808
+ * @param array $args {
1809
+ * Array of image details.
1810
+ *
1811
+ * @type string|bool $image Image URL or false.
1812
+ * @type int $attachment_id Attachment ID of the image.
1813
+ * }
1814
+ */
1815
+ false === apply_filters( 'exactdn_admin_allow_ngg_url', false, $image )
1816
+ ) {
1817
+ return $image;
1818
+ }
1819
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1820
+ if ( $this->validate_image_url( $image ) ) {
1821
+ return $this->generate_url( $image );
1822
+ }
1823
+ return $image;
1824
+ }
1825
+
1826
  /**
1827
  * Enqueue ExactDN helper script
1828
  */
1867
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1868
  $parsed_url = $this->parse_url( $url );
1869
 
1870
+ if ( $this->user_exclusions ) {
1871
+ foreach ( $this->user_exclusions as $exclusion ) {
1872
+ if ( false !== strpos( $url, $exclusion ) ) {
1873
+ ewwwio_debug_message( "user excluded $url via $exclusion" );
1874
+ return $url;
1875
+ }
1876
+ }
1877
+ }
1878
  // Unable to parse.
1879
  if ( ! $parsed_url || ! is_array( $parsed_url ) || empty( $parsed_url['host'] ) || empty( $parsed_url['path'] ) ) {
1880
  ewwwio_debug_message( 'src url no good' );
1900
  return $url;
1901
  }
1902
 
1903
+ global $wp_version;
1904
  // If a resource doesn't have a version string, we add one to help with cache-busting.
1905
+ if ( ( empty( $parsed_url['query'] ) || 'ver=' . $wp_version == $parsed_url['query'] ) && false !== strpos( $url, 'wp-content/' ) ) {
1906
  $modified = ewww_image_optimizer_function_exists( 'filemtime' ) ? filemtime( get_template_directory() ) : '';
1907
  if ( empty( $modified ) ) {
1908
  $modified = (int) EWWW_IMAGE_OPTIMIZER_VERSION;
1913
  * @param string EWWW IO version.
1914
  */
1915
  $parsed_url['query'] = apply_filters( 'exactdn_version_string', "m=$modified" );
1916
+ } elseif ( empty( $parsed_url['query'] ) ) {
1917
+ $parsed_url['query'] = '';
1918
  }
1919
 
1920
  $exactdn_url = '//' . $this->exactdn_domain . '/' . ltrim( $parsed_url['path'], '/' ) . '?' . $parsed_url['query'];
2038
  // However some source images are served via PHP so check the no-query-string extension.
2039
  // For future proofing, this is a blacklist of common issues rather than a whitelist.
2040
  $extension = pathinfo( $image_url_parts['path'], PATHINFO_EXTENSION );
2041
+ if ( ( empty( $extension ) && false === strpos( $image_url_parts['path'], 'nextgen-image/' ) ) || in_array( $extension, array( 'php', 'ashx' ) ) ) {
2042
  ewwwio_debug_message( 'bad extension' );
2043
  return $image_url;
2044
  }
2074
  ewwwio_debug_message( "exactdn url with args: $exactdn_url" );
2075
 
2076
  if ( isset( $image_url_parts['scheme'] ) && 'https' == $image_url_parts['scheme'] ) {
2077
+ $exactdn_url = add_query_arg( 'ssl', 1, $exactdn_url );
 
 
 
 
 
2078
  $scheme = 'https';
2079
  }
2080
 
2115
  if ( 0 === strpos( $url, '//' ) ) {
2116
  $url = ( is_ssl() ? 'https:' : 'http:' ) . $url;
2117
  }
2118
+ if ( false === strpos( $url, 'http' ) && '/' !== substr( $url, 0, 1 ) ) {
2119
+ $url = ( is_ssl() ? 'https://' : 'http://' ) . $url;
2120
+ }
2121
+ // Because encoded ampersands in the filename break things.
2122
+ $url = str_replace( '&#038;', '&', $url );
2123
  return parse_url( $url, $component );
2124
  }
2125
 
common.php CHANGED
@@ -10,31 +10,26 @@
10
  * @package EWWW_Image_Optimizer
11
  */
12
 
13
- // TODO: use <picture> element to serve webp (#54).
14
  // TODO: attempt lazy load support with a3 plugin and one from automattic for alt webp. or are we back here: https://developers.google.com/web/fundamentals/performance/lazy-loading-guidance/images-and-video/
15
- // TODO: prevent bad ajax errors from firing when we click the toggle on the Optimization Log, and the plugin status from doing 403s...
16
- // TODO: use a transient to do health checks on the schedule optimizer.
17
- // TODO: add a column to track compression level used for each image, and later implement a way to (re)compress at a specific compression level.
18
  // TODO: might be able to use the Custom Bulk Actions in 4.7 to support the bulk optimize drop-down menu.
19
  // TODO: need to make the scheduler so it can resume without having to re-run the queue population, and then we can probably also flush the queue when scheduled opt starts, but later it would be nice to implement the bulk_loop as the aux_loop so that it could handle media properly.
20
- // TODO: implement a search for the bulk table, or maybe we should just move it to it's own page?
21
  // TODO: Add a custom async function for parallel mode to store image as pending and use the row ID instead of relative path.
22
  // TODO: write some tests for update_table and check_table, find_already_opt, and remove_dups.
23
  // TODO: write some conversion tests.
24
- // TODO: do a bottom paginator for the show optimized images table.
25
  // TODO: check this patch, to see if the use of 'full' causes any issues: https://core.trac.wordpress.org/ticket/37840 .
26
  // TODO: integrate AGR, since it's "abandoned", but possibly using gifsicle for better GIFs.
27
  // TODO: use this: https://codex.wordpress.org/AJAX_in_Plugins#The_post-load_JavaScript_Event .
28
  // TODO: on images without srscet, add 2x and 3x versions anyway.
29
- // TODO: can svg/use tags be exluded from all the things?
30
  // TODO: match Adaptive Images functionality with ExactDN.
31
  // TODO: handle relative urls with ExactDN.
32
- // TODO: can we fix minify/combine for WP Rocket and WPFC when ExactDN is active?
 
33
  if ( ! defined( 'ABSPATH' ) ) {
34
  exit;
35
  }
36
 
37
- define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '423.0' );
38
 
39
  // Initialize a couple globals.
40
  $ewww_debug = '';
@@ -82,6 +77,8 @@ if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_noauto' ) ) {
82
  add_filter( 'emr_unfiltered_get_attached_file', 'ewww_image_optimizer_image_sizes' );
83
  // Checks to see if thumb regen or other similar operation is running via REST API.
84
  add_action( 'rest_api_init', 'ewww_image_optimizer_restapi_compat_check' );
 
 
85
  // Enables direct integration to the editor's save function.
86
  add_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
87
  }
@@ -176,6 +173,8 @@ add_action( 'wp_ajax_ewww_manual_restore', 'ewww_image_optimizer_manual' );
176
  add_action( 'wp_ajax_ewww_manual_cloud_restore', 'ewww_image_optimizer_manual' );
177
  // AJAX action hook for manually restoring a single image backup from the API.
178
  add_action( 'wp_ajax_ewww_manual_cloud_restore_single', 'ewww_image_optimizer_cloud_restore_single_image_handler' );
 
 
179
  // Adds script to highlight mis-sized images on the front-end (for logged in admins only).
180
  add_action( 'wp_enqueue_scripts', 'ewww_image_optimizer_resize_detection_script' );
181
  // Adds a button on the admin bar to allow highlighting mis-sized images on-demand.
@@ -207,34 +206,20 @@ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) && empty(
207
  }
208
  // If Alt WebP Rewriting is enabled.
209
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) ) {
210
- // Start an output buffer before any output starts.
211
- add_action( 'template_redirect', 'ewww_image_optimizer_webp_buffer_start' );
212
- if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
213
- // Load the non-minified, non-inline version of the webp rewrite script.
214
- add_action( 'wp_enqueue_scripts', 'ewww_image_optimizer_webp_debug_script' );
215
- } elseif ( defined( 'EWWW_IMAGE_OPTIMIZER_WEBP_EXTERNAL_SCRIPT' ) && EWWW_IMAGE_OPTIMIZER_WEBP_EXTERNAL_SCRIPT ) {
216
- // Load the minified, non-inline version of the webp rewrite script.
217
- add_action( 'wp_enqueue_scripts', 'ewww_image_optimizer_webp_min_script' );
218
- } else {
219
- // Loads jQuery and the minified inline webp rewrite script.
220
- add_action( 'wp_enqueue_scripts', 'ewww_image_optimizer_webp_load_jquery' );
221
- if ( ! function_exists( 'wp_add_inline_script' ) || ( defined( 'EWWW_IMAGE_OPTIMIZER_WEBP_INLINE_FALLBACK' ) && EWWW_IMAGE_OPTIMIZER_WEBP_INLINE_FALLBACK ) ) {
222
- add_action( 'wp_head', 'ewww_image_optimizer_webp_inline_script' );
223
- }
224
- }
225
  }
226
 
227
  if ( defined( 'WP_CLI' ) && WP_CLI ) {
228
  require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-ewwwio-cli.php' );
229
  }
230
 
231
- /**
232
- * Display a notice that PHP version 5.4 support is going away.
233
- */
234
- function ewww_image_optimizer_php54_warning() {
235
- echo '<div id="ewww-image-optimizer-notice-php54" class="notice notice-info is-dismissible"><p><a href="https://docs.ewww.io/article/55-upgrading-php" target="_blank" data-beacon-article="5ab2baa6042863478ea7c2ae">' . esc_html__( 'The next major release of EWWW Image Optimizer will require PHP 5.5 or greater. Newer versions of PHP, like 5.6, 7.0 and 7.1, are significantly faster and much more secure. If you are unsure how to upgrade to a supported version, ask your webhost for instructions.', 'ewww-image-optimizer' ) . '</a></p></div>';
236
- }
237
-
238
  /**
239
  * Skips optimization when a file is within EWWW IO's own folder.
240
  *
@@ -309,715 +294,6 @@ function ewww_image_optimizer_wpfc_webp_enabled() {
309
  return false;
310
  }
311
 
312
- /**
313
- * Starts an output buffer and registers the callback function to do WebP replacement.
314
- */
315
- function ewww_image_optimizer_webp_buffer_start() {
316
- ob_start( 'ewww_image_optimizer_filter_webp_page_output' );
317
- }
318
-
319
- /**
320
- * Copies attributes from the original img element to the noscript element.
321
- *
322
- * @param object $image A DOMElement (extension of DOMNode) representing an img element.
323
- * @param object $nscript Passed by reference, a DOMElement that will be given all the (known) attributes of $image.
324
- * @param string $prefix Optional. Value to prepend to all attribute names. Default 'data-'.
325
- */
326
- function ewww_image_optimizer_webp_attr_copy( $image, &$nscript, $prefix = 'data-' ) {
327
- if ( ! is_object( $image ) || ! is_object( $nscript ) ) {
328
- return;
329
- }
330
- $attributes = array(
331
- 'align',
332
- 'alt',
333
- 'border',
334
- 'crossorigin',
335
- 'height',
336
- 'hspace',
337
- 'ismap',
338
- 'longdesc',
339
- 'usemap',
340
- 'vspace',
341
- 'width',
342
- 'accesskey',
343
- 'class',
344
- 'contenteditable',
345
- 'contextmenu',
346
- 'dir',
347
- 'draggable',
348
- 'dropzone',
349
- 'hidden',
350
- 'id',
351
- 'lang',
352
- 'spellcheck',
353
- 'style',
354
- 'tabindex',
355
- 'title',
356
- 'translate',
357
- 'sizes',
358
- 'data-caption',
359
- 'data-lazy-type',
360
- 'data-attachment-id',
361
- 'data-permalink',
362
- 'data-orig-size',
363
- 'data-comments-opened',
364
- 'data-image-meta',
365
- 'data-image-title',
366
- 'data-image-description',
367
- 'data-event-trigger',
368
- 'data-highlight-color',
369
- 'data-highlight-opacity',
370
- 'data-highlight-border-color',
371
- 'data-highlight-border-width',
372
- 'data-highlight-border-opacity',
373
- 'data-no-lazy',
374
- 'data-lazy',
375
- 'data-large_image_width',
376
- 'data-large_image_height',
377
- );
378
- foreach ( $attributes as $attribute ) {
379
- if ( $image->getAttribute( $attribute ) ) {
380
- $nscript->setAttribute( $prefix . $attribute, $image->getAttribute( $attribute ) );
381
- }
382
- }
383
- }
384
-
385
- /**
386
- * Replaces images within a srcset attribute with their .webp derivatives.
387
- *
388
- * @param string $srcset A valid srcset attribute from an img element.
389
- * @param string $home_url The 'home' url for the WordPress site.
390
- * @param bool $valid_path True if a CDN path has been specified and matches the img element.
391
- * @return bool|string False if no changes were made, or the new srcset if any WebP images replaced the originals.
392
- */
393
- function ewww_image_optimizer_webp_srcset_replace( $srcset, $home_url, $valid_path ) {
394
- $srcset_urls = explode( ' ', $srcset );
395
- $found_webp = false;
396
- if ( ewww_image_optimizer_iterable( $srcset_urls ) ) {
397
- ewwwio_debug_message( 'found srcset urls' );
398
- foreach ( $srcset_urls as $srcurl ) {
399
- if ( is_numeric( substr( $srcurl, 0, 1 ) ) ) {
400
- continue;
401
- }
402
- $srcfilepath = ABSPATH . str_replace( $home_url, '', $srcurl );
403
- ewwwio_debug_message( "looking for srcurl on disk: $srcfilepath" );
404
- if ( $valid_path || is_file( $srcfilepath . '.webp' ) ) {
405
- $srcset = preg_replace( "|$srcurl|", $srcurl . '.webp', $srcset );
406
- $found_webp = true;
407
- ewwwio_debug_message( "replacing $srcurl in $srcset" );
408
- }
409
- }
410
- }
411
- if ( $found_webp ) {
412
- return $srcset;
413
- } else {
414
- return false;
415
- }
416
- }
417
-
418
- /**
419
- * Replaces images with the Jetpack data attributes with their .webp derivatives.
420
- *
421
- * @param object $image A DOMElement (extension of DOMNode) representing an img element.
422
- * @param object $nscript Passed by reference, a DOMElement that will be assigned the jetpack data attributes.
423
- * @param string $home_url The 'home' url for the WordPress site.
424
- * @param bool $valid_path True if a CDN path has been specified and matches the img element.
425
- */
426
- function ewww_image_optimizer_webp_jetpack_replace( $image, &$nscript, $home_url, $valid_path ) {
427
- if ( $image->getAttribute( 'data-orig-file' ) ) {
428
- $origfilepath = ABSPATH . str_replace( $home_url, '', $image->getAttribute( 'data-orig-file' ) );
429
- ewwwio_debug_message( "looking for data-orig-file on disk: $origfilepath" );
430
- if ( $valid_path || is_file( $origfilepath . '.webp' ) ) {
431
- $nscript->setAttribute( 'data-webp-orig-file', $image->getAttribute( 'data-orig-file' ) . '.webp' );
432
- ewwwio_debug_message( "replacing $origfilepath in data-orig-file" );
433
- }
434
- $nscript->setAttribute( 'data-orig-file', $image->getAttribute( 'data-orig-file' ) );
435
- }
436
- if ( $image->getAttribute( 'data-medium-file' ) ) {
437
- $mediumfilepath = ABSPATH . str_replace( $home_url, '', $image->getAttribute( 'data-medium-file' ) );
438
- ewwwio_debug_message( "looking for data-medium-file on disk: $mediumfilepath" );
439
- if ( $valid_path || is_file( $mediumfilepath . '.webp' ) ) {
440
- $nscript->setAttribute( 'data-webp-medium-file', $image->getAttribute( 'data-medium-file' ) . '.webp' );
441
- ewwwio_debug_message( "replacing $mediumfilepath in data-medium-file" );
442
- }
443
- $nscript->setAttribute( 'data-medium-file', $image->getAttribute( 'data-medium-file' ) );
444
- }
445
- if ( $image->getAttribute( 'data-large-file' ) ) {
446
- $largefilepath = ABSPATH . str_replace( $home_url, '', $image->getAttribute( 'data-large-file' ) );
447
- ewwwio_debug_message( "looking for data-large-file on disk: $largefilepath" );
448
- if ( $valid_path || is_file( $largefilepath . '.webp' ) ) {
449
- $nscript->setAttribute( 'data-webp-large-file', $image->getAttribute( 'data-large-file' ) . '.webp' );
450
- ewwwio_debug_message( "replacing $largefilepath in data-large-file" );
451
- }
452
- $nscript->setAttribute( 'data-large-file', $image->getAttribute( 'data-large-file' ) );
453
- }
454
- }
455
-
456
- /**
457
- * Replaces images with the WooCommerce data attributes with their .webp derivatives.
458
- *
459
- * @param object $image A DOMElement (extension of DOMNode) representing an img element.
460
- * @param object $nscript Passed by reference, a DOMElement that will be assigned the WooCommerce data attributes.
461
- * @param string $home_url The 'home' url for the WordPress site.
462
- * @param bool $valid_path True if a CDN path has been specified and matches the img element.
463
- */
464
- function ewww_image_optimizer_webp_woocommerce_replace( $image, &$nscript, $home_url, $valid_path ) {
465
- if ( $image->getAttribute( 'data-large_image' ) ) {
466
- $largefilepath = ABSPATH . str_replace( $home_url, '', $image->getAttribute( 'data-large_image' ) );
467
- ewwwio_debug_message( "looking for data-large_image on disk: $largefilepath" );
468
- if ( $valid_path || is_file( $largefilepath . '.webp' ) ) {
469
- $nscript->setAttribute( 'data-webp-large_image', $image->getAttribute( 'data-large_image' ) . '.webp' );
470
- ewwwio_debug_message( "replacing $largefilepath in data-large_image" );
471
- }
472
- $nscript->setAttribute( 'data-large_image', $image->getAttribute( 'data-large_image' ) );
473
- }
474
- if ( $image->getAttribute( 'data-src' ) ) {
475
- $srcpath = ABSPATH . str_replace( $home_url, '', $image->getAttribute( 'data-src' ) );
476
- ewwwio_debug_message( "looking for data-src on disk: $srcpath" );
477
- if ( $valid_path || is_file( $srcpath . '.webp' ) ) {
478
- $nscript->setAttribute( 'data-webp-src', $image->getAttribute( 'data-src' ) . '.webp' );
479
- ewwwio_debug_message( "replacing $srcpath in data-src" );
480
- }
481
- $nscript->setAttribute( 'data-src', $image->getAttribute( 'data-src' ) );
482
- }
483
- }
484
-
485
- /**
486
- * Search for amp-img elements and rewrite them with fallback elements for WebP replacement.
487
- *
488
- * Any amp-img elements will be given the fallback attribute and wrapped inside another amp-img
489
- * element with a WebP src attribute if WebP derivatives exist.
490
- *
491
- * @param string $buffer The entire HTML page from the output buffer.
492
- * @return string The altered buffer containing the full page with WebP images inserted.
493
- */
494
- function ewww_image_optimizer_filter_amp_webp( $buffer ) {
495
- ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
496
- // Modify buffer here, and then return the updated code.
497
- if ( class_exists( 'DOMDocument' ) ) {
498
- $html = new DOMDocument;
499
-
500
- $libxml_previous_error_reporting = libxml_use_internal_errors( true );
501
-
502
- $html->formatOutput = false;
503
- $html->encoding = 'utf-8';
504
- if ( defined( 'LIBXML_VERSION' ) && LIBXML_VERSION < 20800 ) {
505
- ewwwio_debug_message( 'libxml version too old for amp: ' . LIBXML_VERSION );
506
- return $buffer;
507
- } elseif ( ! defined( 'LIBXML_VERSION' ) ) {
508
- // When libxml is too old, we dare not modify the buffer.
509
- ewwwio_debug_message( 'cannot detect libxml version for amp' );
510
- return $buffer;
511
- }
512
- $html->loadHTML( $buffer );
513
- ewwwio_debug_message( 'parsing AMP as html' );
514
- $html->encoding = 'utf-8';
515
- $home_url = get_site_url();
516
- $webp_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' );
517
- if ( ! is_array( $webp_paths ) ) {
518
- $webp_paths = array();
519
- }
520
- $home_relative_url = preg_replace( '/https?:/', '', $home_url );
521
- $images = $html->getElementsByTagName( 'amp-img' );
522
- if ( ewww_image_optimizer_iterable( $images ) ) {
523
- foreach ( $images as $image ) {
524
- if ( 'amp-img' == $image->parentNode->tagName ) {
525
- continue;
526
- }
527
- $srcset = '';
528
- ewwwio_debug_message( 'parsing an AMP image' );
529
- $file = $image->getAttribute( 'src' );
530
- $valid_path = false;
531
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
532
- // Check for CDN paths within the img src attribute.
533
- foreach ( $webp_paths as $webp_path ) {
534
- if ( strpos( $file, $webp_path ) !== false ) {
535
- $valid_path = true;
536
- }
537
- }
538
- }
539
- if ( strpos( $file, $home_relative_url ) === 0 ) {
540
- $filepath = str_replace( $home_relative_url, ABSPATH, $file );
541
- } else {
542
- $filepath = str_replace( $home_url, ABSPATH, $file );
543
- }
544
- ewwwio_debug_message( "the AMP image is at $filepath" );
545
- // If a CDN path match was found, or .webp image existsence is confirmed, and this is not a lazy-load 'dummy' image.
546
- if ( ( $valid_path || is_file( $filepath . '.webp' ) ) && ! strpos( $file, 'assets/images/dummy.png' ) && ! strpos( $file, 'base64,R0lGOD' ) && ! strpos( $file, 'lazy-load/images/1x1' ) ) {
547
- $parent_image = $image->cloneNode();
548
- $parent_image->setAttribute( 'src', $file . '.webp' );
549
- if ( $image->getAttribute( 'srcset' ) ) {
550
- $srcset = $image->getAttribute( 'srcset' );
551
- $srcset_webp = ewww_image_optimizer_webp_srcset_replace( $srcset, $home_url, $valid_path );
552
- if ( $srcset_webp ) {
553
- $parent_image->setAttribute( 'srcset', $srcset_webp );
554
- }
555
- }
556
- $fallback_attr = $html->createAttribute( 'fallback' );
557
- $image->appendChild( $fallback_attr );
558
- $image->parentNode->replaceChild( $parent_image, $image );
559
- $parent_image->appendChild( $image );
560
- }
561
- } // End foreach().
562
- } // End if().
563
- ewwwio_debug_message( 'preparing to dump page back to $buffer' );
564
- $buffer = $html->saveHTML( $html->documentElement );
565
- libxml_clear_errors();
566
- libxml_use_internal_errors( $libxml_previous_error_reporting );
567
- if ( false ) { // Set to true for extra debugging.
568
- ewwwio_debug_message( 'buffer after replacement' );
569
- ewwwio_debug_message( substr( $buffer, 0, 500 ) );
570
- }
571
- } // End if().
572
- if ( false ) { // Set to true for extra logging.
573
- ewww_image_optimizer_debug_log();
574
- }
575
- return $buffer;
576
- }
577
-
578
- /**
579
- * Search for img elements and rewrite them with noscript elements for WebP replacement.
580
- *
581
- * Any img elements or elements that may be used in place of img elements by JS are checked to see
582
- * if WebP derivatives exist. The element is then wrapped within a noscript element for fallback,
583
- * and noscript element receives a copy of the attributes from the img along with webp replacement
584
- * values for those attributes.
585
- *
586
- * @param string $buffer The full HTML page generated since the output buffer was started.
587
- * @return string The altered buffer containing the full page with WebP images inserted.
588
- */
589
- function ewww_image_optimizer_filter_webp_page_output( $buffer ) {
590
- ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
591
- // If this is an admin page, don't filter it.
592
- if ( ( empty( $buffer ) || is_admin() ) ) {
593
- return $buffer;
594
- }
595
- // If Cache Enabler's WebP option is enabled, don't filter it.
596
- if ( ewww_image_optimizer_ce_webp_enabled() ) {
597
- return $buffer;
598
- }
599
- $uri = $_SERVER['REQUEST_URI'];
600
- // Based on the uri, if this is a cornerstone editing page, don't filter the response.
601
- if ( ! empty( $_GET['cornerstone'] ) || strpos( $uri, 'cornerstone-endpoint' ) !== false ) {
602
- return $buffer;
603
- }
604
- if ( ! empty( $_GET['et_fb'] ) ) {
605
- return $buffer;
606
- }
607
- if ( ! empty( $_GET['tatsu'] ) ) {
608
- return $buffer;
609
- }
610
- if ( ! empty( $_POST['action'] ) && 'tatsu_get_concepts' === $_POST['action'] ) {
611
- return $buffer;
612
- }
613
- // Modify buffer here, and then return the updated code.
614
- if ( class_exists( 'DOMDocument' ) ) {
615
- // If this is XML (not XHTML), don't modify the page.
616
- if ( preg_match( '/<\?xml/', $buffer ) ) {
617
- return $buffer;
618
- }
619
- $expanded_head = false;
620
- preg_match( '/.+<head ?\>/s', $buffer, $html_head );
621
- if ( empty( $html_head ) ) {
622
- ewwwio_debug_message( 'did not find head tag' );
623
- preg_match( '/.+<head [^>]*>/s', $buffer, $html_head );
624
- if ( empty( $html_head ) ) {
625
- ewwwio_debug_message( 'did not find expanded head tag either' );
626
- return $buffer;
627
- }
628
- }
629
- if ( strpos( $buffer, 'amp-boilerplate' ) ) {
630
- ewwwio_debug_message( 'AMP page processing' );
631
- return $buffer;
632
- }
633
-
634
- $html = new DOMDocument;
635
-
636
- $libxml_previous_error_reporting = libxml_use_internal_errors( true );
637
-
638
- $html->formatOutput = false;
639
- $html->encoding = 'utf-8';
640
- if ( defined( 'LIBXML_VERSION' ) && LIBXML_VERSION < 20800 && ewww_image_optimizer_function_exists( 'mb_convert_encoding' ) ) {
641
- ewwwio_debug_message( 'libxml version: ' . LIBXML_VERSION );
642
- // Converts the buffer from utf-8 to html-entities.
643
- $buffer = mb_convert_encoding( $buffer, 'HTML-ENTITIES', 'UTF-8' );
644
- } elseif ( ! defined( 'LIBXML_VERSION' ) ) {
645
- // When libxml is too old, we dare not modify the buffer.
646
- ewwwio_debug_message( 'cannot detect libxml version' );
647
- return $buffer;
648
- }
649
- if ( preg_match( '/<.DOCTYPE.+xhtml/', $buffer ) ) {
650
- $html->recover = true;
651
- $xhtml_parse = $html->loadXML( $buffer );
652
- ewwwio_debug_message( 'parsing as xhtml' );
653
- } elseif ( empty( $xhtml_parse ) ) {
654
- $html->loadHTML( $buffer );
655
- ewwwio_debug_message( 'parsing as html' );
656
- }
657
- $html->encoding = 'utf-8';
658
- $home_url = get_site_url();
659
- ewwwio_debug_message( "home url: $home_url" );
660
- if ( class_exists( 'ExactDN' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
661
- global $exactdn;
662
- $exactdn_domain = $exactdn->get_exactdn_domain();
663
- $home_url_parts = $exactdn->parse_url( $home_url );
664
- if ( ! empty( $home_url_parts['host'] ) && $exactdn_domain ) {
665
- $home_url = str_replace( $home_url_parts['host'], $exactdn_domain, $home_url );
666
- ewwwio_debug_message( "new home url: $home_url" );
667
- }
668
- }
669
- $webp_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' );
670
- if ( ! is_array( $webp_paths ) ) {
671
- $webp_paths = array();
672
- }
673
- $home_relative_url = preg_replace( '/https?:/', '', $home_url );
674
- $images = $html->getElementsByTagName( 'img' );
675
- if ( ewww_image_optimizer_iterable( $images ) ) {
676
- foreach ( $images as $image ) {
677
- if ( 'noscript' == $image->parentNode->tagName ) {
678
- continue;
679
- }
680
- $srcset = '';
681
- $valid_path = false;
682
- ewwwio_debug_message( 'parsing an image' );
683
- $file = $image->getAttribute( 'src' );
684
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
685
- // Check for CDN paths within the img src attribute.
686
- foreach ( $webp_paths as $webp_path ) {
687
- if ( strpos( $file, $webp_path ) !== false ) {
688
- $valid_path = true;
689
- }
690
- }
691
- }
692
- if ( strpos( $file, $home_relative_url ) === 0 ) {
693
- $filepath = str_replace( $home_relative_url, ABSPATH, $file );
694
- } else {
695
- $filepath = str_replace( $home_url, ABSPATH, $file );
696
- }
697
- ewwwio_debug_message( "the image is at $filepath" );
698
- // If a CDN path match was found, or .webp image existsence is confirmed, and this is not a lazy-load 'dummy' image.
699
- if ( ( $valid_path || is_file( $filepath . '.webp' ) ) && ! strpos( $file, 'assets/images/dummy.png' ) && ! strpos( $file, 'base64,R0lGOD' ) && ! strpos( $file, 'lazy-load/images/1x1' ) ) {
700
- $nscript = $html->createElement( 'noscript' );
701
- $nscript->setAttribute( 'data-img', $file );
702
- $nscript->setAttribute( 'data-webp', $file . '.webp' );
703
- if ( $image->getAttribute( 'srcset' ) ) {
704
- $srcset = $image->getAttribute( 'srcset' );
705
- $srcset_webp = ewww_image_optimizer_webp_srcset_replace( $srcset, $home_url, $valid_path );
706
- if ( $srcset_webp ) {
707
- $nscript->setAttribute( 'data-srcset-webp', $srcset_webp );
708
- }
709
- $nscript->setAttribute( 'data-srcset-img', $srcset );
710
- }
711
- if ( $image->getAttribute( 'data-orig-file' ) && $image->getAttribute( 'data-medium-file' ) && $image->getAttribute( 'data-large-file' ) ) {
712
- ewww_image_optimizer_webp_jetpack_replace( $image, $nscript, $home_url, $valid_path );
713
- }
714
- if ( $image->getAttribute( 'data-large_image' ) && $image->getAttribute( 'data-src' ) ) {
715
- ewww_image_optimizer_webp_woocommerce_replace( $image, $nscript, $home_url, $valid_path );
716
- }
717
- ewww_image_optimizer_webp_attr_copy( $image, $nscript );
718
- $nscript->setAttribute( 'class', 'ewww_webp' );
719
- $image->parentNode->replaceChild( $nscript, $image );
720
- $nscript->appendChild( $image );
721
- }
722
- // Look for NextGEN attributes that need to be altered.
723
- if ( empty( $file ) && $image->getAttribute( 'data-src' ) && $image->getAttribute( 'data-thumbnail' ) ) {
724
- $file = $image->getAttribute( 'data-src' );
725
- $thumb = $image->getAttribute( 'data-thumbnail' );
726
- ewwwio_debug_message( "checking webp for ngg data-src: $file" );
727
- $filepath = ABSPATH . str_replace( $home_url, '', $file );
728
- ewwwio_debug_message( "checking webp for ngg data-thumbnail: $thumb" );
729
- $thumbpath = ABSPATH . str_replace( $home_url, '', $thumb );
730
- if ( ! $valid_path && ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
731
- // Check the image for configured CDN paths.
732
- foreach ( $webp_paths as $webp_path ) {
733
- if ( strpos( $file, $webp_path ) !== false ) {
734
- $valid_path = true;
735
- }
736
- }
737
- }
738
- if ( $valid_path || is_file( $filepath . '.webp' ) ) {
739
- ewwwio_debug_message( "found webp for ngg data-src: $filepath" );
740
- $image->setAttribute( 'data-webp', $file . '.webp' );
741
- }
742
- if ( $valid_path || is_file( $thumbpath . '.webp' ) ) {
743
- ewwwio_debug_message( "found webp for ngg data-thumbnail: $thumbpath" );
744
- $image->setAttribute( 'data-webp-thumbnail', $thumb . '.webp' );
745
- }
746
- }
747
- // NOTE: lazy loads are shutoff for now, since they don't work consistently
748
- // WP Retina 2x lazy loads.
749
- if ( false && empty( $file ) && $image->getAttribute( 'data-srcset' ) && strpos( $image->getAttribute( 'class' ), 'lazyload' ) ) {
750
- $srcset = $image->getAttribute( 'data-srcset' );
751
- if ( ! $valid_path && ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
752
- // Check the image for configured CDN paths.
753
- foreach ( $webp_paths as $webp_path ) {
754
- if ( strpos( $srcset, $webp_path ) !== false ) {
755
- $valid_path = true;
756
- }
757
- }
758
- }
759
- $srcset_webp = ewww_image_optimizer_webp_srcset_replace( $srcset, $home_url, $valid_path );
760
- if ( $srcset_webp ) {
761
- $nimage = $html->createElement( 'img' );
762
- $nimage->setAttribute( 'data-srcset-webp', $srcset_webp );
763
- $nimage->setAttribute( 'data-srcset-img', $srcset );
764
- ewww_image_optimizer_webp_attr_copy( $image, $nimage, '' );
765
- $nimage->setAttribute( 'class', $image->getAttribute( 'class' ) . ' ewww_webp_lazy_retina' );
766
- $image->parentNode->replaceChild( $nimage, $image );
767
- }
768
- }
769
- // Hueman theme lazy-loads.
770
- if ( false && ! empty( $file ) && strpos( $file, 'image/gif;base64,R0lGOD' ) && $image->getAttribute( 'data-src' ) && $image->getAttribute( 'data-srcset' ) ) {
771
- $dummy = $file;
772
- $file = $image->getAttribute( 'data-src' );
773
- ewwwio_debug_message( "checking webp for hueman data-src: $file" );
774
- $filepath = ABSPATH . str_replace( $home_url, '', $file );
775
- if ( ! $valid_path && ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
776
- // Check the image for configured CDN paths.
777
- foreach ( $webp_paths as $webp_path ) {
778
- if ( strpos( $file, $webp_path ) !== false ) {
779
- $valid_path = true;
780
- }
781
- }
782
- }
783
- if ( $valid_path || is_file( $filepath . '.webp' ) ) {
784
- ewwwio_debug_message( "found webp for Hueman lazyload: $filepath" );
785
- $nscript = $html->createElement( 'noscript' );
786
- $nscript->setAttribute( 'data-src', $dummy );
787
- $nscript->setAttribute( 'data-img', $file );
788
- $nscript->setAttribute( 'data-webp-src', $file . '.webp' );
789
- $image->setAttribute( 'src', $file );
790
- if ( $image->getAttribute( 'data-srcset' ) ) {
791
- $srcset = $image->getAttribute( 'data-srcset' );
792
- $srcset_webp = ewww_image_optimizer_webp_srcset_replace( $srcset, $home_url, $valid_path );
793
- if ( $srcset_webp ) {
794
- $nscript->setAttribute( 'data-srcset-webp', $srcset_webp );
795
- }
796
- $nscript->setAttribute( 'data-srcset-img', $srcset );
797
- }
798
- ewww_image_optimizer_webp_attr_copy( $image, $nscript );
799
- $nscript->setAttribute( 'class', 'ewww_webp_lazy_hueman' );
800
- $image->parentNode->replaceChild( $nscript, $image );
801
- $nscript->appendChild( $image );
802
- }
803
- }
804
- // Lazy Load plugin (and hopefully Cherry variant) and BJ Lazy Load.
805
- if ( false && ! empty( $file ) && ( strpos( $file, 'image/gif;base64,R0lGOD' ) || strpos( $file, 'lazy-load/images/1x1' ) ) && $image->getAttribute( 'data-lazy-src' ) && ! empty( $image->nextSibling ) && 'noscript' == $image->nextSibling->nodeName ) {
806
- $dummy = $file;
807
- $nimage = $html->createElement( 'img' );
808
- $nimage->setAttribute( 'src', $dummy );
809
- $file = $image->getAttribute( 'data-lazy-src' );
810
- ewwwio_debug_message( "checking webp for Lazy Load data-lazy-src: $file" );
811
- $filepath = ABSPATH . str_replace( $home_url, '', $file );
812
- if ( ! $valid_path && ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
813
- // Check the image for configured CDN paths.
814
- foreach ( $webp_paths as $webp_path ) {
815
- if ( strpos( $file, $webp_path ) !== false ) {
816
- $valid_path = true;
817
- }
818
- }
819
- }
820
- if ( $valid_path || is_file( $filepath . '.webp' ) ) {
821
- ewwwio_debug_message( "found webp for Lazy Load: $filepath" );
822
- $nimage->setAttribute( 'data-lazy-img-src', $file );
823
- $nimage->setAttribute( 'data-lazy-webp-src', $file . '.webp' );
824
- if ( $image->getAttribute( 'srcset' ) ) {
825
- $srcset = $image->getAttribute( 'srcset' );
826
- $srcset_webp = ewww_image_optimizer_webp_srcset_replace( $srcset, $home_url, $valid_path );
827
- if ( $srcset_webp ) {
828
- $nimage->setAttribute( 'data-srcset-webp', $srcset_webp );
829
- }
830
- $nimage->setAttribute( 'data-srcset', $srcset );
831
- }
832
- if ( $image->getAttribute( 'data-lazy-srcset' ) ) {
833
- $srcset = $image->getAttribute( 'data-lazy-srcset' );
834
- $srcset_webp = ewww_image_optimizer_webp_srcset_replace( $srcset, $home_url, $valid_path );
835
- if ( $srcset_webp ) {
836
- $nimage->setAttribute( 'data-lazy-srcset-webp', $srcset_webp );
837
- }
838
- $nimage->setAttribute( 'data-lazy-srcset-img', $srcset );
839
- }
840
- ewww_image_optimizer_webp_attr_copy( $image, $nimage, '' );
841
- $nimage->setAttribute( 'class', $image->getAttribute( 'class' ) . ' ewww_webp_lazy_load' );
842
- $image->parentNode->replaceChild( $nimage, $image );
843
- }
844
- } // End if().
845
- if ( $image->getAttribute( 'data-lazyload' ) ) {
846
- $lazyload = $image->getAttribute( 'data-lazyload' );
847
- if ( ! empty( $lazyload ) ) {
848
- $lazyloadpath = ABSPATH . str_replace( $home_url, '', $lazyload );
849
- if ( ! $valid_path && ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
850
- // Check the image for configured CDN paths.
851
- foreach ( $webp_paths as $webp_path ) {
852
- if ( strpos( $lazyload, $webp_path ) !== false ) {
853
- $valid_path = true;
854
- }
855
- }
856
- }
857
- if ( $valid_path || is_file( $lazyloadpath . '.webp' ) ) {
858
- ewwwio_debug_message( "found webp for data-lazyload: $filepath" );
859
- $image->setAttribute( 'data-webp-lazyload', $lazyload . '.webp' );
860
- }
861
- }
862
- }
863
- } // End foreach().
864
- } // End if().
865
- // NextGEN slides listed as 'a' elements.
866
- $links = $html->getElementsByTagName( 'a' );
867
- if ( ewww_image_optimizer_iterable( $links ) ) {
868
- foreach ( $links as $link ) {
869
- ewwwio_debug_message( 'parsing a link' );
870
- if ( $link->getAttribute( 'data-src' ) && $link->getAttribute( 'data-thumbnail' ) ) {
871
- $file = $link->getAttribute( 'data-src' );
872
- $thumb = $link->getAttribute( 'data-thumbnail' );
873
- $valid_path = false;
874
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
875
- // Check the image for configured CDN paths.
876
- foreach ( $webp_paths as $webp_path ) {
877
- if ( strpos( $file, $webp_path ) !== false ) {
878
- $valid_path = true;
879
- }
880
- }
881
- }
882
- ewwwio_debug_message( "checking webp for ngg data-src: $file" );
883
- $filepath = ABSPATH . str_replace( $home_url, '', $file );
884
- ewwwio_debug_message( "checking webp for ngg data-thumbnail: $thumb" );
885
- $thumbpath = ABSPATH . str_replace( $home_url, '', $thumb );
886
- if ( $valid_path || is_file( $filepath . '.webp' ) ) {
887
- ewwwio_debug_message( "found webp for ngg data-src: $filepath" );
888
- $link->setAttribute( 'data-webp', $file . '.webp' );
889
- }
890
- if ( $valid_path || is_file( $thumbpath . '.webp' ) ) {
891
- ewwwio_debug_message( "found webp for ngg data-thumbnail: $thumbpath" );
892
- $link->setAttribute( 'data-webp-thumbnail', $thumb . '.webp' );
893
- }
894
- }
895
- }
896
- }
897
- // Revolution Slider 'li' elements.
898
- $listitems = $html->getElementsByTagName( 'li' );
899
- if ( ewww_image_optimizer_iterable( $listitems ) ) {
900
- foreach ( $listitems as $listitem ) {
901
- ewwwio_debug_message( 'parsing a listitem' );
902
- if ( $listitem->getAttribute( 'data-title' ) === 'Slide' && ( $listitem->getAttribute( 'data-lazyload' ) || $listitem->getAttribute( 'data-thumb' ) ) ) {
903
- $thumb = $listitem->getAttribute( 'data-thumb' );
904
- $valid_path = false;
905
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
906
- // Check the image for configured CDN paths.
907
- foreach ( $webp_paths as $webp_path ) {
908
- if ( strpos( $thumb, $webp_path ) !== false ) {
909
- $valid_path = true;
910
- }
911
- }
912
- }
913
- ewwwio_debug_message( "checking webp for revslider data-thumb: $thumb" );
914
- $thumbpath = str_replace( $home_url, ABSPATH, $thumb );
915
- if ( $valid_path || is_file( $thumbpath . '.webp' ) ) {
916
- ewwwio_debug_message( "found webp for revslider data-thumb: $thumbpath" );
917
- $listitem->setAttribute( 'data-webp-thumb', $thumb . '.webp' );
918
- }
919
- $param_num = 1;
920
- while ( $param_num < 11 ) {
921
- $parameter = '';
922
- if ( $listitem->getAttribute( 'data-param' . $param_num ) ) {
923
- $parameter = $listitem->getAttribute( 'data-param' . $param_num );
924
- ewwwio_debug_message( "checking webp for revslider data-param$param_num: $parameter" );
925
- if ( ! empty( $parameter ) && strpos( $parameter, 'http' ) === 0 ) {
926
- $parameter_path = str_replace( $home_url, ABSPATH, $parameter );
927
- ewwwio_debug_message( "looking for $parameter_path" );
928
- if ( $valid_path || is_file( $parameter_path . '.webp' ) ) {
929
- ewwwio_debug_message( "found webp for data-param$param_num: $parameter_path" );
930
- $listitem->setAttribute( 'data-webp-param' . $param_num, $parameter . '.webp' );
931
- }
932
- }
933
- }
934
- $param_num++;
935
- }
936
- }
937
- } // End foreach().
938
- } // End if().
939
- // WooCommerce thumbs listed as 'div' elements.
940
- $divs = $html->getElementsByTagName( 'div' );
941
- if ( ewww_image_optimizer_iterable( $divs ) ) {
942
- foreach ( $divs as $div ) {
943
- ewwwio_debug_message( 'parsing a div' );
944
- if ( $div->getAttribute( 'class' ) && $div->getAttribute( 'data-thumb' ) && strpos( $div->getAttribute( 'class' ), 'woocommerce-product-gallery__image' ) !== false ) {
945
- $thumb = $div->getAttribute( 'data-thumb' );
946
- $valid_path = false;
947
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
948
- // Check the image for configured CDN paths.
949
- foreach ( $webp_paths as $webp_path ) {
950
- if ( strpos( $file, $webp_path ) !== false ) {
951
- $valid_path = true;
952
- }
953
- }
954
- }
955
- ewwwio_debug_message( "checking webp for WC data-thumb: $thumb" );
956
- $thumbpath = ABSPATH . str_replace( $home_url, '', $thumb );
957
- if ( $valid_path || is_file( $thumbpath . '.webp' ) ) {
958
- ewwwio_debug_message( "found webp for WC data-thumb: $thumbpath" );
959
- $div->setAttribute( 'data-webp-thumb', $thumb . '.webp' );
960
- }
961
- }
962
- }
963
- }
964
- // Video elements, looking for poster attributes that are images.
965
- $videos = $html->getElementsByTagName( 'video' );
966
- if ( ewww_image_optimizer_iterable( $videos ) ) {
967
- foreach ( $videos as $video ) {
968
- ewwwio_debug_message( 'parsing a video element' );
969
- if ( $link->getAttribute( 'poster' ) ) {
970
- $file = $link->getAttribute( 'poster' );
971
- $valid_path = false;
972
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
973
- // Check the image for configured CDN paths.
974
- foreach ( $webp_paths as $webp_path ) {
975
- if ( strpos( $file, $webp_path ) !== false ) {
976
- $valid_path = true;
977
- }
978
- }
979
- }
980
- ewwwio_debug_message( "checking webp for video poster: $file" );
981
- $filepath = ABSPATH . str_replace( $home_url, '', $file );
982
- if ( $valid_path || is_file( $filepath . '.webp' ) ) {
983
- ewwwio_debug_message( "found webp for video poster: $filepath" );
984
- $video->setAttribute( 'data-poster-webp', $file . '.webp' );
985
- $video->setAttribute( 'data-poster-image', $file );
986
- $video->removeAttribute( 'poster' );
987
- }
988
- }
989
- }
990
- }
991
- ewwwio_debug_message( 'preparing to dump page back to $buffer' );
992
- if ( ! empty( $xhtml_parse ) ) {
993
- $buffer = $html->saveXML( $html->documentElement );
994
- } else {
995
- $buffer = $html->saveHTML( $html->documentElement );
996
- }
997
- libxml_clear_errors();
998
- libxml_use_internal_errors( $libxml_previous_error_reporting );
999
- if ( false ) { // Set to true for extra debugging.
1000
- ewwwio_debug_message( 'html head' );
1001
- ewwwio_debug_message( $html_head[0] );
1002
- ewwwio_debug_message( 'buffer beginning' );
1003
- ewwwio_debug_message( substr( $buffer, 0, 500 ) );
1004
- }
1005
- if ( ! empty( $html_head ) && is_array( $html_head ) ) {
1006
- $buffer = preg_replace( '/<html.+>\s.*<head>/', $html_head[0], $buffer );
1007
- }
1008
- // Do some cleanup for the Easy Social Share Buttons for WordPress plugin (can't have <li> elements with newlines between them).
1009
- $buffer = preg_replace( '/\s(<li class="essb_item)/', '$1', $buffer );
1010
- if ( false ) { // Set to true for extra debugging.
1011
- ewwwio_debug_message( 'buffer after replacement' );
1012
- ewwwio_debug_message( substr( $buffer, 0, 500 ) );
1013
- }
1014
- } // End if().
1015
- if ( false ) { // Set to true for extra logging.
1016
- ewww_image_optimizer_debug_log();
1017
- }
1018
- return $buffer;
1019
- }
1020
-
1021
  /**
1022
  * Set default permissions for manual operations (single image optimize, convert, restore).
1023
  *
@@ -1115,17 +391,21 @@ function ewww_image_optimizer_stl_check() {
1115
  * Checks if a function is disabled or does not exist.
1116
  *
1117
  * @param string $function The name of a function to test.
 
1118
  * @return bool True if the function is available, False if not.
1119
  */
1120
- function ewww_image_optimizer_function_exists( $function ) {
1121
- ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1122
  if ( function_exists( 'ini_get' ) ) {
1123
  $disabled = @ini_get( 'disable_functions' );
1124
- ewwwio_debug_message( "disable_functions: $disabled" );
 
 
1125
  }
1126
  if ( extension_loaded( 'suhosin' ) && function_exists( 'ini_get' ) ) {
1127
  $suhosin_disabled = @ini_get( 'suhosin.executor.func.blacklist' );
1128
- ewwwio_debug_message( "suhosin_blacklist: $suhosin_disabled" );
 
 
1129
  if ( ! empty( $suhosin_disabled ) ) {
1130
  $suhosin_disabled = explode( ',', $suhosin_disabled );
1131
  $suhosin_disabled = array_map( 'trim', $suhosin_disabled );
@@ -1341,10 +621,6 @@ function ewww_image_optimizer_admin_init() {
1341
  update_site_option( 'ewww_image_optimizer_maxmediawidth', (int) $_POST['ewww_image_optimizer_maxmediawidth'] );
1342
  $_POST['ewww_image_optimizer_maxmediaheight'] = empty( $_POST['ewww_image_optimizer_maxmediaheight'] ) ? 0 : $_POST['ewww_image_optimizer_maxmediaheight'];
1343
  update_site_option( 'ewww_image_optimizer_maxmediaheight', (int) $_POST['ewww_image_optimizer_maxmediaheight'] );
1344
- $_POST['ewww_image_optimizer_maxotherwidth'] = empty( $_POST['ewww_image_optimizer_maxotherwidth'] ) ? 0 : $_POST['ewww_image_optimizer_maxotherwidth'];
1345
- update_site_option( 'ewww_image_optimizer_maxotherwidth', (int) $_POST['ewww_image_optimizer_maxotherwidth'] );
1346
- $_POST['ewww_image_optimizer_maxotherheight'] = empty( $_POST['ewww_image_optimizer_maxotherheight'] ) ? 0 : $_POST['ewww_image_optimizer_maxotherheight'];
1347
- update_site_option( 'ewww_image_optimizer_maxotherheight', (int) $_POST['ewww_image_optimizer_maxotherheight'] );
1348
  $_POST['ewww_image_optimizer_resize_detection'] = ( empty( $_POST['ewww_image_optimizer_resize_detection'] ) ? false : true );
1349
  update_site_option( 'ewww_image_optimizer_resize_detection', $_POST['ewww_image_optimizer_resize_detection'] );
1350
  $_POST['ewww_image_optimizer_resize_existing'] = ( empty( $_POST['ewww_image_optimizer_resize_existing'] ) ? false : true );
@@ -1415,8 +691,6 @@ function ewww_image_optimizer_admin_init() {
1415
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_resize_detection', 'boolval' );
1416
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxmediawidth', 'intval' );
1417
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxmediaheight', 'intval' );
1418
- register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxotherwidth', 'intval' );
1419
- register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxotherheight', 'intval' );
1420
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_resize_existing', 'boolval' );
1421
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_disable_resizes', 'ewww_image_optimizer_disable_resizes_sanitize' );
1422
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_disable_resizes_opt', 'ewww_image_optimizer_disable_resizes_sanitize' );
@@ -1449,6 +723,7 @@ function ewww_image_optimizer_admin_init() {
1449
  // Alert user if multiple re-optimizations detected.
1450
  add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_reoptimization' );
1451
  add_action( 'admin_notices', 'ewww_image_optimizer_notice_reoptimization' );
 
1452
  if ( ! empty( $_GET['page'] ) ) {
1453
  if ( 'regenerate-thumbnails' == $_GET['page']
1454
  || 'force-regenerate-thumbnails' == $_GET['page']
@@ -1459,9 +734,14 @@ function ewww_image_optimizer_admin_init() {
1459
  add_action( 'admin_notices', 'ewww_image_optimizer_thumbnail_regen_notice' );
1460
  }
1461
  }
 
 
 
 
 
1462
  ewww_image_optimizer_ajax_compat_check();
1463
  // Remove the false when the next bump is coming.
1464
- if ( false && defined( 'PHP_VERSION_ID' ) && PHP_VERSION_ID < 50500 ) {
1465
  add_action( 'network_admin_notices', 'ewww_image_optimizer_php54_warning' );
1466
  add_action( 'admin_notices', 'ewww_image_optimizer_php54_warning' );
1467
  }
@@ -1550,6 +830,22 @@ function ewww_image_optimizer_ajax_compat_check() {
1550
  }
1551
  }
1552
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1553
  /**
1554
  * Optimize a single image from an attachment, based on the size and ID.
1555
  *
@@ -1721,16 +1017,13 @@ function ewww_image_optimizer_save_admin_colors() {
1721
  if ( empty( $ewwwio_admin_color ) ) {
1722
  $ewwwio_admin_color = '#0073aa';
1723
  }
1724
- ewwwio_debug_message( "admin color selected: $ewwwio_admin_color" );
1725
  }
1726
  /**
1727
  * Determines the background color to use based on the selected admin theme.
1728
  */
1729
  function ewww_image_optimizer_admin_background() {
1730
- ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1731
  global $ewwwio_admin_color;
1732
  if ( ! empty( $ewwwio_admin_color ) && preg_match( '/^\#([0-9a-fA-F]){3,6}$/', $ewwwio_admin_color ) ) {
1733
- ewwwio_debug_message( "admin color previously saved: $ewwwio_admin_color" );
1734
  return $ewwwio_admin_color;
1735
  }
1736
  if ( function_exists( 'wp_add_inline_style' ) ) {
@@ -1745,7 +1038,6 @@ function ewww_image_optimizer_admin_background() {
1745
  preg_match( '/^\#([0-9a-fA-F]){3,6}$/', $_wp_admin_css_colors[ $user_info->admin_color ]->colors[2] )
1746
  ) {
1747
  $ewwwio_admin_color = $_wp_admin_css_colors[ $user_info->admin_color ]->colors[2];
1748
- ewwwio_debug_message( "had to go searching for admin color: $ewwwio_admin_color" );
1749
  return $ewwwio_admin_color;
1750
  }
1751
  switch ( $user_info->admin_color ) {
@@ -1767,7 +1059,6 @@ function ewww_image_optimizer_admin_background() {
1767
  return '#0073aa';
1768
  }
1769
  }
1770
- ewwwio_memory( __FUNCTION__ );
1771
  }
1772
 
1773
  /**
@@ -1890,9 +1181,7 @@ function ewww_image_optimizer_install_table() {
1890
  // Include the upgrade library to install/upgrade a table.
1891
  require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
1892
  $updates = dbDelta( $sql );
1893
- if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
1894
- ewwwio_debug_message( 'db upgrade results: ' . print_r( $updates, true ) );
1895
- }
1896
 
1897
  // Make sure some of our options are not autoloaded (since they can be huge).
1898
  $bulk_attachments = get_option( 'ewww_image_optimizer_bulk_attachments', '' );
@@ -1987,12 +1276,37 @@ function ewww_image_optimizer_remove_obsolete_settings() {
1987
  delete_option( 'ewww_image_optimizer_maxheight' );
1988
  }
1989
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1990
  /**
1991
  * Lets the user know their network settings have been saved.
1992
  */
1993
  function ewww_image_optimizer_network_settings_saved() {
1994
- ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1995
- echo "<div id='ewww-image-optimizer-settings-saved' class='updated fade'><p><strong>" . esc_html__( 'Settings saved', 'ewww-image-optimizer' ) . '.</strong></p></div>';
1996
  }
1997
 
1998
  /**
@@ -2003,6 +1317,17 @@ function ewww_image_optimizer_thumbnail_regen_notice() {
2003
  echo '&nbsp;<a href="https://docs.ewww.io/article/49-regenerate-thumbnails" target="_blank" data-beacon-article="5a0f84ed2c7d3a272c0dc801">' . esc_html__( 'Learn more.', 'ewww-image-optimizer' ) . '</a></p></div>';
2004
  }
2005
 
 
 
 
 
 
 
 
 
 
 
 
2006
  /**
2007
  * Alert the user when 5 images have been re-optimized more than 10 times.
2008
  *
@@ -2071,8 +1396,8 @@ function ewww_image_optimizer_load_editor( $editors ) {
2071
  if ( ! in_array( 'EWWWIO_Gmagick_Editor', $editors ) && class_exists( 'WP_Image_Editor_Gmagick' ) ) {
2072
  array_unshift( $editors, 'EWWWIO_Gmagick_Editor' );
2073
  }
2074
- if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
2075
- ewwwio_debug_message( 'loading image editors: ' . print_r( $editors, true ) );
2076
  }
2077
  ewwwio_memory( __FUNCTION__ );
2078
  return $editors;
@@ -2096,6 +1421,7 @@ function ewww_image_optimizer_add_attachment() {
2096
  function ewww_image_optimizer_image_sizes( $sizes ) {
2097
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
2098
  remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
 
2099
  add_filter( 'wp_generate_attachment_metadata', 'ewww_image_optimizer_restore_editor_hooks', 1 );
2100
  add_filter( 'mpp_generate_metadata', 'ewww_image_optimizer_restore_editor_hooks', 1 );
2101
  return $sizes;
@@ -2313,6 +1639,9 @@ function ewww_image_optimizer_handle_mpp_upload( $params ) {
2313
  */
2314
  function ewww_image_optimizer_handle_upload( $params ) {
2315
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
 
 
 
2316
  global $ewww_new_image;
2317
  $ewww_new_image = true;
2318
  if ( empty( $params['file'] ) ) {
@@ -2325,8 +1654,25 @@ function ewww_image_optimizer_handle_upload( $params ) {
2325
  $file_path = $params['file'];
2326
  }
2327
  ewww_image_optimizer_autorotate( $file_path );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2328
  // NOTE: if you use the ewww_image_optimizer_defer_resizing filter to defer the resize operation, only the "other" dimensions will apply
2329
- // resize here unless the user chose to defer resizing or imsanity is enabled with a max size.
2330
  if ( ! apply_filters( 'ewww_image_optimizer_defer_resizing', false ) && ! function_exists( 'imsanity_get_max_width_height' ) ) {
2331
  if ( empty( $params['type'] ) ) {
2332
  $mime_type = ewww_image_optimizer_mimetype( $file_path, 'i' );
@@ -2730,54 +2076,6 @@ function ewww_image_optimizer_myarcade_thumbnail( $url ) {
2730
  return $url;
2731
  }
2732
 
2733
- /**
2734
- * Load full webp script when SCRIPT_DEBUG is enabled.
2735
- */
2736
- function ewww_image_optimizer_webp_debug_script() {
2737
- if ( ! ewww_image_optimizer_ce_webp_enabled() ) {
2738
- wp_enqueue_script( 'ewww-webp-load-script', plugins_url( '/includes/load_webp.js', __FILE__ ), array( 'jquery' ), EWWW_IMAGE_OPTIMIZER_VERSION );
2739
- }
2740
- }
2741
-
2742
- /**
2743
- * Load minified webp script when EWWW_IMAGE_OPTIMIZER_WEBP_EXTERNAL_SCRIPT is set.
2744
- */
2745
- function ewww_image_optimizer_webp_min_script() {
2746
- if ( ! ewww_image_optimizer_ce_webp_enabled() ) {
2747
- wp_enqueue_script( 'ewww-webp-load-script', plugins_url( '/includes/load_webp.min.js', __FILE__ ), array( 'jquery' ), EWWW_IMAGE_OPTIMIZER_VERSION );
2748
- }
2749
- }
2750
-
2751
- /**
2752
- * Enqueue script dependency for alt webp rewriting when running inline.
2753
- */
2754
- function ewww_image_optimizer_webp_load_jquery() {
2755
- if ( ! ewww_image_optimizer_ce_webp_enabled() ) {
2756
- wp_enqueue_script( 'jquery' );
2757
- if ( function_exists( 'wp_add_inline_script' ) && ( ! defined( 'EWWW_IMAGE_OPTIMIZER_WEBP_INLINE_FALLBACK' ) || ! EWWW_IMAGE_OPTIMIZER_WEBP_INLINE_FALLBACK ) ) {
2758
- ewwwio_debug_message( 'loading webp script with wp_add_inline_script' );
2759
- wp_add_inline_script( 'jquery-migrate',
2760
- 'function check_webp_feature(t,e){var a={alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"},i=!1,r=new Image;r.onload=function(){var t=r.width>0&&r.height>0;i=!0,e(t)},r.onerror=function(){i=!1,e(!1)},r.src="data:image/webp;base64,"+a[t]}function ewww_load_images(t){jQuery(document).arrive(".ewww_webp",function(){ewww_load_images(t)}),function(e){function a(t,a){for(var r=["align","alt","border","crossorigin","height","hspace","ismap","longdesc","usemap","vspace","width","accesskey","class","contenteditable","contextmenu","dir","draggable","dropzone","hidden","id","lang","spellcheck","style","tabindex","title","translate","sizes","data-caption","data-attachment-id","data-permalink","data-orig-size","data-comments-opened","data-image-meta","data-image-title","data-image-description","data-event-trigger","data-highlight-color","data-highlight-opacity","data-highlight-border-color","data-highlight-border-width","data-highlight-border-opacity","data-no-lazy","data-lazy","data-large_image_width","data-large_image_height"],n=0,o=r.length;n<o;n++){var s=e(t).attr(i+r[n]);void 0!==s&&!1!==s&&e(a).attr(r[n],s)}return a}var i="data-";t&&(e(".batch-image img, .image-wrapper a, .ngg-pro-masonry-item a").each(function(){var t=e(this).attr("data-webp");void 0!==t&&!1!==t&&e(this).attr("data-src",t),void 0!==(t=e(this).attr("data-webp-thumbnail"))&&!1!==t&&e(this).attr("data-thumbnail",t)}),e(".image-wrapper a, .ngg-pro-masonry-item a").each(function(){var t=e(this).attr("data-webp");void 0!==t&&!1!==t&&e(this).attr("href",t)}),e(".rev_slider ul li").each(function(){var t=e(this).attr("data-webp-thumb");void 0!==t&&!1!==t&&e(this).attr("data-thumb",t);for(var a=1;a<11;)void 0!==(t=e(this).attr("data-webp-param"+a))&&!1!==t&&e(this).attr("data-param"+a,t),a++}),e(".rev_slider img").each(function(){var t=e(this).attr("data-webp-lazyload");void 0!==t&&!1!==t&&e(this).attr("data-lazyload",t)}),e("div.woocommerce-product-gallery__image").each(function(){var t=e(this).attr("data-webp-thumb");void 0!==t&&!1!==t&&e(this).attr("data-thumb",t)})),e("img.ewww_webp_lazy_retina").each(function(){if(t)void 0!==(a=e(this).attr("data-srcset-webp"))&&!1!==a&&e(this).attr("data-srcset",a);else{var a=e(this).attr("data-srcset-img");void 0!==a&&!1!==a&&e(this).attr("data-srcset",a)}e(this).removeClass("ewww_webp_lazy_retina")}),e("video").each(function(){if(t)void 0!==(a=e(this).attr("data-poster-webp"))&&!1!==a&&e(this).attr("poster",a);else{var a=e(this).attr("data-poster-image");void 0!==a&&!1!==a&&e(this).attr("poster",a)}}),e("img.ewww_webp_lazy_load").each(function(){if(t)e(this).attr("data-lazy-src",e(this).attr("data-lazy-webp-src")),void 0!==(a=e(this).attr("data-srcset-webp"))&&!1!==a&&e(this).attr("srcset",a),void 0!==(a=e(this).attr("data-lazy-srcset-webp"))&&!1!==a&&e(this).attr("data-lazy-srcset",a);else{e(this).attr("data-lazy-src",e(this).attr("data-lazy-img-src"));var a=e(this).attr("data-srcset");void 0!==a&&!1!==a&&e(this).attr("srcset",a),void 0!==(a=e(this).attr("data-lazy-srcset-img"))&&!1!==a&&e(ewww_img).attr("data-lazy-srcset",a)}e(this).removeClass("ewww_webp_lazy_load")}),e(".ewww_webp_lazy_hueman").each(function(){var i=document.createElement("img");if(e(i).attr("src",e(this).attr("data-src")),t)e(i).attr("data-src",e(this).attr("data-webp-src")),void 0!==(r=e(this).attr("data-srcset-webp"))&&!1!==r&&e(i).attr("data-srcset",r);else{e(i).attr("data-src",e(this).attr("data-img"));var r=e(this).attr("data-srcset-img");void 0!==r&&!1!==r&&e(i).attr("data-srcset",r)}i=a(this,i),e(this).after(i),e(this).removeClass("ewww_webp_lazy_hueman")}),e(".ewww_webp").each(function(){var i=document.createElement("img");if(t)e(i).attr("src",e(this).attr("data-webp")),void 0!==(r=e(this).attr("data-srcset-webp"))&&!1!==r&&e(i).attr("srcset",r),void 0!==(r=e(this).attr("data-webp-orig-file"))&&!1!==r?e(i).attr("data-orig-file",r):void 0!==(r=e(this).attr("data-orig-file"))&&!1!==r&&e(i).attr("data-orig-file",r),void 0!==(r=e(this).attr("data-webp-medium-file"))&&!1!==r?e(i).attr("data-medium-file",r):void 0!==(r=e(this).attr("data-medium-file"))&&!1!==r&&e(i).attr("data-medium-file",r),void 0!==(r=e(this).attr("data-webp-large-file"))&&!1!==r?e(i).attr("data-large-file",r):void 0!==(r=e(this).attr("data-large-file"))&&!1!==r&&e(i).attr("data-large-file",r),void 0!==(r=e(this).attr("data-webp-large_image"))&&!1!==r?e(i).attr("data-large_image",r):void 0!==(r=e(this).attr("data-large_image"))&&!1!==r&&e(i).attr("data-large_image",r),void 0!==(r=e(this).attr("data-webp-src"))&&!1!==r?e(i).attr("data-src",r):void 0!==(r=e(this).attr("data-src"))&&!1!==r&&e(i).attr("data-src",r);else{e(i).attr("src",e(this).attr("data-img"));var r=e(this).attr("data-srcset-img");void 0!==r&&!1!==r&&e(i).attr("srcset",r),void 0!==(r=e(this).attr("data-orig-file"))&&!1!==r&&e(i).attr("data-orig-file",r),void 0!==(r=e(this).attr("data-medium-file"))&&!1!==r&&e(i).attr("data-medium-file",r),void 0!==(r=e(this).attr("data-large-file"))&&!1!==r&&e(i).attr("data-large-file",r),void 0!==(r=e(this).attr("data-large_image"))&&!1!==r&&e(i).attr("data-large_image",r),void 0!==(r=e(this).attr("data-src"))&&!1!==r&&e(i).attr("data-src",r)}i=a(this,i),e(this).after(i),e(this).removeClass("ewww_webp")})}(jQuery),jQuery.fn.isotope&&jQuery.fn.imagesLoaded&&(jQuery(".fusion-posts-container-infinite").imagesLoaded(function(){jQuery(".fusion-posts-container-infinite").hasClass("isotope")&&jQuery(".fusion-posts-container-infinite").isotope()}),jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").imagesLoaded(function(){jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").isotope()}))}var Arrive=function(t,e,a){"use strict";function i(t,e,a){o.addMethod(e,a,t.unbindEvent),o.addMethod(e,a,t.unbindEventWithSelectorOrCallback),o.addMethod(e,a,t.unbindEventWithSelectorAndCallback)}function r(t){t.arrive=l.bindEvent,i(l,t,"unbindArrive"),t.leave=c.bindEvent,i(c,t,"unbindLeave")}if(t.MutationObserver&&"undefined"!=typeof HTMLElement){var n=0,o=function(){var e=HTMLElement.prototype.matches||HTMLElement.prototype.webkitMatchesSelector||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelector;return{matchesSelector:function(t,a){return t instanceof HTMLElement&&e.call(t,a)},addMethod:function(t,e,a){var i=t[e];t[e]=function(){return a.length==arguments.length?a.apply(this,arguments):"function"==typeof i?i.apply(this,arguments):void 0}},callCallbacks:function(t){for(var e,a=0;e=t[a];a++)e.callback.call(e.elem)},checkChildNodesRecursively:function(t,e,a,i){for(var r,n=0;r=t[n];n++)a(r,e,i)&&i.push({callback:e.callback,elem:r}),r.childNodes.length>0&&o.checkChildNodesRecursively(r.childNodes,e,a,i)},mergeArrays:function(t,e){var a,i={};for(a in t)i[a]=t[a];for(a in e)i[a]=e[a];return i},toElementsArray:function(e){return void 0===e||"number"==typeof e.length&&e!==t||(e=[e]),e}}}(),s=function(){var t=function(){this._eventsBucket=[],this._beforeAdding=null,this._beforeRemoving=null};return t.prototype.addEvent=function(t,e,a,i){var r={target:t,selector:e,options:a,callback:i,firedElems:[]};return this._beforeAdding&&this._beforeAdding(r),this._eventsBucket.push(r),r},t.prototype.removeEvent=function(t){for(var e,a=this._eventsBucket.length-1;e=this._eventsBucket[a];a--)t(e)&&(this._beforeRemoving&&this._beforeRemoving(e),this._eventsBucket.splice(a,1))},t.prototype.beforeAdding=function(t){this._beforeAdding=t},t.prototype.beforeRemoving=function(t){this._beforeRemoving=t},t}(),d=function(e,i){var r=new s,n=this,d={fireOnAttributesModification:!1};return r.beforeAdding(function(a){var r,o=a.target;a.selector,a.callback;o!==t.document&&o!==t||(o=document.getElementsByTagName("html")[0]),r=new MutationObserver(function(t){i.call(this,t,a)});var s=e(a.options);r.observe(o,s),a.observer=r,a.me=n}),r.beforeRemoving(function(t){t.observer.disconnect()}),this.bindEvent=function(t,e,a){e=o.mergeArrays(d,e);for(var i=o.toElementsArray(this),n=0;n<i.length;n++)r.addEvent(i[n],t,e,a)},this.unbindEvent=function(){var t=o.toElementsArray(this);r.removeEvent(function(e){for(var i=0;i<t.length;i++)if(this===a||e.target===t[i])return!0;return!1})},this.unbindEventWithSelectorOrCallback=function(t){var e,i=o.toElementsArray(this),n=t;e="function"==typeof t?function(t){for(var e=0;e<i.length;e++)if((this===a||t.target===i[e])&&t.callback===n)return!0;return!1}:function(e){for(var r=0;r<i.length;r++)if((this===a||e.target===i[r])&&e.selector===t)return!0;return!1},r.removeEvent(e)},this.unbindEventWithSelectorAndCallback=function(t,e){var i=o.toElementsArray(this);r.removeEvent(function(r){for(var n=0;n<i.length;n++)if((this===a||r.target===i[n])&&r.selector===t&&r.callback===e)return!0;return!1})},this},l=new function(){function t(t,e,i){if(o.matchesSelector(t,e.selector)&&(t._id===a&&(t._id=n++),-1==e.firedElems.indexOf(t._id))){if(e.options.onceOnly){if(0!==e.firedElems.length)return;e.me.unbindEventWithSelectorAndCallback.call(e.target,e.selector,e.callback)}e.firedElems.push(t._id),i.push({callback:e.callback,elem:t})}}var e={fireOnAttributesModification:!1,onceOnly:!1,existing:!1},i=(l=new d(function(t){var e={attributes:!1,childList:!0,subtree:!0};return t.fireOnAttributesModification&&(e.attributes=!0),e},function(e,a){e.forEach(function(e){var i=e.addedNodes,r=e.target,n=[];null!==i&&i.length>0?o.checkChildNodesRecursively(i,a,t,n):"attributes"===e.type&&t(r,a,n)&&n.push({callback:a.callback,elem:node}),o.callCallbacks(n)})})).bindEvent;return l.bindEvent=function(t,a,r){void 0===r?(r=a,a=e):a=o.mergeArrays(e,a);var n=o.toElementsArray(this);if(a.existing){for(var s=[],d=0;d<n.length;d++)for(var l=n[d].querySelectorAll(t),c=0;c<l.length;c++)s.push({callback:r,elem:l[c]});if(a.onceOnly&&s.length)return r.call(s[0].elem);setTimeout(o.callCallbacks,1,s)}i.call(this,t,a,r)},l},c=new function(){function t(t,e){return o.matchesSelector(t,e.selector)}var e={},a=(c=new d(function(t){return{childList:!0,subtree:!0}},function(e,a){e.forEach(function(e){var i=e.removedNodes,r=(e.target,[]);null!==i&&i.length>0&&o.checkChildNodesRecursively(i,a,t,r),o.callCallbacks(r)})})).bindEvent;return c.bindEvent=function(t,i,r){void 0===r?(r=i,i=e):i=o.mergeArrays(e,i),a.call(this,t,i,r)},c};e&&r(e.fn),r(HTMLElement.prototype),r(NodeList.prototype),r(HTMLCollection.prototype),r(HTMLDocument.prototype),r(Window.prototype);var h={};return i(l,h,"unbindAllArrive"),i(c,h,"unbindAllLeave"),h}}(window,"undefined"==typeof jQuery?null:jQuery,void 0);"undefined"!=typeof jQuery&&check_webp_feature("alpha",ewww_load_images);'
2761
- );
2762
- }
2763
- }
2764
- }
2765
-
2766
- /**
2767
- * Load minified inline version of webp script (from jscompress.com).
2768
- */
2769
- function ewww_image_optimizer_webp_inline_script() {
2770
- if ( ! ewww_image_optimizer_ce_webp_enabled() ) {
2771
- ewwwio_debug_message( 'loading webp script without wp_add_inline_script' );
2772
- ?>
2773
- <script>
2774
- function check_webp_feature(t,e){var a={alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"},i=!1,r=new Image;r.onload=function(){var t=r.width>0&&r.height>0;i=!0,e(t)},r.onerror=function(){i=!1,e(!1)},r.src="data:image/webp;base64,"+a[t]}function ewww_load_images(t){jQuery(document).arrive(".ewww_webp",function(){ewww_load_images(t)}),function(e){function a(t,a){for(var r=["align","alt","border","crossorigin","height","hspace","ismap","longdesc","usemap","vspace","width","accesskey","class","contenteditable","contextmenu","dir","draggable","dropzone","hidden","id","lang","spellcheck","style","tabindex","title","translate","sizes","data-caption","data-attachment-id","data-permalink","data-orig-size","data-comments-opened","data-image-meta","data-image-title","data-image-description","data-event-trigger","data-highlight-color","data-highlight-opacity","data-highlight-border-color","data-highlight-border-width","data-highlight-border-opacity","data-no-lazy","data-lazy","data-large_image_width","data-large_image_height"],n=0,o=r.length;n<o;n++){var s=e(t).attr(i+r[n]);void 0!==s&&!1!==s&&e(a).attr(r[n],s)}return a}var i="data-";t&&(e(".batch-image img, .image-wrapper a, .ngg-pro-masonry-item a").each(function(){var t=e(this).attr("data-webp");void 0!==t&&!1!==t&&e(this).attr("data-src",t),void 0!==(t=e(this).attr("data-webp-thumbnail"))&&!1!==t&&e(this).attr("data-thumbnail",t)}),e(".image-wrapper a, .ngg-pro-masonry-item a").each(function(){var t=e(this).attr("data-webp");void 0!==t&&!1!==t&&e(this).attr("href",t)}),e(".rev_slider ul li").each(function(){var t=e(this).attr("data-webp-thumb");void 0!==t&&!1!==t&&e(this).attr("data-thumb",t);for(var a=1;a<11;)void 0!==(t=e(this).attr("data-webp-param"+a))&&!1!==t&&e(this).attr("data-param"+a,t),a++}),e(".rev_slider img").each(function(){var t=e(this).attr("data-webp-lazyload");void 0!==t&&!1!==t&&e(this).attr("data-lazyload",t)}),e("div.woocommerce-product-gallery__image").each(function(){var t=e(this).attr("data-webp-thumb");void 0!==t&&!1!==t&&e(this).attr("data-thumb",t)})),e("img.ewww_webp_lazy_retina").each(function(){if(t)void 0!==(a=e(this).attr("data-srcset-webp"))&&!1!==a&&e(this).attr("data-srcset",a);else{var a=e(this).attr("data-srcset-img");void 0!==a&&!1!==a&&e(this).attr("data-srcset",a)}e(this).removeClass("ewww_webp_lazy_retina")}),e("video").each(function(){if(t)void 0!==(a=e(this).attr("data-poster-webp"))&&!1!==a&&e(this).attr("poster",a);else{var a=e(this).attr("data-poster-image");void 0!==a&&!1!==a&&e(this).attr("poster",a)}}),e("img.ewww_webp_lazy_load").each(function(){if(t)e(this).attr("data-lazy-src",e(this).attr("data-lazy-webp-src")),void 0!==(a=e(this).attr("data-srcset-webp"))&&!1!==a&&e(this).attr("srcset",a),void 0!==(a=e(this).attr("data-lazy-srcset-webp"))&&!1!==a&&e(this).attr("data-lazy-srcset",a);else{e(this).attr("data-lazy-src",e(this).attr("data-lazy-img-src"));var a=e(this).attr("data-srcset");void 0!==a&&!1!==a&&e(this).attr("srcset",a),void 0!==(a=e(this).attr("data-lazy-srcset-img"))&&!1!==a&&e(ewww_img).attr("data-lazy-srcset",a)}e(this).removeClass("ewww_webp_lazy_load")}),e(".ewww_webp_lazy_hueman").each(function(){var i=document.createElement("img");if(e(i).attr("src",e(this).attr("data-src")),t)e(i).attr("data-src",e(this).attr("data-webp-src")),void 0!==(r=e(this).attr("data-srcset-webp"))&&!1!==r&&e(i).attr("data-srcset",r);else{e(i).attr("data-src",e(this).attr("data-img"));var r=e(this).attr("data-srcset-img");void 0!==r&&!1!==r&&e(i).attr("data-srcset",r)}i=a(this,i),e(this).after(i),e(this).removeClass("ewww_webp_lazy_hueman")}),e(".ewww_webp").each(function(){var i=document.createElement("img");if(t)e(i).attr("src",e(this).attr("data-webp")),void 0!==(r=e(this).attr("data-srcset-webp"))&&!1!==r&&e(i).attr("srcset",r),void 0!==(r=e(this).attr("data-webp-orig-file"))&&!1!==r?e(i).attr("data-orig-file",r):void 0!==(r=e(this).attr("data-orig-file"))&&!1!==r&&e(i).attr("data-orig-file",r),void 0!==(r=e(this).attr("data-webp-medium-file"))&&!1!==r?e(i).attr("data-medium-file",r):void 0!==(r=e(this).attr("data-medium-file"))&&!1!==r&&e(i).attr("data-medium-file",r),void 0!==(r=e(this).attr("data-webp-large-file"))&&!1!==r?e(i).attr("data-large-file",r):void 0!==(r=e(this).attr("data-large-file"))&&!1!==r&&e(i).attr("data-large-file",r),void 0!==(r=e(this).attr("data-webp-large_image"))&&!1!==r?e(i).attr("data-large_image",r):void 0!==(r=e(this).attr("data-large_image"))&&!1!==r&&e(i).attr("data-large_image",r),void 0!==(r=e(this).attr("data-webp-src"))&&!1!==r?e(i).attr("data-src",r):void 0!==(r=e(this).attr("data-src"))&&!1!==r&&e(i).attr("data-src",r);else{e(i).attr("src",e(this).attr("data-img"));var r=e(this).attr("data-srcset-img");void 0!==r&&!1!==r&&e(i).attr("srcset",r),void 0!==(r=e(this).attr("data-orig-file"))&&!1!==r&&e(i).attr("data-orig-file",r),void 0!==(r=e(this).attr("data-medium-file"))&&!1!==r&&e(i).attr("data-medium-file",r),void 0!==(r=e(this).attr("data-large-file"))&&!1!==r&&e(i).attr("data-large-file",r),void 0!==(r=e(this).attr("data-large_image"))&&!1!==r&&e(i).attr("data-large_image",r),void 0!==(r=e(this).attr("data-src"))&&!1!==r&&e(i).attr("data-src",r)}i=a(this,i),e(this).after(i),e(this).removeClass("ewww_webp")})}(jQuery),jQuery.fn.isotope&&jQuery.fn.imagesLoaded&&(jQuery(".fusion-posts-container-infinite").imagesLoaded(function(){jQuery(".fusion-posts-container-infinite").hasClass("isotope")&&jQuery(".fusion-posts-container-infinite").isotope()}),jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").imagesLoaded(function(){jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").isotope()}))}var Arrive=function(t,e,a){"use strict";function i(t,e,a){o.addMethod(e,a,t.unbindEvent),o.addMethod(e,a,t.unbindEventWithSelectorOrCallback),o.addMethod(e,a,t.unbindEventWithSelectorAndCallback)}function r(t){t.arrive=l.bindEvent,i(l,t,"unbindArrive"),t.leave=c.bindEvent,i(c,t,"unbindLeave")}if(t.MutationObserver&&"undefined"!=typeof HTMLElement){var n=0,o=function(){var e=HTMLElement.prototype.matches||HTMLElement.prototype.webkitMatchesSelector||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelector;return{matchesSelector:function(t,a){return t instanceof HTMLElement&&e.call(t,a)},addMethod:function(t,e,a){var i=t[e];t[e]=function(){return a.length==arguments.length?a.apply(this,arguments):"function"==typeof i?i.apply(this,arguments):void 0}},callCallbacks:function(t){for(var e,a=0;e=t[a];a++)e.callback.call(e.elem)},checkChildNodesRecursively:function(t,e,a,i){for(var r,n=0;r=t[n];n++)a(r,e,i)&&i.push({callback:e.callback,elem:r}),r.childNodes.length>0&&o.checkChildNodesRecursively(r.childNodes,e,a,i)},mergeArrays:function(t,e){var a,i={};for(a in t)i[a]=t[a];for(a in e)i[a]=e[a];return i},toElementsArray:function(e){return void 0===e||"number"==typeof e.length&&e!==t||(e=[e]),e}}}(),s=function(){var t=function(){this._eventsBucket=[],this._beforeAdding=null,this._beforeRemoving=null};return t.prototype.addEvent=function(t,e,a,i){var r={target:t,selector:e,options:a,callback:i,firedElems:[]};return this._beforeAdding&&this._beforeAdding(r),this._eventsBucket.push(r),r},t.prototype.removeEvent=function(t){for(var e,a=this._eventsBucket.length-1;e=this._eventsBucket[a];a--)t(e)&&(this._beforeRemoving&&this._beforeRemoving(e),this._eventsBucket.splice(a,1))},t.prototype.beforeAdding=function(t){this._beforeAdding=t},t.prototype.beforeRemoving=function(t){this._beforeRemoving=t},t}(),d=function(e,i){var r=new s,n=this,d={fireOnAttributesModification:!1};return r.beforeAdding(function(a){var r,o=a.target;a.selector,a.callback;o!==t.document&&o!==t||(o=document.getElementsByTagName("html")[0]),r=new MutationObserver(function(t){i.call(this,t,a)});var s=e(a.options);r.observe(o,s),a.observer=r,a.me=n}),r.beforeRemoving(function(t){t.observer.disconnect()}),this.bindEvent=function(t,e,a){e=o.mergeArrays(d,e);for(var i=o.toElementsArray(this),n=0;n<i.length;n++)r.addEvent(i[n],t,e,a)},this.unbindEvent=function(){var t=o.toElementsArray(this);r.removeEvent(function(e){for(var i=0;i<t.length;i++)if(this===a||e.target===t[i])return!0;return!1})},this.unbindEventWithSelectorOrCallback=function(t){var e,i=o.toElementsArray(this),n=t;e="function"==typeof t?function(t){for(var e=0;e<i.length;e++)if((this===a||t.target===i[e])&&t.callback===n)return!0;return!1}:function(e){for(var r=0;r<i.length;r++)if((this===a||e.target===i[r])&&e.selector===t)return!0;return!1},r.removeEvent(e)},this.unbindEventWithSelectorAndCallback=function(t,e){var i=o.toElementsArray(this);r.removeEvent(function(r){for(var n=0;n<i.length;n++)if((this===a||r.target===i[n])&&r.selector===t&&r.callback===e)return!0;return!1})},this},l=new function(){function t(t,e,i){if(o.matchesSelector(t,e.selector)&&(t._id===a&&(t._id=n++),-1==e.firedElems.indexOf(t._id))){if(e.options.onceOnly){if(0!==e.firedElems.length)return;e.me.unbindEventWithSelectorAndCallback.call(e.target,e.selector,e.callback)}e.firedElems.push(t._id),i.push({callback:e.callback,elem:t})}}var e={fireOnAttributesModification:!1,onceOnly:!1,existing:!1},i=(l=new d(function(t){var e={attributes:!1,childList:!0,subtree:!0};return t.fireOnAttributesModification&&(e.attributes=!0),e},function(e,a){e.forEach(function(e){var i=e.addedNodes,r=e.target,n=[];null!==i&&i.length>0?o.checkChildNodesRecursively(i,a,t,n):"attributes"===e.type&&t(r,a,n)&&n.push({callback:a.callback,elem:node}),o.callCallbacks(n)})})).bindEvent;return l.bindEvent=function(t,a,r){void 0===r?(r=a,a=e):a=o.mergeArrays(e,a);var n=o.toElementsArray(this);if(a.existing){for(var s=[],d=0;d<n.length;d++)for(var l=n[d].querySelectorAll(t),c=0;c<l.length;c++)s.push({callback:r,elem:l[c]});if(a.onceOnly&&s.length)return r.call(s[0].elem);setTimeout(o.callCallbacks,1,s)}i.call(this,t,a,r)},l},c=new function(){function t(t,e){return o.matchesSelector(t,e.selector)}var e={},a=(c=new d(function(t){return{childList:!0,subtree:!0}},function(e,a){e.forEach(function(e){var i=e.removedNodes,r=(e.target,[]);null!==i&&i.length>0&&o.checkChildNodesRecursively(i,a,t,r),o.callCallbacks(r)})})).bindEvent;return c.bindEvent=function(t,i,r){void 0===r?(r=i,i=e):i=o.mergeArrays(e,i),a.call(this,t,i,r)},c};e&&r(e.fn),r(HTMLElement.prototype),r(NodeList.prototype),r(HTMLCollection.prototype),r(HTMLDocument.prototype),r(Window.prototype);var h={};return i(l,h,"unbindAllArrive"),i(c,h,"unbindAllLeave"),h}}(window,"undefined"==typeof jQuery?null:jQuery,void 0);"undefined"!=typeof jQuery&&check_webp_feature("alpha",ewww_load_images);
2775
- </script>
2776
- <?php
2777
- } // End if().
2778
- // Current length 10783.
2779
- }
2780
-
2781
  /**
2782
  * Enqueue custom jquery stylesheet and scripts for the media library AJAX functions.
2783
  *
@@ -3852,7 +3150,7 @@ function ewww_image_optimizer_cloud_optimizer( $file, $type, $convert = false, $
3852
  }
3853
  // Calculate how much time has elapsed since we started.
3854
  $elapsed = microtime( true ) - $started;
3855
- ewwwio_debug_message( "Cloud verify took $elapsed seconds" );
3856
  $ewww_status = get_transient( 'ewww_image_optimizer_cloud_status' );
3857
  if ( ( ! empty( $ewww_status ) && preg_match( '/exceeded/', $ewww_status ) ) || ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_exceeded' ) > time() ) {
3858
  ewwwio_debug_message( 'license exceeded, image not processed' );
@@ -4071,7 +3369,7 @@ function ewww_image_optimizer_cloud_autorotate( $file, $type ) {
4071
  }
4072
  // Calculate how much time has elapsed since we started.
4073
  $elapsed = microtime( true ) - $started;
4074
- ewwwio_debug_message( "Cloud verify took $elapsed seconds" );
4075
  $ewww_status = get_transient( 'ewww_image_optimizer_cloud_status' );
4076
  if ( ( ! empty( $ewww_status ) && preg_match( '/exceeded/', $ewww_status ) ) || ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_exceeded' ) > time() ) {
4077
  ewwwio_debug_message( 'license exceeded, image not rotated' );
@@ -4263,11 +3561,20 @@ function ewww_image_optimizer_check_table( $file, $orig_size ) {
4263
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
4264
  ewwwio_debug_message( "checking for $file with size: $orig_size" );
4265
  global $s3_uploads_image;
 
4266
  if ( class_exists( 'S3_Uploads' ) && ! empty( $s3_uploads_image ) && $s3_uploads_image != $file ) {
4267
  $file = $s3_uploads_image;
4268
  ewwwio_debug_message( "overriding check with: $file" );
4269
  }
4270
- $image = ewww_image_optimizer_find_already_optimized( $file );
 
 
 
 
 
 
 
 
4271
  if ( is_array( $image ) && $image['image_size'] == $orig_size ) {
4272
  $prev_string = ' - ' . __( 'Previously Optimized', 'ewww-image-optimizer' );
4273
  if ( preg_match( '/' . __( 'License exceeded', 'ewww-image-optimizer' ) . '/', $image['results'] ) ) {
@@ -4348,6 +3655,7 @@ function ewww_image_optimizer_update_table( $attachment, $opt_size, $orig_size,
4348
  $updates = array(
4349
  'path' => ewww_image_optimizer_relative_path_remove( $attachment ),
4350
  'converted' => $converted,
 
4351
  'image_size' => $opt_size,
4352
  'results' => $results_msg,
4353
  'updates' => 1,
@@ -4368,6 +3676,9 @@ function ewww_image_optimizer_update_table( $attachment, $opt_size, $orig_size,
4368
  if ( is_object( $ewww_image ) && $ewww_image instanceof EWWW_Image && $ewww_image->resize ) {
4369
  $updates['resize'] = $ewww_image->resize;
4370
  }
 
 
 
4371
  $updates['orig_size'] = $orig_size;
4372
  $updates['updated'] = date( 'Y-m-d H:i:s' );
4373
  $ewwwdb->insert( $ewwwdb->ewwwio_images, $updates );
@@ -4392,6 +3703,9 @@ function ewww_image_optimizer_update_table( $attachment, $opt_size, $orig_size,
4392
  if ( empty( $already_optimized['resize'] ) && is_object( $ewww_image ) && $ewww_image instanceof EWWW_Image && $ewww_image->resize ) {
4393
  $updates['resize'] = $ewww_image->resize;
4394
  }
 
 
 
4395
  if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
4396
  ewwwio_debug_message( print_r( $updates, true ) );
4397
  }
@@ -4896,7 +4210,7 @@ function ewww_image_optimizer_raise_memory_limit( $memory_limit ) {
4896
  */
4897
  function ewww_image_optimizer_autorotate( $file ) {
4898
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
4899
- if ( defined( 'EWWW_IMAGE_OPTIMIZER_NO_ROTATE' ) && EWWW_IMAGE_OPTIMIZER_NO_ROTATE ) {
4900
  return;
4901
  }
4902
  if ( function_exists( 'wp_raise_memory_limit' ) ) {
@@ -4948,6 +4262,32 @@ function ewww_image_optimizer_autorotate( $file ) {
4948
  ewww_image_optimizer_cloud_autorotate( $file, $type );
4949
  }
4950
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4951
  /**
4952
  * Skips resizing for any image with 'noresize' in the filename.
4953
  *
@@ -4981,13 +4321,25 @@ function ewww_image_optimizer_resize_upload( $file ) {
4981
  wp_raise_memory_limit( 'image' );
4982
  }
4983
  if ( ! empty( $_REQUEST['post_id'] ) || ( ! empty( $_REQUEST['action'] ) && 'upload-attachment' === $_REQUEST['action'] ) || ( ! empty( $_SERVER['HTTP_REFERER'] ) && strpos( $_SERVER['HTTP_REFERER'], 'media-new.php' ) ) ) {
 
 
 
 
 
4984
  $maxwidth = ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' );
4985
  $maxheight = ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' );
4986
- ewwwio_debug_message( 'resizing image from media library or attached to post' );
4987
  } else {
 
4988
  $maxwidth = ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherwidth' );
4989
  $maxheight = ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherheight' );
4990
- ewwwio_debug_message( 'resizing images from somewhere else' );
 
 
 
 
 
 
 
4991
  }
4992
 
4993
  /**
@@ -5025,7 +4377,7 @@ function ewww_image_optimizer_resize_upload( $file ) {
5025
  return false;
5026
  }
5027
  $crop = false;
5028
- if ( $oldwidth > $maxwidth && $maxwidth && $oldheight > $maxheight && $maxheight && apply_filters( 'ewww_image_optimizer_crop_image', false ) ) {
5029
  $crop = true;
5030
  $newwidth = $maxwidth;
5031
  $newheight = $maxheight;
@@ -5315,7 +4667,8 @@ function ewww_image_optimizer_remove_duplicate_records( $duplicates ) {
5315
  $delete_ids[] = (int) $record['id'];
5316
  }
5317
  if ( ! empty( $delete_ids ) && is_array( $delete_ids ) ) {
5318
- $ewwwdb->query( "DELETE FROM $ewwwdb->ewwwio_images WHERE id IN (" . implode( ',', $delete_ids ) . ')' ); // WPCS: unprepared SQL ok.
 
5319
  }
5320
  return $keeper;
5321
  }
@@ -6301,7 +5654,7 @@ function ewww_image_optimizer_unique_filename( $file, $fileext ) {
6301
  // Set the increment to 1 (but allow the user to override it).
6302
  $filenum = apply_filters( 'ewww_image_optimizer_converted_filename_suffix', 1 );
6303
  // But it must be only letters, numbers, or underscores.
6304
- $filenum = ( preg_match( '/^[\w\d]*$/', $filenum ) ? $filenum : 1 );
6305
  $suffix = ( ! empty( $filenum ) ? '-' . $filenum : '' );
6306
  // While a file exists with the current increment.
6307
  while ( file_exists( $filename . $suffix . $fileext ) ) {
@@ -6480,9 +5833,10 @@ function ewww_image_optimizer_custom_column( $column_name, $id, $meta = null, $r
6480
  $meta = wp_get_attachment_metadata( $id );
6481
  }
6482
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) && ! $return_output && ewww_image_optimizer_function_exists( 'print_r' ) ) {
6483
- $print_meta = print_r( $meta, true );
6484
- $print_meta = preg_replace( array( '/ /', '/\n+/' ), array( '&nbsp;', '<br />' ), $print_meta );
6485
- $output .= '<div style="background-color:#ffff99;font-size: 10px;padding: 10px;margin:-10px -10px 10px;line-height: 1.1em">' . $print_meta . '</div>';
 
6486
  }
6487
  $output .= "<div id='ewww-media-status-$id'>";
6488
  $ewww_cdn = false;
@@ -7078,6 +6432,21 @@ function ewww_image_optimizer_migrate_meta_to_db( $id, $meta, $bail_early = fals
7078
  return $meta;
7079
  }
7080
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7081
  /**
7082
  * Load JS in media library footer for bulk actions.
7083
  */
@@ -7124,10 +6493,8 @@ function ewww_image_optimizer_bulk_action_handler() {
7124
  $ids = implode( ',', array_map( 'intval', $_REQUEST['media'] ) );
7125
  wp_redirect( add_query_arg(
7126
  array(
7127
- 'page' => 'ewww-image-optimizer-bulk',
7128
- '_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-bulk' ),
7129
- 'goback' => 1,
7130
- 'ids' => $ids,
7131
  ),
7132
  admin_url( 'upload.php' )
7133
  ) );
@@ -7215,7 +6582,9 @@ function ewww_image_optimizer_settings_script( $hook ) {
7215
  if ( strpos( $hook, 'settings_page_ewww-image-optimizer' ) !== 0 ) {
7216
  return;
7217
  }
 
7218
  wp_enqueue_script( 'ewwwbulkscript', plugins_url( '/includes/eio.js', __FILE__ ), array( 'jquery' ), EWWW_IMAGE_OPTIMIZER_VERSION );
 
7219
  wp_enqueue_script( 'postbox' );
7220
  wp_enqueue_script( 'dashboard' );
7221
  wp_localize_script( 'ewwwbulkscript', 'ewww_vars', array(
@@ -7239,6 +6608,9 @@ function ewww_image_optimizer_savings() {
7239
  // Need to include the plugin library for the is_plugin_active function.
7240
  require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
7241
  }
 
 
 
7242
  if ( is_multisite() && is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) ) {
7243
  ewwwio_debug_message( 'querying savings for multi-site' );
7244
 
@@ -7260,7 +6632,6 @@ function ewww_image_optimizer_savings() {
7260
  'limit' => 1000,
7261
  ) );
7262
  }
7263
- $total_savings = 0;
7264
  if ( ewww_image_optimizer_iterable( $blogs ) ) {
7265
  foreach ( $blogs as $blog ) {
7266
  if ( is_array( $blog ) ) {
@@ -7276,9 +6647,12 @@ function ewww_image_optimizer_savings() {
7276
  ewww_image_optimizer_install_table();
7277
  }
7278
  if ( $wpdb->ewwwio_images ) {
7279
- $wpdb->query( "DELETE FROM $wpdb->ewwwio_images WHERE image_size > orig_size" );
7280
- $savings = $wpdb->get_var( "SELECT SUM(orig_size-image_size) FROM $wpdb->ewwwio_images" );
7281
- ewwwio_debug_message( "savings found: $savings" );
 
 
 
7282
  $total_savings += $savings;
7283
  }
7284
  restore_current_blog();
@@ -7286,17 +6660,22 @@ function ewww_image_optimizer_savings() {
7286
  }
7287
  } else {
7288
  ewwwio_debug_message( 'querying savings for single site' );
7289
- $total_savings = 0;
7290
- $table_name = $wpdb->ewwwio_images;
7291
  ewwwio_debug_message( "table name is $table_name" );
7292
  if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name ) ) != $table_name ) {
7293
  ewww_image_optimizer_install_table();
7294
  }
7295
- $wpdb->query( 'DELETE FROM ' . $wpdb->prefix . 'ewwwio_images WHERE image_size > orig_size' );
7296
- $total_savings = $wpdb->get_var( "SELECT SUM(orig_size-image_size) FROM $wpdb->ewwwio_images" );
7297
- ewwwio_debug_message( "savings found: $total_savings" );
 
 
 
7298
  } // End if().
7299
- return $total_savings;
 
 
 
7300
  }
7301
 
7302
  /**
@@ -7331,6 +6710,9 @@ function ewww_image_optimizer_webp_rewrite() {
7331
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-settings' ) ) {
7332
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
7333
  }
 
 
 
7334
  $ewww_rules = ewww_image_optimizer_webp_rewrite_verify();
7335
  if ( $ewww_rules ) {
7336
  if ( insert_with_markers( ewww_image_optimizer_htaccess_path(), 'EWWWIO', $ewww_rules ) && ! ewww_image_optimizer_webp_rewrite_verify() ) {
@@ -7352,6 +6734,9 @@ function ewww_image_optimizer_webp_unwrite() {
7352
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-settings' ) ) {
7353
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
7354
  }
 
 
 
7355
  if ( insert_with_markers( ewww_image_optimizer_htaccess_path(), 'EWWWIO', '' ) ) {
7356
  esc_html_e( 'Removal successful', 'ewww-image-optimizer' );
7357
  } else {
@@ -7391,8 +6776,8 @@ function ewww_image_optimizer_webp_rewrite_verify() {
7391
  '</IfModule>',
7392
  'AddType image/webp .webp',
7393
  );
7394
- if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
7395
- ewwwio_debug_message( print_r( $current_rules, true ) );
7396
  }
7397
  if ( empty( $current_rules ) ||
7398
  ! ewww_image_optimizer_array_search( '{HTTP_ACCEPT} image/webp', $current_rules ) ||
@@ -7487,8 +6872,8 @@ function ewww_image_optimizer_get_image_sizes() {
7487
  global $_wp_additional_image_sizes;
7488
  $sizes = array();
7489
  $image_sizes = get_intermediate_image_sizes();
7490
- if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
7491
- ewwwio_debug_message( print_r( $image_sizes, true ) );
7492
  }
7493
  if ( false ) { // set to true to enable more debugging.
7494
  ewwwio_debug_message( print_r( $_wp_additional_image_sizes, true ) );
@@ -7562,6 +6947,10 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7562
  ewwwio_debug_message( 'home url: ' . get_home_url() );
7563
  ewwwio_debug_message( 'site url: ' . get_site_url() );
7564
  ewwwio_debug_message( 'content_url: ' . content_url() );
 
 
 
 
7565
  $network_class = $network;
7566
  if ( empty( $network ) ) {
7567
  $network_class = 'singlesite';
@@ -7595,9 +6984,9 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7595
  $output[] = "<h1>EWWW Image Optimizer</h1>\n";
7596
  $output[] = "<div id='ewww-container-left' style='float: left; margin-right: 225px;'>\n";
7597
  $output[] = "<p><a href='https://ewww.io/'>" . esc_html__( 'Plugin Home Page', 'ewww-image-optimizer' ) . '</a> | ' .
7598
- "<a href='https://docs.ewww.io/'>" . esc_html__( 'Documentation', 'ewww-image-optimizer' ) . '</a> | ' .
7599
- "<a href='https://ewww.io/contact-us/'>" . esc_html__( 'Plugin Support', 'ewww-image-optimizer' ) . '</a> | ' .
7600
- "<a href='https://ewww.io/status/'>" . esc_html__( 'Cloud Status', 'ewww-image-optimizer' ) . '</a> | ' .
7601
  "<a href='https://ewww.io/downloads/s3-image-optimizer/'>" . esc_html__( 'S3 Image Optimizer', 'ewww-image-optimizer' ) . "</a></p>\n";
7602
  if ( 'network-multisite' == $network ) {
7603
  $bulk_link = esc_html__( 'Media Library', 'ewww-image-optimizer' ) . ' -> ' . esc_html__( 'Bulk Optimize', 'ewww-image-optimizer' );
@@ -7610,69 +6999,91 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7610
  /* translators: %s: Bulk Optimize (link) */
7611
  esc_html__( 'New images uploaded to the Media Library will be optimized automatically. If you have existing images you would like to optimize, you can use the %s tool.', 'ewww-image-optimizer' ),
7612
  $bulk_link
7613
- ) . ' ' .
7614
  sprintf(
7615
  /* translators: %s: S3 Image Optimizer (link) */
7616
  esc_html__( 'Images stored in an Amazon S3 bucket can be optimized using our %s.' ),
7617
  $s3_link
7618
  ) .
7619
  "</p>\n";
 
 
 
 
 
 
 
 
7620
  $status_output = "<div id='ewww-widgets' class='metabox-holder'><div class='meta-box-sortables'><div id='ewww-status' class='postbox'>\n" .
7621
- "<h2 class='hndle'>" . esc_html__( 'Plugin Status', 'ewww-image-optimizer' ) . "&emsp;STATUS_PLACEHOLDER</h2>\n<div class='inside'>";
7622
- $total_savings = ewww_image_optimizer_savings();
7623
- if ( $total_savings ) {
7624
- $status_output .= '<b>' . esc_html__( 'Total Savings:', 'ewww-image-optimizer' ) . "</b> <span id='ewww-total-savings'>" . ewww_image_optimizer_size_format( $total_savings, 2 ) . '</span><br>';
7625
- }
7626
- ewwwio_debug_message( ewww_image_optimizer_aux_images_table_count() . ' images have been optimized' );
7627
- // If this remains true, then we display an all clear, otherwise something needs fixing. TODO: rename this someday.
7628
- $collapsible = true;
7629
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
7630
- $status_output .= '<p><b>' . esc_html__( 'Cloud optimization API Key', 'ewww-image-optimizer' ) . ':</b> ';
7631
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_cloud_exceeded', 0 );
7632
  $verify_cloud = ewww_image_optimizer_cloud_verify( false );
7633
- if ( preg_match( '/great/', $verify_cloud ) ) {
7634
- $status_output .= '<span style="color: green">' . esc_html__( 'Verified,', 'ewww-image-optimizer' ) . ' </span>' . ewww_image_optimizer_cloud_quota();
7635
- } elseif ( preg_match( '/exceeded/', $verify_cloud ) ) {
7636
- $status_output .= '<span style="color: orange">' . esc_html__( 'Verified,', 'ewww-image-optimizer' ) . '</span> <a href="https://ewww.io/plans/" target="_blank">' . ewww_image_optimizer_cloud_quota() . '</a>';
7637
- $collapsible = false;
 
 
 
 
 
 
 
 
 
 
7638
  } else {
7639
- $status_output .= '<span style="color: red">' . esc_html__( 'Not Verified', 'ewww-image-optimizer' ) . '</span>';
7640
- $collapsible = false;
7641
  }
7642
- $status_output .= ' <a target="_blank" href="https://history.exactlywww.com/show/?api_key=' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) . '">' . esc_html__( 'View Usage', 'ewww-image-optimizer' ) . '</a>';
7643
- $status_output .= "</p>\n";
7644
- $disable_level = '';
 
 
7645
  } else {
 
 
 
7646
  $disable_level = "disabled='disabled'";
7647
  }
7648
  if ( class_exists( 'Jetpack_Photon' ) && Jetpack::is_module_active( 'photon' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
7649
- $status_output .= '<p><b>ExactDN:</b> <span style="color: red">' . esc_html__( 'Inactive, please disable the Image Performance option on the Jetpack Dashboard.', 'ewww-image-optimizer' ) . '</span></p>';
7650
- $collapsible = false;
7651
  } elseif ( class_exists( 'ExactDN' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
7652
- $status_output .= '<p><b>ExactDN:</b> ';
7653
  global $exactdn;
7654
  if ( $exactdn->get_exactdn_domain() && $exactdn->verify_domain( $exactdn->get_exactdn_domain() ) ) {
7655
- $status_output .= '<span style="color: green">' . esc_html__( 'Verified', 'ewww-image-optimizer' ) . ' </span>';
7656
  if ( defined( 'WP_ROCKET_VERSION' ) ) {
7657
- $status_output .= '<br><i>' . esc_html__( 'If you use the File Optimization options within WP Rocket, you should also enter your ExactDN CNAME in the WP Rocket CDN settings (reserved for CSS and Javascript):', 'ewww-image-optimizer' ) . ' ' . $exactdn->get_exactdn_domain() . '</i>';
 
 
 
 
 
 
 
 
 
7658
  }
7659
  } elseif ( $exactdn->get_exactdn_domain() && $exactdn->get_exactdn_option( 'verified' ) ) {
7660
- $status_output .= '<span style="color: orange">' . esc_html__( 'Temporarily disabled.', 'ewww-image-optimizer' ) . ' </span>';
7661
- $collapsible = false;
7662
  } elseif ( $exactdn->get_exactdn_domain() && $exactdn->get_exactdn_option( 'suspended' ) ) {
7663
- $status_output .= '<span style="color: orange">' . esc_html__( 'Active, not yet verified.', 'ewww-image-optimizer' ) . ' </span>';
7664
- $collapsible = false;
7665
  } else {
7666
  ewwwio_debug_message( 'could not verify: ' . $exactdn->get_exactdn_domain() );
7667
- $status_output .= '<span style="color: red"><a href="https://ewww.io/manage-sites/" target="_blank">' . esc_html__( 'Not Verified', 'ewww-image-optimizer' ) . '</a></span>';
7668
- $collapsible = false;
7669
  }
7670
  if ( function_exists( 'remove_query_strings_link' ) || function_exists( 'rmqrst_loader_src' ) || function_exists( 'qsr_remove_query_strings_1' ) ) {
7671
- $status_output .= '<br><i>' . esc_html__( 'Plugins that remove query strings are unnecessary with ExactDN. You may remove them at your convenience.', 'ewww-image-optimizer' ) . '</i>';
7672
  }
7673
- $status_output .= '</p>';
7674
  } elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
7675
- $status_output .= '<p><b>ExactDN:</b> ' . esc_html__( 'Inactive, enable automatic resizing in the Resize Settings', 'ewww-image-optimizer' ) . '</p>';
 
7676
  delete_option( 'ewww_image_optimizer_exactdn_domain' );
7677
  delete_option( 'ewww_image_optimizer_exactdn_failures' );
7678
  delete_option( 'ewww_image_optimizer_exactdn_checkin' );
@@ -7686,13 +7097,24 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7686
  delete_site_option( 'ewww_image_optimizer_exactdn_validation' );
7687
  delete_site_option( 'ewww_image_optimizer_exactdn_suspended' );
7688
  }
7689
- if ( ! ewww_image_optimizer_full_cloud() && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
7690
- list ( $jpegtran_src, $optipng_src, $gifsicle_src, $jpegtran_dst, $optipng_dst, $gifsicle_dst ) = ewww_image_optimizer_install_paths();
 
 
 
 
 
 
 
 
 
 
 
 
 
7691
  }
7692
- $skip = ewww_image_optimizer_skip_tools();
7693
- $status_output .= "<p>\n";
7694
  if ( ! $skip['jpegtran'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
7695
- $status_output .= '<b>jpegtran:</b> ';
7696
  if ( EWWW_IMAGE_OPTIMIZER_JPEGTRAN ) {
7697
  $jpegtran_installed = ewww_image_optimizer_tool_found( EWWW_IMAGE_OPTIMIZER_JPEGTRAN, 'j' );
7698
  if ( ! $jpegtran_installed ) {
@@ -7700,14 +7122,12 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7700
  }
7701
  }
7702
  if ( ! empty( $jpegtran_installed ) ) {
7703
- $status_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span>&emsp;' . esc_html__( 'version', 'ewww-image-optimizer' ) . ': ' . $jpegtran_installed . "<br />\n";
7704
  } else {
7705
- $status_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span><br />' . "\n";
7706
- $collapsible = false;
7707
  }
7708
  }
7709
  if ( ! $skip['optipng'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
7710
- $status_output .= '<b>optipng:</b> ';
7711
  if ( EWWW_IMAGE_OPTIMIZER_OPTIPNG ) {
7712
  $optipng_version = ewww_image_optimizer_tool_found( EWWW_IMAGE_OPTIMIZER_OPTIPNG, 'o' );
7713
  if ( ! $optipng_version ) {
@@ -7715,14 +7135,12 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7715
  }
7716
  }
7717
  if ( ! empty( $optipng_version ) ) {
7718
- $status_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span>&emsp;' . esc_html__( 'version', 'ewww-image-optimizer' ) . ': ' . $optipng_version . "<br />\n";
7719
  } else {
7720
- $status_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span><br />' . "\n";
7721
- $collapsible = false;
7722
  }
7723
  }
7724
  if ( ! $skip['pngout'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
7725
- $status_output .= '<b>pngout:</b> ';
7726
  if ( EWWW_IMAGE_OPTIMIZER_PNGOUT ) {
7727
  $pngout_version = ewww_image_optimizer_tool_found( EWWW_IMAGE_OPTIMIZER_PNGOUT, 'p' );
7728
  if ( ! $pngout_version ) {
@@ -7730,29 +7148,12 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7730
  }
7731
  }
7732
  if ( ! empty( $pngout_version ) ) {
7733
- $status_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span>&emsp;' . esc_html__( 'version', 'ewww-image-optimizer' ) . ': ' . preg_replace( '/PNGOUT \[.*\)\s*?/', '', $pngout_version ) . "<br />\n";
7734
- } else {
7735
- $status_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span>&emsp;' . esc_html__( 'Install', 'ewww-image-optimizer' ) . ' <a href="admin.php?action=ewww_image_optimizer_install_pngout">' . esc_html__( 'automatically', 'ewww-image-optimizer' ) . '</a> | <a href="http://advsys.net/ken/utils.htm">' . esc_html__( 'manually', 'ewww-image-optimizer' ) . '</a> - ' . esc_html__( 'Pngout is free closed-source software that can produce drastically reduced filesizes for PNGs, but can be very time consuming to process images', 'ewww-image-optimizer' ) . "<br />\n";
7736
- $collapsible = false;
7737
- }
7738
- }
7739
- if ( ! $skip['gifsicle'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
7740
- $status_output .= '<b>gifsicle:</b> ';
7741
- if ( EWWW_IMAGE_OPTIMIZER_GIFSICLE ) {
7742
- $gifsicle_version = ewww_image_optimizer_tool_found( EWWW_IMAGE_OPTIMIZER_GIFSICLE, 'g' );
7743
- if ( ! $gifsicle_version ) {
7744
- $gifsicle_version = ewww_image_optimizer_tool_found( EWWW_IMAGE_OPTIMIZER_GIFSICLE, 'gb' );
7745
- }
7746
- }
7747
- if ( ! empty( $gifsicle_version ) ) {
7748
- $status_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span>&emsp;' . esc_html__( 'version', 'ewww-image-optimizer' ) . ': ' . $gifsicle_version . "<br />\n";
7749
  } else {
7750
- $status_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span><br />' . "\n";
7751
- $collapsible = false;
7752
  }
7753
  }
7754
  if ( ! $skip['pngquant'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
7755
- $status_output .= '<b>pngquant:</b> ';
7756
  if ( EWWW_IMAGE_OPTIMIZER_PNGQUANT ) {
7757
  $pngquant_version = ewww_image_optimizer_tool_found( EWWW_IMAGE_OPTIMIZER_PNGQUANT, 'q' );
7758
  if ( ! $pngquant_version ) {
@@ -7760,14 +7161,25 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7760
  }
7761
  }
7762
  if ( ! empty( $pngquant_version ) ) {
7763
- $status_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span>&emsp;' . esc_html__( 'version', 'ewww-image-optimizer' ) . ': ' . $pngquant_version . "<br />\n";
 
 
 
 
 
 
 
 
 
 
 
 
 
7764
  } else {
7765
- $status_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span><br />' . "\n";
7766
- $collapsible = false;
7767
  }
7768
  }
7769
  if ( EWWW_IMAGE_OPTIMIZER_CWEBP && ! $skip['webp'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
7770
- $status_output .= '<b>webp:</b> ';
7771
  if ( EWWW_IMAGE_OPTIMIZER_CWEBP ) {
7772
  $webp_version = ewww_image_optimizer_tool_found( EWWW_IMAGE_OPTIMIZER_CWEBP, 'w' );
7773
  if ( ! $webp_version ) {
@@ -7775,148 +7187,143 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7775
  }
7776
  }
7777
  if ( ! empty( $webp_version ) ) {
7778
- $status_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span>&emsp;' . esc_html__( 'version', 'ewww-image-optimizer' ) . ': ' . $webp_version . "<br />\n";
7779
  } else {
7780
- $status_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span><br />' . "\n";
7781
- $collapsible = false;
7782
  }
7783
  }
7784
- if ( ! ewww_image_optimizer_full_cloud() ) {
7785
- if ( ewww_image_optimizer_exec_check() ) {
7786
- $status_output .= 'exec(): <span style="color: red; font-weight: bolder">' . esc_html__( 'Disabled', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7787
- $collapsible = false;
7788
- } else {
7789
- $status_output .= 'exec(): <span style="color: green; font-weight: bolder">' . esc_html__( 'Enabled', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7790
- }
7791
- $status_output .= "<br />\n";
7792
- }
7793
- if ( ! ewww_image_optimizer_full_cloud() && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
7794
- $toolkit_output = sprintf(
7795
- /* translators: %s: Graphics libraries - */
7796
- esc_html__( '%s only need one, used for conversion, not optimization', 'ewww-image-optimizer' ),
7797
- '<b>' . __( 'Graphics libraries', 'ewww-image-optimizer' ) . '</b> - '
7798
- );
7799
- $toolkit_output .= '<br>';
7800
- $toolkit_found = false;
7801
- if ( ewww_image_optimizer_gd_support() ) {
7802
- $toolkit_output .= 'GD: <span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' );
7803
- $toolkit_found = true;
7804
- } else {
7805
- $toolkit_output .= 'GD: <span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' );
7806
- }
7807
- $toolkit_output .= '</span>&emsp;&emsp;' .
7808
- 'Gmagick: ';
7809
- if ( ewww_image_optimizer_gmagick_support() ) {
7810
- $toolkit_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' );
7811
- $toolkit_found = true;
7812
- } else {
7813
- $toolkit_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' );
7814
- }
7815
- $toolkit_output .= '</span>&emsp;&emsp;' .
7816
- 'Imagick: ';
7817
- if ( ewww_image_optimizer_imagick_support() ) {
7818
- $toolkit_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' );
7819
- $toolkit_found = true;
7820
- } else {
7821
- $toolkit_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' );
7822
- }
7823
- $toolkit_output .= "</span><br />\n";
7824
- if ( ! $toolkit_found && ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_to_jpg' ) || ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_to_png' ) ) ) {
7825
- $collapsible = false;
7826
- } else {
7827
- $toolkit_output = str_replace( 'color: red', 'color: gray', $toolkit_output );
7828
- }
7829
- $status_output .= $toolkit_output;
7830
- } else {
7831
- ewww_image_optimizer_gd_support();
7832
- ewww_image_optimizer_gmagick_support();
7833
- ewww_image_optimizer_imagick_support();
7834
- } // End if().
7835
- $mimetype_output = '<b>' . esc_html__( 'Only need one of these:', 'ewww-image-optimizer' ) . ' </b><br>';
7836
- // Initialize this variable to check for the 'file' command if we don't have any php libraries we can use.
7837
- $file_command_check = true;
7838
- $mimetype_tool = '';
7839
- if ( function_exists( 'finfo_file' ) ) {
7840
- $mimetype_output .= 'fileinfo: <span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7841
- $file_command_check = false;
7842
- $mimetype_tool = 'fileinfo';
7843
- } else {
7844
- $mimetype_output .= 'fileinfo: <span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7845
  }
7846
- if ( function_exists( 'getimagesize' ) ) {
7847
- $mimetype_output .= 'getimagesize(): <span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7848
- if ( ewww_image_optimizer_full_cloud() || EWWW_IMAGE_OPTIMIZER_NOEXEC || PHP_OS == 'WINNT' ) {
7849
- $file_command_check = false;
7850
- }
7851
- $mimetype_tool = empty( $mimetype_tool ) ? 'getimagesize' : $mimetype_tool;
7852
- } else {
7853
- $mimetype_output .= 'getimagesize(): <span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7854
  }
7855
- if ( function_exists( 'mime_content_type' ) ) {
7856
- $mimetype_output .= 'mime_content_type(): <span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span><br />' . "\n";
7857
- $file_command_check = false;
7858
- $mimetype_tool = empty( $mimetype_tool ) ? 'mime_content_type' : $mimetype_tool;
7859
- } else {
7860
- $mimetype_output .= 'mime_content_type(): <span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span><br />' . "\n";
7861
  }
7862
- $extra_tool_output = '';
7863
  if ( PHP_OS != 'WINNT' && ! ewww_image_optimizer_full_cloud() && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
7864
- if ( $file_command_check && ! ewww_image_optimizer_find_nix_binary( 'file', 'f' ) ) {
7865
- $extra_tool_output .= '<span style="color: red; font-weight: bolder">file: ' . esc_html__( 'command not found on your system', 'ewww-image-optimizer' ) . '</span><br />';
7866
- $collapsible = false;
7867
- } elseif ( empty( $mimetype_tool ) ) {
7868
- $mimetype_tool = 'file'; // So that we know a mimetype library was found.
7869
- }
7870
- if ( ! ewww_image_optimizer_find_nix_binary( 'nice', 'n' ) ) {
7871
- $extra_tool_output .= '<span style="color: orange; font-weight: bolder">nice: ' . esc_html__( 'command not found on your system', 'ewww-image-optimizer' ) . ' (' . esc_html__( 'not required', 'ewww-image-optimizer' ) . ')</span><br />';
7872
- }
7873
- if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_pngout' ) && ! $skip['pngout'] && PHP_OS != 'SunOS' && ! ewww_image_optimizer_find_nix_binary( 'tar', 't' ) ) {
7874
- $extra_tool_output .= '<span style="color: red; font-weight: bolder">tar: ' . esc_html__( 'command not found on your system', 'ewww-image-optimizer' ) . ' (' . esc_html__( 'required for automatic pngout installer', 'ewww-image-optimizer' ) . ')</span><br />';
7875
- $collapsible = false;
7876
- }
7877
- } elseif ( $file_command_check ) {
7878
- $collapsible = false;
7879
  }
7880
- if ( false && 'getimagesize' == $mimetype_tool && ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ) ) {
7881
- $collapsible = false;
7882
- ewww_image_optimizer_set_option( 'ewww_image_optimizer_pdf_level', 0 );
7883
- } elseif ( $mimetype_tool ) {
7884
- $mimetype_output = str_replace( 'color: red', 'color: gray', $mimetype_output );
7885
- }
7886
- ewwwio_debug_message( "mimetype function in use: $mimetype_tool" );
7887
- // The whole mimetype section can go away when we're comfortable that nothing has broken.
7888
- /* $status_output .= $mimetype_output; */
7889
- $status_output .= $extra_tool_output;
7890
- $status_output .= '<strong>' . esc_html( 'Background and Parallel optimization (faster uploads):', 'ewww-image-optimizer' ) . '</strong><br>';
7891
  if ( defined( 'EWWW_DISABLE_ASYNC' ) && EWWW_DISABLE_ASYNC ) {
7892
- $status_output .= '<span>' . esc_html__( 'Disabled by administrator', 'ewww-image-optimizer' ) . '</span>';
7893
  } elseif ( ! ewww_image_optimizer_function_exists( 'sleep' ) ) {
7894
- $status_output .= '<span style="color: orange; font-weight: bolder">' . esc_html__( 'Disabled, sleep function missing', 'ewww-image-optimizer' ) . '</span>';
7895
  } elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_background_optimization' ) ) {
7896
- $status_output .= '<span style="color: orange; font-weight: bolder">' . esc_html__( 'Disabled automatically, async requests blocked', 'ewww-image-optimizer' ) . " - <a href='admin.php?action=ewww_image_optimizer_retest_background_optimization'>" . esc_html__( 'Re-test', 'ewww-image-optimizer' ) . '</a><span>';
7897
  } elseif ( ewww_image_optimizer_detect_wpsf_location_lock() ) {
7898
- $status_output .= '<span style="color: orange; font-weight: bolder">' . esc_html__( "Disabled by Shield's Lock to Location feature", 'ewww-image-optimizer' ) . '</span>';
7899
  } elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_parallel_optimization' ) ) {
7900
- $status_output .= '<span>' . esc_html__( 'Background mode active, enable Parallel Optimization in Advanced Settings', 'ewww-image-optimizer' ) . '</span>';
7901
  } else {
7902
- $status_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Fully Enabled', 'ewww-image-optimizer' ) . '</span>';
7903
  }
7904
- $status_output .= '</div><!-- end .inside -->';
7905
- $status_output .= "</div></div></div>\n";
7906
- if ( $collapsible ) {
7907
- $output[] = str_replace( 'STATUS_PLACEHOLDER', "<span id='ewww-status-ok' style='color: green;'>" . esc_html__( 'All Clear', 'ewww-image-optimizer' ) . '</span>', $status_output );
 
 
 
7908
  } else {
7909
- $output[] = str_replace( 'STATUS_PLACEHOLDER', "<span id='ewww-status-attention' style='color: red;'>" . esc_html__( 'Requires Attention', 'ewww-image-optimizer' ) . '</span>', $status_output );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7910
  }
 
 
 
 
 
 
 
 
 
 
 
7911
  if ( ( 'network-multisite' != $network || ! get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) ) && // Display tabs so long as this isn't the network admin OR single-site override is disabled.
7912
  ! ( 'network-singlesite' == $network && ! get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) ) ) { // Also make sure that this isn't single site without override mode.
7913
  $output[] = "<ul class='ewww-tab-nav'>\n" .
7914
- "<li class='ewww-tab ewww-general-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Basic Settings', 'ewww-image-optimizer' ) . "</span></li>\n" .
7915
- "<li class='ewww-tab ewww-optimization-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Advanced Settings', 'ewww-image-optimizer' ) . "</span></li>\n" .
7916
- "<li class='ewww-tab ewww-resize-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Resize Settings', 'ewww-image-optimizer' ) . "</span></li>\n" .
7917
- "<li class='ewww-tab ewww-conversion-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Conversion Settings', 'ewww-image-optimizer' ) . "</span></li>\n" .
7918
- "<li class='ewww-tab ewww-webp-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'WebP Settings', 'ewww-image-optimizer' ) . "</span></li>\n" .
7919
- "<li class='ewww-tab ewww-overrides-nav'><span class='ewww-tab-hidden'><a href='https://docs.ewww.io/article/40-override-options' target='_blank' data-beacon-article='59710ce4042863033a1b45a6'><span class='ewww-tab-hidden'>" . esc_html__( 'Overrides', 'ewww-image-optimizer' ) . "</a></span></li>\n" .
 
7920
  "</ul>\n";
7921
  }
7922
  if ( 'network-multisite' == $network ) {
@@ -7934,10 +7341,10 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7934
  $output[] = "<table class='form-table'>\n";
7935
  if ( is_multisite() ) {
7936
  if ( is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) ) {
7937
- $output[] = "<tr class='network-only'><th><label for='ewww_image_optimizer_allow_multisite_override'>" . esc_html__( 'Allow Single-site Override', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_allow_multisite_override' name='ewww_image_optimizer_allow_multisite_override' value='true' " . ( get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Allow individual sites to configure their own settings and override all network options.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7938
  }
7939
  if ( 'network-multisite' == $network && get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) ) {
7940
- $output[] = "<tr><th><label for='ewww_image_optimizer_allow_tracking'>" . esc_html__( 'Allow Usage Tracking?', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_allow_tracking' name='ewww_image_optimizer_allow_tracking' value='true' " . ( get_site_option( 'ewww_image_optimizer_allow_tracking' ) == true ? "checked='true'" : '' ) . ' /> ' .
7941
  esc_html__( 'Allow EWWW Image Optimizer to anonymously track how this plugin is used and help us make the plugin better. Opt-in to tracking and receive 500 API image credits free. No sensitive data is tracked.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7942
  $output[] = "<input type='hidden' id='ewww_image_optimizer_allow_multisite_override_active' name='ewww_image_optimizer_allow_multisite_override_active' value='0'>";
7943
  if ( get_site_option( 'ewww_image_optimizer_cloud_key' ) ) {
@@ -7953,13 +7360,14 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7953
  }
7954
  }
7955
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
7956
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_cloud_notkey'>" . esc_html__( 'Cloud optimization API Key', 'ewww-image-optimizer' ) . "</label></th><td><input type='text' id='ewww_image_optimizer_cloud_notkey' name='ewww_image_optimizer_cloud_notkey' readonly='readonly' value='****************************" . substr( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ), 28 ) . "' size='32' /> <a href='admin.php?action=ewww_image_optimizer_remove_cloud_key'>" . esc_html__( 'Remove API key', 'ewww-image-optimizer' ) . "</a></td></tr>\n";
7957
  $output[] = "<input type='hidden' id='ewww_image_optimizer_cloud_key' name='ewww_image_optimizer_cloud_key' value='" . ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) . "' />\n";
7958
  } else {
7959
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_cloud_key'>" . esc_html__( 'Cloud optimization API Key', 'ewww-image-optimizer' ) . "</label></th><td><input type='text' id='ewww_image_optimizer_cloud_key' name='ewww_image_optimizer_cloud_key' value='' size='32' /> " . esc_html__( 'API Key will be validated when you save your settings.', 'ewww-image-optimizer' ) . " <a href='https://ewww.io/plans/' target='_blank'>" . esc_html__( 'Purchase an API key.', 'ewww-image-optimizer' ) . "</a></td></tr>\n";
7960
  }
7961
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_debug'>" . esc_html__( 'Debugging', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_debug' name='ewww_image_optimizer_debug' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Use this to provide information for support purposes, or if you feel comfortable digging around in the code to fix a problem you are experiencing.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7962
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_jpegtran_copy'>" . esc_html__( 'Remove metadata', 'ewww-image-optimizer' ) . "</label></th>\n" .
 
7963
  "<td><input type='checkbox' id='ewww_image_optimizer_jpegtran_copy' name='ewww_image_optimizer_jpegtran_copy' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'This will remove ALL metadata: EXIF, comments, color profiles, and anything else that is not pixel data.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7964
  ewwwio_debug_message( 'remove metadata: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) == true ? 'on' : 'off' ) );
7965
  $output[] = "<tr class='$network_class'><th>&nbsp;</th><td>" .
@@ -7967,7 +7375,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7967
  ' ' . esc_html__( 'Lossless compression is actually identical to the original, while lossy reduces the quality a small amount.', 'ewww-image-optimizer' ) . "</p>\n" .
7968
  ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ? "<p class='$network_class nocloud'><strong>* <a href='https://ewww.io/plans/' target='_blank'>" . esc_html__( 'Get an API key to achieve up to 80% compression and see the quality for yourself.', 'ewww-image-optimizer' ) . "</a></strong></p>\n" : '' );
7969
  $output[] = "</td></tr>\n";
7970
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_jpg_level'>" . esc_html__( 'JPG Optimization Level', 'ewww-image-optimizer' ) . "</label></th>\n" .
7971
  "<td><span><select id='ewww_image_optimizer_jpg_level' name='ewww_image_optimizer_jpg_level'>\n" .
7972
  "<option value='0'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ), 0, false ) . '>' . esc_html__( 'No Compression', 'ewww-image-optimizer' ) . "</option>\n";
7973
  if ( defined( 'EWWW_IMAGE_OPTIMIZER_TOOL_PATH' ) ) {
@@ -7978,7 +7386,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7978
  "<option $disable_level value='40'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ), 40, false ) . '>' . esc_html__( 'Maximum Lossy Compression', 'ewww-image-optimizer' ) . " *</option>\n" .
7979
  "</select></td></tr>\n";
7980
  ewwwio_debug_message( 'jpg level: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) );
7981
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_png_level'>" . esc_html__( 'PNG Optimization Level', 'ewww-image-optimizer' ) . "</label></th>\n" .
7982
  "<td><span><select id='ewww_image_optimizer_png_level' name='ewww_image_optimizer_png_level'>\n" .
7983
  "<option value='0'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ), 0, false ) . '>' . esc_html__( 'No Compression', 'ewww-image-optimizer' ) . "</option>\n";
7984
  if ( defined( 'EWWW_IMAGE_OPTIMIZER_TOOL_PATH' ) ) {
@@ -7990,34 +7398,59 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7990
  "<option $disable_level value='50'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ), 50, false ) . '>' . esc_html__( 'Maximum Lossy Compression', 'ewww-image-optimizer' ) . " *</option>\n" .
7991
  "</select></td></tr>\n";
7992
  ewwwio_debug_message( 'png level: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) );
7993
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_gif_level'>" . esc_html__( 'GIF Optimization Level', 'ewww-image-optimizer' ) . "</label></th>\n" .
7994
  "<td><span><select id='ewww_image_optimizer_gif_level' name='ewww_image_optimizer_gif_level'>\n" .
7995
  "<option value='0'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' ), 0, false ) . '>' . esc_html__( 'No Compression', 'ewww-image-optimizer' ) . "</option>\n" .
7996
  "<option value='10'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' ), 10, false ) . '>' . esc_html__( 'Lossless Compression', 'ewww-image-optimizer' ) . "</option>\n" .
7997
  "</select></td></tr>\n";
7998
  ewwwio_debug_message( 'gif level: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' ) );
7999
- $disable_pdf_level = $disable_level;
8000
- if ( false && 'getimagesize' == $mimetype_tool ) {
8001
- $disable_pdf_level = "disabled='disabled'";
8002
- $output[] = "<tr class='$network_class'><th>&nbsp;</th><td>";
8003
- $output[] = "<p class='$network_class description'>" . esc_html__( '*PDF optimization cannot be enabled because the fileinfo extension is missing.', 'ewww-image-optimizer' ) . "</p></td></tr>\n";
8004
- }
8005
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_pdf_level'>" . esc_html__( 'PDF Optimization Level', 'ewww-image-optimizer' ) . "</label></th>\n" .
8006
  "<td><span><select id='ewww_image_optimizer_pdf_level' name='ewww_image_optimizer_pdf_level'>\n" .
8007
  "<option value='0'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ), 0, false ) . '>' . esc_html__( 'No Compression', 'ewww-image-optimizer' ) . "</option>\n" .
8008
- "<option $disable_pdf_level value='10'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ), 10, false ) . '>' . esc_html__( 'Lossless Compression', 'ewww-image-optimizer' ) . " *</option>\n" .
8009
- "<option $disable_pdf_level value='20'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ), 20, false ) . '>' . esc_html__( 'Lossy Compression', 'ewww-image-optimizer' ) . " *</option>\n" .
8010
  "</select></td></tr>\n";
8011
  ewwwio_debug_message( 'pdf level: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ) );
8012
  ewwwio_debug_message( 'bulk delay: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_delay' ) );
8013
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_backup_files'>" . esc_html__( 'Backup Originals', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_backup_files' name='ewww_image_optimizer_backup_files' value='true' " .
 
8014
  ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_backup_files' ) ? "checked='true'" : '' ) . " $disable_level > " . esc_html__( 'Store a copy of your original images on our secure server for 30 days. *Requires an active API key.', 'ewww-image-optimizer' ) . "</td></tr>\n";
8015
  ewwwio_debug_message( 'backup mode: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_backup_files' ) ? 'on' : 'off' ) );
8016
  if ( class_exists( 'Cloudinary' ) && Cloudinary::config_get( 'api_secret' ) ) {
8017
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_enable_cloudinary'>" . esc_html__( 'Automatic Cloudinary upload', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_enable_cloudinary' name='ewww_image_optimizer_enable_cloudinary' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_cloudinary' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'When enabled, uploads to the Media Library will be transferred to Cloudinary after optimization. Cloudinary generates resizes, so only the full-size image is uploaded.', 'ewww-image-optimizer' ) . "</td></tr>\n";
8018
  ewwwio_debug_message( 'cloudinary upload: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_cloudinary' ) == true ? 'on' : 'off' ) );
8019
  }
8020
  $output[] = "</table>\n</div>\n";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8021
  $output[] = "<div id='ewww-optimization-settings'>\n";
8022
  $output[] = "<table class='form-table'>\n";
8023
  if ( ! ewww_image_optimizer_full_cloud() ) {
@@ -8025,8 +7458,8 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8025
  ewwwio_debug_message( 'pngout disabled: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_pngout' ) == true ? 'yes' : 'no' ) );
8026
  ewwwio_debug_message( 'pngout level: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_pngout_level' ) );
8027
  }
8028
- $output[] = "<tr class='$network_class'><th><span><label for='ewww_image_optimizer_jpg_quality'>" . esc_html__( 'JPG quality level:', 'ewww-image-optimizer' ) . "</label></th><td><input type='text' id='ewww_image_optimizer_jpg_quality' name='ewww_image_optimizer_jpg_quality' class='small-text' value='" . ewww_image_optimizer_jpg_quality() . "' /> " . esc_html__( 'Valid values are 1-100.', 'ewww-image-optimizer' ) . "\n<p class='description'>" . esc_html__( 'Use this to override the default WordPress quality level of 82. Applies to image editing, resizing, PNG to JPG conversion, and JPG to WebP conversion. Does not affect the original uploaded image unless maximum dimensions are set and resizing occurs.', 'ewww-image-optimizer' ) . "</p></td></tr>\n";
8029
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_parallel_optimization'>" . esc_html__( 'Parallel optimization', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_parallel_optimization' name='ewww_image_optimizer_parallel_optimization' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_parallel_optimization' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'All resizes generated from a single upload are optimized in parallel for faster optimization. If this is causing performance issues, disable parallel optimization to reduce the load on your server.', 'ewww-image-optimizer' ) . "</td></tr>\n";
8030
  ewwwio_debug_message( 'parallel optimization: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_parallel_optimization' ) == true ? 'on' : 'off' ) );
8031
  ewwwio_debug_message( 'background optimization: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_background_optimization' ) == true ? 'on' : 'off' ) );
8032
  if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_background_optimization' ) ) {
@@ -8072,18 +7505,18 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8072
  ewwwio_debug_message( "invalid admin ajax url: $admin_ajax_url" );
8073
  }
8074
  }
8075
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_auto'>" . esc_html__( 'Scheduled optimization', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_auto' name='ewww_image_optimizer_auto' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_auto' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'This will enable scheduled optimization of unoptimized images for your theme, buddypress, and any additional folders you have configured below. Runs hourly: wp_cron only runs when your site is visited, so it may be even longer between optimizations.', 'ewww-image-optimizer' ) . "</td></tr>\n";
8076
  ewwwio_debug_message( 'scheduled optimization: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_auto' ) == true ? 'on' : 'off' ) );
8077
  $media_include_disable = '';
8078
  if ( get_option( 'ewww_image_optimizer_disable_resizes_opt' ) ) {
8079
  $media_include_disable = 'disabled="disabled"';
8080
  $output[] = "<tr class='$network_class'><th>&nbsp;</th><td>" .
8081
- '<p><span style="color: green">' . esc_html__( '*Include Media Library Folders has been disabled because it will cause the scanner to ignore the disabled resizes.', 'ewww-image-optimizer' ) . "</span></p></td></tr>\n";
8082
  }
8083
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_include_media_paths'>" . esc_html__( 'Include Media Library Folders', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_include_media_paths' name='ewww_image_optimizer_include_media_paths' $media_include_disable value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_include_media_paths' ) == true && ! get_option( 'ewww_image_optimizer_disable_resizes_opt' ) ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Scan all images from the latest two folders of the Media Library during the Bulk Optimizer and Scheduled Optimization.', 'ewww-image-optimizer' ) . "</td></tr>\n";
8084
  ewwwio_debug_message( 'include media library: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_include_media_paths' ) == true ? 'on' : 'off' ) );
8085
  $aux_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_aux_paths' ) ? esc_html( implode( "\n", ewww_image_optimizer_get_option( 'ewww_image_optimizer_aux_paths' ) ) ) : '';
8086
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_aux_paths'>" . esc_html__( 'Folders to optimize', 'ewww-image-optimizer' ) . '</label></th><td>' .
8087
  /* translators: %s: the folder where WordPress is installed */
8088
  sprintf( esc_html__( 'One path per line, must be within %s. Use full paths, not relative paths.', 'ewww-image-optimizer' ), ABSPATH ) . "<br>\n" .
8089
  "<textarea id='ewww_image_optimizer_aux_paths' name='ewww_image_optimizer_aux_paths' rows='3' cols='60'>$aux_paths</textarea>\n" .
@@ -8092,7 +7525,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8092
  ewwwio_debug_message( $aux_paths );
8093
 
8094
  $exclude_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_exclude_paths' ) ? esc_html( implode( "\n", ewww_image_optimizer_get_option( 'ewww_image_optimizer_exclude_paths' ) ) ) : '';
8095
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_exclude_paths'>" . esc_html__( 'Folders to ignore', 'ewww-image-optimizer' ) . '</label></th><td>' . esc_html__( 'One path per line, partial paths allowed, but no urls.', 'ewww-image-optimizer' ) . "<br>\n" .
8096
  "<textarea id='ewww_image_optimizer_exclude_paths' name='ewww_image_optimizer_exclude_paths' rows='3' cols='60'>$exclude_paths</textarea>\n" .
8097
  "<p class='description'>" . esc_html__( 'A file that matches any pattern or path provided will not be optimized.', 'ewww-image-optimizer' ) . "</p></td></tr>\n";
8098
  ewwwio_debug_message( 'folders to ignore:' );
@@ -8102,53 +7535,37 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8102
  ewwwio_debug_message( 'exclude originals from lossy: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_lossy_skip_full' ) == true ? 'on' : 'off' ) );
8103
  ewwwio_debug_message( 'exclude originals from metadata removal: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_skip_full' ) == true ? 'on' : 'off' ) );
8104
  ewwwio_debug_message( 'use system binaries: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_skip_bundle' ) == true ? 'yes' : 'no' ) );
8105
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_enable_help'>" . esc_html__( 'Enable Embedded Help', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_enable_help' name='ewww_image_optimizer_enable_help' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_help' ) == true ? "checked='true'" : '' ) . ' /> ' .
8106
  esc_html__( 'Enable the support beacon, which gives you access to documentation and our support team right from your WordPress dashboard. To assist you more efficiently, we may collect the current url, IP address, browser/device information, and debugging information.', 'ewww-image-optimizer' ) . "</td></tr>\n";
8107
  ewwwio_debug_message( 'enable help beacon: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_help' ) == true ? 'yes' : 'no' ) );
8108
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_allow_tracking'>" . esc_html__( 'Allow Usage Tracking?', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_allow_tracking' name='ewww_image_optimizer_allow_tracking' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_allow_tracking' ) == true ? "checked='true'" : '' ) . ' /> ' .
8109
  esc_html__( 'Allow EWWW Image Optimizer to anonymously track how this plugin is used and help us make the plugin better. Opt-in to tracking and receive 500 API image credits free. No sensitive data is tracked.', 'ewww-image-optimizer' ) . "</td></tr>\n";
8110
  $output[] = "</table>\n</div>\n";
8111
 
8112
  $output[] = "<div id='ewww-resize-settings'>\n";
8113
  $output[] = "<table class='form-table'>\n";
8114
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_exactdn'>" . esc_html__( 'ExactDN', 'ewww-image-optimizer' ) .
8115
- "</label></th><td><input type='checkbox' id='ewww_image_optimizer_exactdn' name='ewww_image_optimizer_exactdn' value='true' " .
8116
- ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) == true ? "checked='true'" : '' ) . ' /> ' .
8117
- esc_html__( 'Enables CDN and automatic image resizing to fit your pages.', 'ewww-image-optimizer' ) .
8118
- ' <a href="https://ewww.io/resize/" target="_blank">' . esc_html__( 'Purchase a subscription for your site.', 'ewww-image-optimizer' ) . '</a>' .
8119
- '<p class="description">' . // esc_html__( 'WebP Conversion', 'ewww-image-optimizer' ) . '<br>' .
8120
- esc_html__( 'Retina Support, use WP Retina 2x for best results', 'ewww-image-optimizer' ) . '<br>' .
8121
- esc_html__( 'Maximum Lossless Compression', 'ewww-image-optimizer' ) . '<br>' .
8122
- esc_html__( 'Adjustable Quality', 'ewww-image-optimizer' ) . '<br>' .
8123
- '<a href="https://docs.ewww.io/article/44-introduction-to-exactdn" target="_blank" data-beacon-article="59bc5ad6042863033a1ce370">' . esc_html__( 'Learn more about ExactDN', 'ewww-image-optimizer' ) . '</a>' .
8124
- "</p></td></tr>\n";
8125
- ewwwio_debug_message( 'ExactDN enabled: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) == true ? 'on' : 'off' ) );
8126
- ewwwio_debug_message( 'ExactDN all the things: ' . ( ewww_image_optimizer_get_option( 'exactdn_all_the_things' ) == true ? 'on' : 'off' ) );
8127
- ewwwio_debug_message( 'ExactDN lossy: ' . intval( ewww_image_optimizer_get_option( 'exactdn_lossy' ) ) );
8128
- ewwwio_debug_message( 'ExactDN resize existing: ' . ( ewww_image_optimizer_get_option( 'exactdn_resize_existing' ) == true ? 'on' : 'off' ) );
8129
- ewwwio_debug_message( 'ExactDN attachment queries: ' . ( ewww_image_optimizer_get_option( 'exactdn_prevent_db_queries' ) == true ? 'off' : 'on' ) );
8130
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_resize_detection'>" . esc_html__( 'Resize Detection', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_resize_detection' name='ewww_image_optimizer_resize_detection' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_detection' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Highlight images that need to be resized because the browser is scaling them down. Only visible for Admin users and adds a button to the admin bar to detect scaled images that have been lazy loaded.', 'ewww-image-optimizer' ) . "</td></tr>\n";
8131
  ewwwio_debug_message( 'resize detection: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_detection' ) == true ? 'on' : 'off' ) );
8132
  if ( function_exists( 'imsanity_get_max_width_height' ) ) {
8133
  $output[] = "<tr class='$network_class'><th>&nbsp;</th><td>" .
8134
- '<p><span style="color: green">' . esc_html__( '*Imsanity settings override the EWWW resize dimensions.', 'ewww-image-optimizer' ) . "</span></p></td></tr>\n";
8135
  }
8136
- $output[] = "<tr class='$network_class'><th>" . esc_html__( 'Resize Media Images', 'ewww-image-optimizer' ) . "</th><td><label for='ewww_image_optimizer_maxmediawidth'>" . esc_html__( 'Max Width', 'ewww-image-optimizer' ) . "</label> <input type='number' step='1' min='0' class='small-text' id='ewww_image_optimizer_maxmediawidth' name='ewww_image_optimizer_maxmediawidth' value='" . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' ) . ( function_exists( 'imsanity_get_max_width_height' ) ? "' disabled='disabled" : '' ) . "' /> <label for='ewww_image_optimizer_maxmediaheight'>" . esc_html__( 'Max Height', 'ewww-image-optimizer' ) . "</label> <input type='number' step='1' min='0' class='small-text' id='ewww_image_optimizer_maxmediaheight' name='ewww_image_optimizer_maxmediaheight' value='" . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' ) . ( function_exists( 'imsanity_get_max_width_height' ) ? "' disabled='disabled" : '' ) . "' /> " . esc_html__( 'in pixels', 'ewww-image-optimizer' ) . "\n" .
8137
- "<p class='description'>" . esc_html__( 'Resizes images uploaded directly to the Media Library and those uploaded within a post or page.', 'ewww-image-optimizer' ) .
8138
  "</td></tr>\n";
8139
  ewwwio_debug_message( 'max media dimensions: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' ) . ' x ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' ) );
8140
- $output[] = "<tr class='$network_class'><th>" . esc_html__( 'Resize Other Images', 'ewww-image-optimizer' ) . "</th><td><label for='ewww_image_optimizer_maxotherwidth'>" . esc_html__( 'Max Width', 'ewww-image-optimizer' ) . "</label> <input type='number' step='1' min='0' class='small-text' id='ewww_image_optimizer_maxotherwidth' name='ewww_image_optimizer_maxotherwidth' value='" . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherwidth' ) . ( function_exists( 'imsanity_get_max_width_height' ) ? "' disabled='disabled" : '' ) . "' /> <label for='ewww_image_optimizer_maxotherheight'>" . esc_html__( 'Max Height', 'ewww-image-optimizer' ) . "</label> <input type='number' step='1' min='0' class='small-text' id='ewww_image_optimizer_maxotherheight' name='ewww_image_optimizer_maxotherheight' value='" . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherheight' ) . ( function_exists( 'imsanity_get_max_width_height' ) ? "' disabled='disabled" : '' ) . "' /> " . esc_html__( 'in pixels', 'ewww-image-optimizer' ) . "\n" .
8141
- "<p class='description'>" . esc_html__( 'Resizes images uploaded indirectly to the Media Library, like theme images or front-end uploads. Also applied to existing images during Bulk Optimization if necessary.', 'ewww-image-optimizer' ) .
8142
- "</td></tr>\n";
8143
  ewwwio_debug_message( 'max other dimensions: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherwidth' ) . ' x ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherheight' ) );
8144
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_resize_existing'>" . esc_html__( 'Resize Existing Images', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_resize_existing' name='ewww_image_optimizer_resize_existing' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Allow resizing of existing Media Library images.', 'ewww-image-optimizer' ) . "</td></tr>\n";
8145
  ewwwio_debug_message( 'resize existing images: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' ) == true ? 'on' : 'off' ) );
8146
 
8147
- $output[] = '<tr class="network-singlesite"><th>' . esc_html__( 'Disable Resizes', 'ewww-image-optimizer' ) . '</th><td><p>' . esc_html__( 'WordPress, your theme, and other plugins generate various image sizes. You may disable optimization for certain sizes, or completely prevent those sizes from being created.', 'ewww-image-optimizer' ) . "</p>\n";
 
 
 
8148
  $image_sizes = ewww_image_optimizer_get_image_sizes();
8149
  $disabled_sizes = get_option( 'ewww_image_optimizer_disable_resizes' );
8150
  $disabled_sizes_opt = get_option( 'ewww_image_optimizer_disable_resizes_opt' );
8151
- $output[] = '<table><tr class="network-singlesite"><th>' . esc_html__( 'Disable Optimization', 'ewww-image-optimizer' ) . '</th><th>' . esc_html__( 'Disable Creation', 'ewww-image-optimizer' ) . "</th></tr>\n";
8152
  ewwwio_debug_message( 'disabled resizes:' );
8153
  foreach ( $image_sizes as $size => $dimensions ) {
8154
  if ( 'thumbnail' == $size ) {
@@ -8164,8 +7581,8 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8164
  $output[] = "</table>\n";
8165
  $output[] = "</td></tr>\n";
8166
  } else {
8167
- $output[] = '<tr><th>' . esc_html__( 'Disable Resizes', 'ewww-image-optimizer' ) . '</th><td>';
8168
- $output[] = '<p><span style="color: green">' . esc_html__( '*Settings to disable creation and optimization of individual sizes must be configured for each individual site.', 'ewww-image-optimizer' ) . "</span></p></td></tr>\n";
8169
  }
8170
  $output[] = "</table>\n</div>\n";
8171
  $output[] = "<div id='ewww-conversion-settings'>\n";
@@ -8173,50 +7590,68 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8173
  '<b>' . esc_html__( 'NOTE:', 'ewww-image-optimizer' ) . '</b> ' . esc_html__( 'The plugin will attempt to update image locations for any posts that contain the images. You may still need to manually update locations/urls for converted images.', 'ewww-image-optimizer' ) . "\n" .
8174
  "</p>\n";
8175
  $output[] = "<table class='form-table'>\n";
8176
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_disable_convert_links'>" . esc_html__( 'Hide Conversion Links', 'ewww-image-optimizer' ) . "</label</th><td><input type='checkbox' id='ewww_image_optimizer_disable_convert_links' name='ewww_image_optimizer_disable_convert_links' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_convert_links' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Site or Network admins can use this to prevent other users from using the conversion links in the Media Library which bypass the settings below.', 'ewww-image-optimizer' ) . "</td></tr>\n";
8177
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_delete_originals'>" . esc_html__( 'Delete originals', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_delete_originals' name='ewww_image_optimizer_delete_originals' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'This will remove the original image from the server after a successful conversion.', 'ewww-image-optimizer' ) . "</td></tr>\n";
8178
- ewwwio_debug_message( 'delete originals: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' ) == true ? 'on' : 'off' ) );
8179
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_jpg_to_png'>" .
8180
- /* translators: 1: JPG, GIF or PNG 2: JPG or PNG */
8181
- sprintf( esc_html__( 'enable %1$s to %2$s conversion', 'ewww-image-optimizer' ), 'JPG', 'PNG' ) .
8182
- "</label></th><td><span><input type='checkbox' id='ewww_image_optimizer_jpg_to_png' name='ewww_image_optimizer_jpg_to_png' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_to_png' ) == true ? "checked='true'" : '' ) . ' /> <b>' . esc_html__( 'WARNING:', 'ewww-image-optimizer' ) . '</b> ' . esc_html__( 'Removes metadata and increases cpu usage dramatically.', 'ewww-image-optimizer' ) . "</span>\n" .
8183
- "<p class='description'>" . esc_html__( 'PNG is generally much better than JPG for logos and other images with a limited range of colors. Checking this option will slow down JPG processing significantly, and you may want to enable it only temporarily.', 'ewww-image-optimizer' ) . "</p></td></tr>\n";
8184
- ewwwio_debug_message( 'jpg2png: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_to_png' ) == true ? 'on' : 'off' ) );
8185
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_png_to_jpg'>" .
8186
- /* translators: 1: JPG, GIF or PNG 2: JPG or PNG */
8187
- sprintf( esc_html__( 'enable %1$s to %2$s conversion', 'ewww-image-optimizer' ), 'PNG', 'JPG' ) .
8188
- "</label></th><td><span><input type='checkbox' id='ewww_image_optimizer_png_to_jpg' name='ewww_image_optimizer_png_to_jpg' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_to_jpg' ) == true ? "checked='true'" : '' ) . ' /> <b>' . esc_html__( 'WARNING:', 'ewww-image-optimizer' ) . '</b> ' . esc_html__( 'This is not a lossless conversion.', 'ewww-image-optimizer' ) . "</span>\n" .
8189
- "<p class='description'>" . esc_html__( 'JPG is generally much better than PNG for photographic use because it compresses the image and discards data. PNGs with transparency are not converted by default.', 'ewww-image-optimizer' ) . "</p>\n" .
8190
- "<span><label for='ewww_image_optimizer_jpg_background'> " . esc_html__( 'JPG background color:', 'ewww-image-optimizer' ) . "</label> #<input type='text' id='ewww_image_optimizer_jpg_background' name='ewww_image_optimizer_jpg_background' size='6' value='" . ewww_image_optimizer_jpg_background() . "' /> <span style='padding-left: 12px; font-size: 12px; border: solid 1px #555555; background-color: #" . ewww_image_optimizer_jpg_background() . "'>&nbsp;</span> " . esc_html__( 'HEX format (#123def)', 'ewww-image-optimizer' ) . ".</span>\n" .
8191
- "<p class='description'>" . esc_html__( 'Background color is used only if the PNG has transparency. Leave this value blank to skip PNGs with transparency.', 'ewww-image-optimizer' ) . "</p></td></tr>\n";
8192
- ewwwio_debug_message( 'png2jpg: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_to_jpg' ) == true ? 'on' : 'off' ) );
8193
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_gif_to_png'>" .
8194
- /* translators: 1: JPG, GIF or PNG 2: JPG or PNG */
8195
- sprintf( esc_html__( 'enable %1$s to %2$s conversion', 'ewww-image-optimizer' ), 'GIF', 'PNG' ) .
8196
- "</label></th><td><span><input type='checkbox' id='ewww_image_optimizer_gif_to_png' name='ewww_image_optimizer_gif_to_png' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_to_png' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'No warnings here, just do it.', 'ewww-image-optimizer' ) . "</span>\n" .
8197
- "<p class='description'> " . esc_html__( 'PNG is generally better than GIF, but animated images cannot be converted.', 'ewww-image-optimizer' ) . "</p></td></tr>\n";
8198
- ewwwio_debug_message( 'gif2png: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_to_png' ) == true ? 'on' : 'off' ) );
 
 
 
 
 
8199
  $output[] = "</table>\n</div>\n";
8200
  $output[] = "<div id='ewww-webp-settings'>\n";
8201
  $output[] = "<table class='form-table'>\n";
8202
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_webp'>" . esc_html__( 'JPG/PNG to WebP', 'ewww-image-optimizer' ) . "</label></th><td><span><input type='checkbox' id='ewww_image_optimizer_webp' name='ewww_image_optimizer_webp' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) == true ? "checked='true'" : '' ) . ' /> <b>' . esc_html__( 'WARNING:', 'ewww-image-optimizer' ) . '</b> ' . esc_html__( 'JPG to WebP conversion is lossy, but quality loss is minimal. PNG to WebP conversion is lossless.', 'ewww-image-optimizer' ) . "</span>\n" .
8203
- "<p class='description'>" . esc_html__( 'Originals are never deleted, and WebP images should only be served to supported browsers.', 'ewww-image-optimizer' ) . " <a href='#webp-rewrite'>" . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) ? esc_html__( 'You can use the rewrite rules below to serve WebP images with Apache.', 'ewww-image-optimizer' ) : '' ) . "</a></td></tr>\n";
8204
- ewwwio_debug_message( 'webp conversion: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) == true ? 'on' : 'off' ) );
8205
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_webp_force'>" . esc_html__( 'Force WebP', 'ewww-image-optimizer' ) . "</label></th><td><span><input type='checkbox' id='ewww_image_optimizer_webp_force' name='ewww_image_optimizer_webp_force' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'WebP images will be generated and saved for all JPG/PNG images regardless of their size. The Alternative WebP Rewriting will not check if a file exists, only that the domain matches the home url.', 'ewww-image-optimizer' ) . "</span></td></tr>\n";
8206
- ewwwio_debug_message( 'forced webp: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) == true ? 'on' : 'off' ) );
 
 
 
 
 
 
 
 
 
 
 
8207
  if ( ! ewww_image_optimizer_ce_webp_enabled() ) {
8208
- $webp_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' ) ? esc_html( implode( "\n", ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' ) ) ) : '';
8209
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_webp_paths'>" . esc_html__( 'WebP URLs', 'ewww-image-optimizer' ) . '</label></th><td>' . esc_html__( 'If Force WebP is enabled, enter URL patterns that should be permitted for Alternative WebP Rewriting. One pattern per line, may be partial URLs, but must include the domain name.', 'ewww-image-optimizer' ) . '<br>' .
8210
- "<textarea id='ewww_image_optimizer_webp_paths' name='ewww_image_optimizer_webp_paths' rows='3' cols='60'>$webp_paths</textarea></td></tr>\n";
8211
- ewwwio_debug_message( 'webp paths:' );
8212
- ewwwio_debug_message( $webp_paths );
8213
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_webp_for_cdn'>" .
 
 
8214
  esc_html__( 'Alternative WebP Rewriting', 'ewww-image-optimizer' ) .
8215
- "</label></th><td><span><input type='checkbox' id='ewww_image_optimizer_webp_for_cdn' name='ewww_image_optimizer_webp_for_cdn' value='true' " .
8216
  ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) == true ? "checked='true'" : '' ) . ' /> ' .
8217
- esc_html__( 'Uses output buffering and libxml functionality from PHP. Use this if the Apache rewrite rules do not work, or if your images are served from a CDN.', 'ewww-image-optimizer' ) . ' ' .
8218
  /* translators: %s: Cache Enabler (link) */
8219
- sprintf( esc_html__( 'Sites using a CDN may also use the WebP option in the %s plugin.', 'ewww-image-optimizer' ), '<a href="https://wordpress.org/plugins/cache-enabler/">Cache Enabler</a>' ) . '</span></td></tr>';
8220
  }
8221
  ewwwio_debug_message( 'alt webp rewriting: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) == true ? 'on' : 'off' ) );
8222
  $output[] = "</table>\n</div>\n";
@@ -8275,8 +7710,6 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8275
  '<p>' . esc_html__( 'Would you like to help support development of this plugin?', 'ewww-image-optimizer' ) . "</p>\n" .
8276
  "<p><a href='https://translate.wordpress.org/projects/wp-plugins/ewww-image-optimizer/'>" . esc_html__( 'Help translate EWWW I.O.', 'ewww-image-optimizer' ) . "</a></p>\n" .
8277
  "<p><a href='https://wordpress.org/support/view/plugin-reviews/ewww-image-optimizer#postform'>" . esc_html__( 'Write a review.', 'ewww-image-optimizer' ) . "</a></p>\n" .
8278
- /* translators: %s: Paypal (link) */
8279
- '<p>' . sprintf( esc_html__( 'Contribute directly via %s.', 'ewww-image-optimizer' ), "<a href='https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=MKMQKCBFFG3WW'>Paypal</a>" ) . "</p>\n" .
8280
  '<p>' . esc_html__( 'Signup for premium image optimization:', 'ewww-image-optimizer' ) . "<br>\n" .
8281
  "<a target='_blank' href='https://ewww.io/plans/'>" . esc_html__( 'Compress', 'ewww-image-optimizer' ) . "</a><br>\n" .
8282
  "<a target='_blank' href='https://ewww.io/resize/'>" . esc_html__( 'Resize', 'ewww-image-optimizer' ) . "</a></p>\n" .
@@ -8285,40 +7718,22 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8285
  "</div>\n";
8286
  ewwwio_debug_message( 'max_execution_time: ' . ini_get( 'max_execution_time' ) );
8287
  ewww_image_optimizer_stl_check();
8288
- if ( ! ewww_image_optimizer_function_exists( 'sleep' ) ) {
8289
- ewwwio_debug_message( 'sleep disabled' );
8290
- }
8291
- if ( ! ewww_image_optimizer_function_exists( 'print_r' ) ) {
8292
- ewwwio_debug_message( 'print_r disabled' );
8293
- }
8294
  ewwwio_check_memory_available();
8295
  if ( 'debug-silent' === $network ) {
8296
  return;
8297
  }
8298
  echo apply_filters( 'ewww_image_optimizer_settings', $output );
8299
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) && ! ewww_image_optimizer_ce_webp_enabled() ) {
8300
- ewww_image_optimizer_webp_inline_script();
 
8301
  }
8302
 
8303
  $help_instructions = esc_html__( 'Enable the Debugging option and refresh this page to include debugging information with your question.', 'ewww-image-optimizer' ) . ' ' .
8304
  esc_html__( 'This will allow us to assist you more quickly.', 'ewww-image-optimizer' );
8305
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
8306
- ?>
8307
- <script type="text/javascript">
8308
- function selectText(containerid) {
8309
- var debug_node = document.getElementById(containerid);
8310
- if (document.selection) {
8311
- var range = document.body.createTextRange();
8312
- range.moveToElementText(debug_node);
8313
- range.select();
8314
- } else if (window.getSelection) {
8315
- window.getSelection().selectAllChildren(debug_node);
8316
- }
8317
- }
8318
- </script>
8319
- <?php
8320
  global $ewww_debug;
8321
- echo '<p style="clear:both"><b>' . esc_html__( 'Debugging Information', 'ewww-image-optimizer' ) . ':</b> <button onclick="selectText(' . "'ewww-debug-info'" . ')">' . esc_html__( 'Select All', 'ewww-image-optimizer' ) . '</button>';
8322
  if ( is_file( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'debug.log' ) ) {
8323
  $debug_log_url = plugins_url( '/debug.log', __FILE__ );
8324
  echo "&emsp;<a href='$debug_log_url'>" . esc_html( 'View Debug Log', 'ewww-image-optimizer' ) . "</a> - <a href='admin.php?action=ewww_image_optimizer_delete_debug_log'>" . esc_html( 'Remove Debug Log', 'ewww-image-optimizer' ) . '</a>';
@@ -8329,7 +7744,6 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
8329
  esc_html__( 'This will allow us to assist you more quickly.', 'ewww-image-optimizer' );
8330
  }
8331
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_help' ) ) {
8332
- /* $help_instructions = esc_html__( 'Please turn on the Debugging option. Then copy and paste the Debug Information from the bottom of the settings page. This will allow us to assist you more quickly.', 'ewww-image-optimizer' ); */
8333
  $current_user = wp_get_current_user();
8334
  $help_email = $current_user->user_email;
8335
  $hs_config = array(
@@ -8428,6 +7842,27 @@ function ewww_image_optimizer_filter_network_singlesite_settings_page( $input )
8428
  return $output;
8429
  }
8430
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8431
  /**
8432
  * Removes the API key currently installed.
8433
  *
@@ -8878,4 +8313,25 @@ function ewwwio_memory_output() {
8878
  $ewww_memory = '';
8879
  }
8880
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8881
  ?>
10
  * @package EWWW_Image_Optimizer
11
  */
12
 
 
13
  // TODO: attempt lazy load support with a3 plugin and one from automattic for alt webp. or are we back here: https://developers.google.com/web/fundamentals/performance/lazy-loading-guidance/images-and-video/
14
+ // TODO: implement a way to (re)compress at a specific compression level.
 
 
15
  // TODO: might be able to use the Custom Bulk Actions in 4.7 to support the bulk optimize drop-down menu.
16
  // TODO: need to make the scheduler so it can resume without having to re-run the queue population, and then we can probably also flush the queue when scheduled opt starts, but later it would be nice to implement the bulk_loop as the aux_loop so that it could handle media properly.
 
17
  // TODO: Add a custom async function for parallel mode to store image as pending and use the row ID instead of relative path.
18
  // TODO: write some tests for update_table and check_table, find_already_opt, and remove_dups.
19
  // TODO: write some conversion tests.
 
20
  // TODO: check this patch, to see if the use of 'full' causes any issues: https://core.trac.wordpress.org/ticket/37840 .
21
  // TODO: integrate AGR, since it's "abandoned", but possibly using gifsicle for better GIFs.
22
  // TODO: use this: https://codex.wordpress.org/AJAX_in_Plugins#The_post-load_JavaScript_Event .
23
  // TODO: on images without srscet, add 2x and 3x versions anyway.
 
24
  // TODO: match Adaptive Images functionality with ExactDN.
25
  // TODO: handle relative urls with ExactDN.
26
+ // TODO: see if we can parse all use tags and use the bypass mechanism to avoid ExactDN + SVG issues.
27
+ // TODO: can some of the bulk "fallbacks" be implemented for async processing?
28
  if ( ! defined( 'ABSPATH' ) ) {
29
  exit;
30
  }
31
 
32
+ define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '430.0' );
33
 
34
  // Initialize a couple globals.
35
  $ewww_debug = '';
77
  add_filter( 'emr_unfiltered_get_attached_file', 'ewww_image_optimizer_image_sizes' );
78
  // Checks to see if thumb regen or other similar operation is running via REST API.
79
  add_action( 'rest_api_init', 'ewww_image_optimizer_restapi_compat_check' );
80
+ // Detect WP/LR Sync when it starts.
81
+ add_action( 'wplr_presync_media', 'ewww_image_optimizer_image_sizes' );
82
  // Enables direct integration to the editor's save function.
83
  add_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
84
  }
173
  add_action( 'wp_ajax_ewww_manual_cloud_restore', 'ewww_image_optimizer_manual' );
174
  // AJAX action hook for manually restoring a single image backup from the API.
175
  add_action( 'wp_ajax_ewww_manual_cloud_restore_single', 'ewww_image_optimizer_cloud_restore_single_image_handler' );
176
+ // AJAX action hook to disable the media library notice.
177
+ add_action( 'wp_ajax_ewww_dismiss_media_notice', 'ewww_image_optimizer_dismiss_media_notice' );
178
  // Adds script to highlight mis-sized images on the front-end (for logged in admins only).
179
  add_action( 'wp_enqueue_scripts', 'ewww_image_optimizer_resize_detection_script' );
180
  // Adds a button on the admin bar to allow highlighting mis-sized images on-demand.
206
  }
207
  // If Alt WebP Rewriting is enabled.
208
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) ) {
209
+ /**
210
+ * Page Parsing class for working with HTML content.
211
+ */
212
+ require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-ewwwio-page-parser.php' );
213
+ /**
214
+ * Alt WebP class for parsing image urls and rewriting them for WebP support.
215
+ */
216
+ require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-ewwwio-alt-webp.php' );
 
 
 
 
 
 
 
217
  }
218
 
219
  if ( defined( 'WP_CLI' ) && WP_CLI ) {
220
  require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-ewwwio-cli.php' );
221
  }
222
 
 
 
 
 
 
 
 
223
  /**
224
  * Skips optimization when a file is within EWWW IO's own folder.
225
  *
294
  return false;
295
  }
296
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
297
  /**
298
  * Set default permissions for manual operations (single image optimize, convert, restore).
299
  *
391
  * Checks if a function is disabled or does not exist.
392
  *
393
  * @param string $function The name of a function to test.
394
+ * @param bool $debug Whether to output debugging.
395
  * @return bool True if the function is available, False if not.
396
  */
397
+ function ewww_image_optimizer_function_exists( $function, $debug = false ) {
 
398
  if ( function_exists( 'ini_get' ) ) {
399
  $disabled = @ini_get( 'disable_functions' );
400
+ if ( $debug ) {
401
+ ewwwio_debug_message( "disable_functions: $disabled" );
402
+ }
403
  }
404
  if ( extension_loaded( 'suhosin' ) && function_exists( 'ini_get' ) ) {
405
  $suhosin_disabled = @ini_get( 'suhosin.executor.func.blacklist' );
406
+ if ( $debug ) {
407
+ ewwwio_debug_message( "suhosin_blacklist: $suhosin_disabled" );
408
+ }
409
  if ( ! empty( $suhosin_disabled ) ) {
410
  $suhosin_disabled = explode( ',', $suhosin_disabled );
411
  $suhosin_disabled = array_map( 'trim', $suhosin_disabled );
621
  update_site_option( 'ewww_image_optimizer_maxmediawidth', (int) $_POST['ewww_image_optimizer_maxmediawidth'] );
622
  $_POST['ewww_image_optimizer_maxmediaheight'] = empty( $_POST['ewww_image_optimizer_maxmediaheight'] ) ? 0 : $_POST['ewww_image_optimizer_maxmediaheight'];
623
  update_site_option( 'ewww_image_optimizer_maxmediaheight', (int) $_POST['ewww_image_optimizer_maxmediaheight'] );
 
 
 
 
624
  $_POST['ewww_image_optimizer_resize_detection'] = ( empty( $_POST['ewww_image_optimizer_resize_detection'] ) ? false : true );
625
  update_site_option( 'ewww_image_optimizer_resize_detection', $_POST['ewww_image_optimizer_resize_detection'] );
626
  $_POST['ewww_image_optimizer_resize_existing'] = ( empty( $_POST['ewww_image_optimizer_resize_existing'] ) ? false : true );
691
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_resize_detection', 'boolval' );
692
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxmediawidth', 'intval' );
693
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxmediaheight', 'intval' );
 
 
694
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_resize_existing', 'boolval' );
695
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_disable_resizes', 'ewww_image_optimizer_disable_resizes_sanitize' );
696
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_disable_resizes_opt', 'ewww_image_optimizer_disable_resizes_sanitize' );
723
  // Alert user if multiple re-optimizations detected.
724
  add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_reoptimization' );
725
  add_action( 'admin_notices', 'ewww_image_optimizer_notice_reoptimization' );
726
+ add_action( 'admin_notices', 'ewww_image_optimizer_notice_media_listmode' );
727
  if ( ! empty( $_GET['page'] ) ) {
728
  if ( 'regenerate-thumbnails' == $_GET['page']
729
  || 'force-regenerate-thumbnails' == $_GET['page']
734
  add_action( 'admin_notices', 'ewww_image_optimizer_thumbnail_regen_notice' );
735
  }
736
  }
737
+ if ( ! empty( $_GET['ewww_pngout'] ) ) {
738
+ add_action( 'admin_notices', 'ewww_image_optimizer_pngout_installed' );
739
+ add_action( 'network_admin_notices', 'ewww_image_optimizer_pngout_installed' );
740
+ }
741
+ ewww_image_optimizer_privacy_policy_content();
742
  ewww_image_optimizer_ajax_compat_check();
743
  // Remove the false when the next bump is coming.
744
+ if ( defined( 'PHP_VERSION_ID' ) && PHP_VERSION_ID < 50500 ) {
745
  add_action( 'network_admin_notices', 'ewww_image_optimizer_php54_warning' );
746
  add_action( 'admin_notices', 'ewww_image_optimizer_php54_warning' );
747
  }
830
  }
831
  }
832
 
833
+ /**
834
+ * Adds suggested privacy policy content for site admins.
835
+ *
836
+ * Note that this is just a suggestion, it should be customized for your site.
837
+ */
838
+ function ewww_image_optimizer_privacy_policy_content() {
839
+ $content = '<p class="privacy-policy-tutorial">';
840
+ if ( ! defined( 'EWWW_IO_CLOUD_PLUGIN' ) || ! EWWW_IO_CLOUD_PLUGIN ) {
841
+ $content .= wp_kses_post( __( 'By default, the EWWW Image Optimizer does not store any personal data nor share it with anyone.', 'ewww-image-optimizer' ) ) . '</p><p>';
842
+ }
843
+ $content .= wp_kses_post( __( 'If you accept user-submitted images and use the API or ExactDN, those images may be transmitted to third-party servers in foregin countries. If Backup Originals is enabled, images are stored for 30 days. Otherwise, no images are stored on the API for longer than 30 minutes.', 'ewww-image-optimizer' ) ) . '</p>';
844
+ $content .= '<p><strong>' . wp_kses_post( __( 'Suggested API Text:' ) ) . '</strong> <i>' . wp_kses_post( __( 'User-submitted images may be transmitted to image compression servers in the United States and stored there for up to 30 days.' ) ) . '</i></p>';
845
+ $content .= '<p><strong>' . wp_kses_post( __( 'Suggested ExactDN Text:' ) ) . '</strong> <i>' . wp_kses_post( __( 'User-submitted images that are displayed on this site will be transmitted and stored on a global network of third-party servers (a CDN).' ) ) . '</i></p>';
846
+ wp_add_privacy_policy_content( 'EWWW Image Optimizer', $content );
847
+ }
848
+
849
  /**
850
  * Optimize a single image from an attachment, based on the size and ID.
851
  *
1017
  if ( empty( $ewwwio_admin_color ) ) {
1018
  $ewwwio_admin_color = '#0073aa';
1019
  }
 
1020
  }
1021
  /**
1022
  * Determines the background color to use based on the selected admin theme.
1023
  */
1024
  function ewww_image_optimizer_admin_background() {
 
1025
  global $ewwwio_admin_color;
1026
  if ( ! empty( $ewwwio_admin_color ) && preg_match( '/^\#([0-9a-fA-F]){3,6}$/', $ewwwio_admin_color ) ) {
 
1027
  return $ewwwio_admin_color;
1028
  }
1029
  if ( function_exists( 'wp_add_inline_style' ) ) {
1038
  preg_match( '/^\#([0-9a-fA-F]){3,6}$/', $_wp_admin_css_colors[ $user_info->admin_color ]->colors[2] )
1039
  ) {
1040
  $ewwwio_admin_color = $_wp_admin_css_colors[ $user_info->admin_color ]->colors[2];
 
1041
  return $ewwwio_admin_color;
1042
  }
1043
  switch ( $user_info->admin_color ) {
1059
  return '#0073aa';
1060
  }
1061
  }
 
1062
  }
1063
 
1064
  /**
1181
  // Include the upgrade library to install/upgrade a table.
1182
  require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
1183
  $updates = dbDelta( $sql );
1184
+ ewwwio_debug_message( 'db upgrade results: ' . implode( '<br>', $updates ) );
 
 
1185
 
1186
  // Make sure some of our options are not autoloaded (since they can be huge).
1187
  $bulk_attachments = get_option( 'ewww_image_optimizer_bulk_attachments', '' );
1276
  delete_option( 'ewww_image_optimizer_maxheight' );
1277
  }
1278
 
1279
+ /**
1280
+ * Display a success or failure message after PNGOUT installation.
1281
+ */
1282
+ function ewww_image_optimizer_pngout_installed() {
1283
+ if ( 'success' == $_REQUEST['ewww_pngout'] ) {
1284
+ echo "<div id='ewww-image-optimizer-pngout-success' class='updated fade'>\n" .
1285
+ '<p>' . esc_html__( 'Pngout was successfully installed.', 'ewww-image-optimizer' ) . "</p>\n" .
1286
+ "</div>\n";
1287
+ }
1288
+ if ( 'failed' == $_REQUEST['ewww_pngout'] ) {
1289
+ echo "<div id='ewww-image-optimizer-pngout-failure' class='error'>\n" .
1290
+ '<p>' . sprintf(
1291
+ /* translators: 1: An error message 2: The folder where pngout should be installed */
1292
+ esc_html__( 'Pngout was not installed: %1$s. Make sure this folder is writable: %2$s', 'ewww-image-optimizer' ),
1293
+ sanitize_text_field( $_REQUEST['ewww_error'] ), EWWW_IMAGE_OPTIMIZER_TOOL_PATH
1294
+ ) . "</p>\n" .
1295
+ "</div>\n";
1296
+ }
1297
+ }
1298
+ /**
1299
+ * Display a notice that PHP version 5.4 support is going away.
1300
+ */
1301
+ function ewww_image_optimizer_php54_warning() {
1302
+ echo '<div id="ewww-image-optimizer-notice-php54" class="notice notice-info is-dismissible"><p><a href="https://docs.ewww.io/article/55-upgrading-php" target="_blank" data-beacon-article="5ab2baa6042863478ea7c2ae">' . esc_html__( 'The next major release of EWWW Image Optimizer will require PHP 5.5 or greater. Newer versions of PHP, like 5.6, 7.0 and 7.1, are significantly faster and much more secure. If you are unsure how to upgrade to a supported version, ask your webhost for instructions.', 'ewww-image-optimizer' ) . '</a></p></div>';
1303
+ }
1304
+
1305
  /**
1306
  * Lets the user know their network settings have been saved.
1307
  */
1308
  function ewww_image_optimizer_network_settings_saved() {
1309
+ echo "<div id='ewww-image-optimizer-settings-saved' class='notice notice-success updated fade'><p><strong>" . esc_html__( 'Settings saved', 'ewww-image-optimizer' ) . '.</strong></p></div>';
 
1310
  }
1311
 
1312
  /**
1317
  echo '&nbsp;<a href="https://docs.ewww.io/article/49-regenerate-thumbnails" target="_blank" data-beacon-article="5a0f84ed2c7d3a272c0dc801">' . esc_html__( 'Learn more.', 'ewww-image-optimizer' ) . '</a></p></div>';
1318
  }
1319
 
1320
+ /**
1321
+ * Let the user know they can view more options and stats in the Media Library's list mode.
1322
+ */
1323
+ function ewww_image_optimizer_notice_media_listmode() {
1324
+ if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_dismiss_media_notice' ) ) {
1325
+ $current_screen = get_current_screen();
1326
+ if ( 'upload' === $current_screen->id ) {
1327
+ echo "<div id='ewww-image-optimizer-media-listmode' class='notice notice-info is-dismissible'><p>" . esc_html__( 'Change the Media Library to List mode for additional image optimization information and actions.', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/62-power-user-options-in-list-mode', '5b61fdd32c7d3a03f89d41c4' ) . '</p></div>';
1328
+ }
1329
+ }
1330
+ }
1331
  /**
1332
  * Alert the user when 5 images have been re-optimized more than 10 times.
1333
  *
1396
  if ( ! in_array( 'EWWWIO_Gmagick_Editor', $editors ) && class_exists( 'WP_Image_Editor_Gmagick' ) ) {
1397
  array_unshift( $editors, 'EWWWIO_Gmagick_Editor' );
1398
  }
1399
+ if ( is_array( $editors ) ) {
1400
+ ewwwio_debug_message( 'loading image editors: ' . implode( '<br>', $editors ) );
1401
  }
1402
  ewwwio_memory( __FUNCTION__ );
1403
  return $editors;
1421
  function ewww_image_optimizer_image_sizes( $sizes ) {
1422
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1423
  remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
1424
+ // This happens right after thumbs and meta are generated.
1425
  add_filter( 'wp_generate_attachment_metadata', 'ewww_image_optimizer_restore_editor_hooks', 1 );
1426
  add_filter( 'mpp_generate_metadata', 'ewww_image_optimizer_restore_editor_hooks', 1 );
1427
  return $sizes;
1639
  */
1640
  function ewww_image_optimizer_handle_upload( $params ) {
1641
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1642
+ if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
1643
+ ewwwio_debug_message( print_r( $params, true ) );
1644
+ }
1645
  global $ewww_new_image;
1646
  $ewww_new_image = true;
1647
  if ( empty( $params['file'] ) ) {
1654
  $file_path = $params['file'];
1655
  }
1656
  ewww_image_optimizer_autorotate( $file_path );
1657
+ $new_image = ewww_image_optimizer_autoconvert( $file_path );
1658
+ if ( $new_image ) {
1659
+ if ( ! empty( $params['tmp_name'] ) && $params['tmp_name'] == $file_path ) {
1660
+ $params['tmp_name'] = $new_image;
1661
+ }
1662
+ if ( ! empty( $params['file'] ) && $params['file'] == $file_path ) {
1663
+ $params['file'] = $new_image;
1664
+ }
1665
+ if ( ! empty( $params['url'] ) && basename( $file_path ) == basename( $params['url'] ) ) {
1666
+ $params['url'] = trailingslashit( dirname( $params['url'] ) ) . basename( $new_image );
1667
+ }
1668
+ $params['type'] = ewww_image_optimizer_mimetype( $new_image, 'i' );
1669
+ if ( is_file( $file_path ) ) {
1670
+ unlink( $file_path );
1671
+ }
1672
+ $file_path = $new_image;
1673
+ }
1674
  // NOTE: if you use the ewww_image_optimizer_defer_resizing filter to defer the resize operation, only the "other" dimensions will apply
1675
+ // Resize here unless the user chose to defer resizing or imsanity is enabled with a max size.
1676
  if ( ! apply_filters( 'ewww_image_optimizer_defer_resizing', false ) && ! function_exists( 'imsanity_get_max_width_height' ) ) {
1677
  if ( empty( $params['type'] ) ) {
1678
  $mime_type = ewww_image_optimizer_mimetype( $file_path, 'i' );
2076
  return $url;
2077
  }
2078
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2079
  /**
2080
  * Enqueue custom jquery stylesheet and scripts for the media library AJAX functions.
2081
  *
3150
  }
3151
  // Calculate how much time has elapsed since we started.
3152
  $elapsed = microtime( true ) - $started;
3153
+ ewwwio_debug_message( "cloud verify took $elapsed seconds" );
3154
  $ewww_status = get_transient( 'ewww_image_optimizer_cloud_status' );
3155
  if ( ( ! empty( $ewww_status ) && preg_match( '/exceeded/', $ewww_status ) ) || ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_exceeded' ) > time() ) {
3156
  ewwwio_debug_message( 'license exceeded, image not processed' );
3369
  }
3370
  // Calculate how much time has elapsed since we started.
3371
  $elapsed = microtime( true ) - $started;
3372
+ ewwwio_debug_message( "cloud verify took $elapsed seconds" );
3373
  $ewww_status = get_transient( 'ewww_image_optimizer_cloud_status' );
3374
  if ( ( ! empty( $ewww_status ) && preg_match( '/exceeded/', $ewww_status ) ) || ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_exceeded' ) > time() ) {
3375
  ewwwio_debug_message( 'license exceeded, image not rotated' );
3561
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
3562
  ewwwio_debug_message( "checking for $file with size: $orig_size" );
3563
  global $s3_uploads_image;
3564
+ global $ewww_image;
3565
  if ( class_exists( 'S3_Uploads' ) && ! empty( $s3_uploads_image ) && $s3_uploads_image != $file ) {
3566
  $file = $s3_uploads_image;
3567
  ewwwio_debug_message( "overriding check with: $file" );
3568
  }
3569
+ $image = array();
3570
+ if ( ! is_object( $ewww_image ) || ! $ewww_image instanceof EWWW_Image || $ewww_image->file != $file ) {
3571
+ $ewww_image = new EWWW_Image( 0, '', $file );
3572
+ }
3573
+ if ( ! empty( $ewww_image->record ) ) {
3574
+ $image = $ewww_image->record;
3575
+ } else {
3576
+ $image = false;
3577
+ }
3578
  if ( is_array( $image ) && $image['image_size'] == $orig_size ) {
3579
  $prev_string = ' - ' . __( 'Previously Optimized', 'ewww-image-optimizer' );
3580
  if ( preg_match( '/' . __( 'License exceeded', 'ewww-image-optimizer' ) . '/', $image['results'] ) ) {
3655
  $updates = array(
3656
  'path' => ewww_image_optimizer_relative_path_remove( $attachment ),
3657
  'converted' => $converted,
3658
+ 'level' => 0,
3659
  'image_size' => $opt_size,
3660
  'results' => $results_msg,
3661
  'updates' => 1,
3676
  if ( is_object( $ewww_image ) && $ewww_image instanceof EWWW_Image && $ewww_image->resize ) {
3677
  $updates['resize'] = $ewww_image->resize;
3678
  }
3679
+ if ( is_object( $ewww_image ) && $ewww_image instanceof EWWW_Image && $ewww_image->level ) {
3680
+ $updates['level'] = $ewww_image->level;
3681
+ }
3682
  $updates['orig_size'] = $orig_size;
3683
  $updates['updated'] = date( 'Y-m-d H:i:s' );
3684
  $ewwwdb->insert( $ewwwdb->ewwwio_images, $updates );
3703
  if ( empty( $already_optimized['resize'] ) && is_object( $ewww_image ) && $ewww_image instanceof EWWW_Image && $ewww_image->resize ) {
3704
  $updates['resize'] = $ewww_image->resize;
3705
  }
3706
+ if ( is_object( $ewww_image ) && $ewww_image instanceof EWWW_Image && $ewww_image->level ) {
3707
+ $updates['level'] = $ewww_image->level;
3708
+ }
3709
  if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
3710
  ewwwio_debug_message( print_r( $updates, true ) );
3711
  }
4210
  */
4211
  function ewww_image_optimizer_autorotate( $file ) {
4212
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
4213
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_autorotate' ) ) {
4214
  return;
4215
  }
4216
  if ( function_exists( 'wp_raise_memory_limit' ) ) {
4262
  ewww_image_optimizer_cloud_autorotate( $file, $type );
4263
  }
4264
 
4265
+ /**
4266
+ * If a PNG image is over the threshold, see if we can make it smaller as a JPG.
4267
+ *
4268
+ * @param string $file The file to check for conversion.
4269
+ */
4270
+ function ewww_image_optimizer_autoconvert( $file ) {
4271
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
4272
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_autoconvert' ) ) {
4273
+ return;
4274
+ }
4275
+ if ( function_exists( 'wp_raise_memory_limit' ) ) {
4276
+ wp_raise_memory_limit( 'image' );
4277
+ }
4278
+ $type = ewww_image_optimizer_mimetype( $file, 'i' );
4279
+ if ( 'image/png' != $type ) {
4280
+ ewwwio_debug_message( 'not a PNG, no conversion needed' );
4281
+ return;
4282
+ }
4283
+ $orig_size = ewww_image_optimizer_filesize( $file );
4284
+ if ( $orig_size < 350000 ) {
4285
+ return;
4286
+ }
4287
+ $ewww_image = new EWWW_Image( 0, '', $file );
4288
+ return $ewww_image->convert( $file, false );
4289
+ }
4290
+
4291
  /**
4292
  * Skips resizing for any image with 'noresize' in the filename.
4293
  *
4321
  wp_raise_memory_limit( 'image' );
4322
  }
4323
  if ( ! empty( $_REQUEST['post_id'] ) || ( ! empty( $_REQUEST['action'] ) && 'upload-attachment' === $_REQUEST['action'] ) || ( ! empty( $_SERVER['HTTP_REFERER'] ) && strpos( $_SERVER['HTTP_REFERER'], 'media-new.php' ) ) ) {
4324
+ ewwwio_debug_message( 'resizing image from media library or attached to post' );
4325
+ $maxwidth = ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' );
4326
+ $maxheight = ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' );
4327
+ } elseif ( ! empty( $_SERVER['HTTP_REFERER'] ) && strpos( $_SERVER['HTTP_REFERER'], '/post.php' ) ) {
4328
+ ewwwio_debug_message( 'resizing image from the post/page editor' );
4329
  $maxwidth = ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' );
4330
  $maxheight = ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' );
 
4331
  } else {
4332
+ ewwwio_debug_message( 'resizing images from somewhere else' );
4333
  $maxwidth = ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherwidth' );
4334
  $maxheight = ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherheight' );
4335
+ if ( ! $maxwidth && ! $maxheight ) {
4336
+ ewwwio_debug_message( 'other dimensions not set, overriding with media dimensions' );
4337
+ $maxwidth = ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' );
4338
+ $maxheight = ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' );
4339
+ }
4340
+ }
4341
+ if ( ! empty( $_SERVER['HTTP_REFERER'] ) ) {
4342
+ ewwwio_debug_message( 'uploaded from: ' . $_SERVER['HTTP_REFERER'] );
4343
  }
4344
 
4345
  /**
4377
  return false;
4378
  }
4379
  $crop = false;
4380
+ if ( $oldwidth >= $maxwidth && $maxwidth && $oldheight >= $maxheight && $maxheight && apply_filters( 'ewww_image_optimizer_crop_image', false ) ) {
4381
  $crop = true;
4382
  $newwidth = $maxwidth;
4383
  $newheight = $maxheight;
4667
  $delete_ids[] = (int) $record['id'];
4668
  }
4669
  if ( ! empty( $delete_ids ) && is_array( $delete_ids ) ) {
4670
+ $query_ids = implode( ',', $delete_ids );
4671
+ $ewwwdb->query( "DELETE FROM $ewwwdb->ewwwio_images WHERE id IN ($query_ids)" ); // WPCS: unprepared SQL ok.
4672
  }
4673
  return $keeper;
4674
  }
5654
  // Set the increment to 1 (but allow the user to override it).
5655
  $filenum = apply_filters( 'ewww_image_optimizer_converted_filename_suffix', 1 );
5656
  // But it must be only letters, numbers, or underscores.
5657
+ $filenum = ( preg_match( '/^[\w\d]+$/', $filenum ) ? $filenum : 1 );
5658
  $suffix = ( ! empty( $filenum ) ? '-' . $filenum : '' );
5659
  // While a file exists with the current increment.
5660
  while ( file_exists( $filename . $suffix . $fileext ) ) {
5833
  $meta = wp_get_attachment_metadata( $id );
5834
  }
5835
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) && ! $return_output && ewww_image_optimizer_function_exists( 'print_r' ) ) {
5836
+ $print_meta = print_r( $meta, true );
5837
+ $print_meta = preg_replace( array( '/ /', '/\n+/' ), array( '&nbsp;', '<br />' ), $print_meta );
5838
+ $debug_button = esc_html__( 'Show Metadata', 'ewww-image-optimizer' );
5839
+ $output .= "<button type='button' class='ewww-show-debug-meta button button-secondary' data-id='$id'>$debug_button</button><div id='ewww-debug-meta-$id' style='background-color:#ffff99;font-size: 10px;padding: 10px;margin:3px -10px 10px;line-height: 1.1em;display: none;'>$print_meta</div>";
5840
  }
5841
  $output .= "<div id='ewww-media-status-$id'>";
5842
  $ewww_cdn = false;
6432
  return $meta;
6433
  }
6434
 
6435
+ /**
6436
+ * Disables the Media Library notice about List Mode.
6437
+ */
6438
+ function ewww_image_optimizer_dismiss_media_notice() {
6439
+ ewwwio_ob_clean();
6440
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
6441
+ // Verify that the user is properly authorized.
6442
+ if ( ! current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', 'manage_options' ) ) ) {
6443
+ wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
6444
+ }
6445
+ update_option( 'ewww_image_optimizer_dismiss_media_notice', true, false );
6446
+ update_site_option( 'ewww_image_optimizer_dismiss_media_notice', true );
6447
+ wp_die();
6448
+ }
6449
+
6450
  /**
6451
  * Load JS in media library footer for bulk actions.
6452
  */
6493
  $ids = implode( ',', array_map( 'intval', $_REQUEST['media'] ) );
6494
  wp_redirect( add_query_arg(
6495
  array(
6496
+ 'page' => 'ewww-image-optimizer-bulk',
6497
+ 'ids' => $ids,
 
 
6498
  ),
6499
  admin_url( 'upload.php' )
6500
  ) );
6582
  if ( strpos( $hook, 'settings_page_ewww-image-optimizer' ) !== 0 ) {
6583
  return;
6584
  }
6585
+ wp_enqueue_script( 'jquery-ui-tooltip' );
6586
  wp_enqueue_script( 'ewwwbulkscript', plugins_url( '/includes/eio.js', __FILE__ ), array( 'jquery' ), EWWW_IMAGE_OPTIMIZER_VERSION );
6587
+ wp_enqueue_style( 'jquery-ui-tooltip-custom', plugins_url( '/includes/jquery-ui-1.10.1.custom.css', __FILE__ ), array(), EWWW_IMAGE_OPTIMIZER_VERSION );
6588
  wp_enqueue_script( 'postbox' );
6589
  wp_enqueue_script( 'dashboard' );
6590
  wp_localize_script( 'ewwwbulkscript', 'ewww_vars', array(
6608
  // Need to include the plugin library for the is_plugin_active function.
6609
  require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
6610
  }
6611
+ $total_orig = 0;
6612
+ $total_opt = 0;
6613
+ $total_savings = 0;
6614
  if ( is_multisite() && is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) ) {
6615
  ewwwio_debug_message( 'querying savings for multi-site' );
6616
 
6632
  'limit' => 1000,
6633
  ) );
6634
  }
 
6635
  if ( ewww_image_optimizer_iterable( $blogs ) ) {
6636
  foreach ( $blogs as $blog ) {
6637
  if ( is_array( $blog ) ) {
6647
  ewww_image_optimizer_install_table();
6648
  }
6649
  if ( $wpdb->ewwwio_images ) {
6650
+ $orig_size = $wpdb->get_var( "SELECT SUM(orig_size) FROM $wpdb->ewwwio_images WHERE image_size > 0" );
6651
+ $opt_size = $wpdb->get_var( "SELECT SUM(image_size) FROM $wpdb->ewwwio_images WHERE image_size > 0" );
6652
+ $total_orig += $orig_size;
6653
+ $total_opt += $opt_size;
6654
+ $savings = $orig_size - $opt_size;
6655
+ ewwwio_debug_message( "savings found for site $blog_id: $savings" );
6656
  $total_savings += $savings;
6657
  }
6658
  restore_current_blog();
6660
  }
6661
  } else {
6662
  ewwwio_debug_message( 'querying savings for single site' );
6663
+ $table_name = $wpdb->ewwwio_images;
 
6664
  ewwwio_debug_message( "table name is $table_name" );
6665
  if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name ) ) != $table_name ) {
6666
  ewww_image_optimizer_install_table();
6667
  }
6668
+ $orig_size = $wpdb->get_var( "SELECT SUM(orig_size) FROM $wpdb->ewwwio_images WHERE image_size > 0" );
6669
+ $opt_size = $wpdb->get_var( "SELECT SUM(image_size) FROM $wpdb->ewwwio_images WHERE image_size > 0" );
6670
+ $total_orig += $orig_size;
6671
+ $total_opt += $opt_size;
6672
+
6673
+ $total_savings = $orig_size - $opt_size;
6674
  } // End if().
6675
+ ewwwio_debug_message( "total original size: $total_orig" );
6676
+ ewwwio_debug_message( "total current(opt) size: $total_opt" );
6677
+ ewwwio_debug_message( "savings found: $total_savings" );
6678
+ return array( $total_opt, $total_orig );
6679
  }
6680
 
6681
  /**
6710
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-settings' ) ) {
6711
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
6712
  }
6713
+ if ( ! current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', 'manage_options' ) ) ) {
6714
+ wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
6715
+ }
6716
  $ewww_rules = ewww_image_optimizer_webp_rewrite_verify();
6717
  if ( $ewww_rules ) {
6718
  if ( insert_with_markers( ewww_image_optimizer_htaccess_path(), 'EWWWIO', $ewww_rules ) && ! ewww_image_optimizer_webp_rewrite_verify() ) {
6734
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-settings' ) ) {
6735
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
6736
  }
6737
+ if ( ! current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', 'manage_options' ) ) ) {
6738
+ wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
6739
+ }
6740
  if ( insert_with_markers( ewww_image_optimizer_htaccess_path(), 'EWWWIO', '' ) ) {
6741
  esc_html_e( 'Removal successful', 'ewww-image-optimizer' );
6742
  } else {
6776
  '</IfModule>',
6777
  'AddType image/webp .webp',
6778
  );
6779
+ if ( is_array( $current_rules ) ) {
6780
+ ewwwio_debug_message( 'current rules: ' . implode( '<br>', $current_rules ) );
6781
  }
6782
  if ( empty( $current_rules ) ||
6783
  ! ewww_image_optimizer_array_search( '{HTTP_ACCEPT} image/webp', $current_rules ) ||
6872
  global $_wp_additional_image_sizes;
6873
  $sizes = array();
6874
  $image_sizes = get_intermediate_image_sizes();
6875
+ if ( is_array( $image_sizes ) ) {
6876
+ ewwwio_debug_message( 'sizes: ' . implode( '<br>', $image_sizes ) );
6877
  }
6878
  if ( false ) { // set to true to enable more debugging.
6879
  ewwwio_debug_message( print_r( $_wp_additional_image_sizes, true ) );
6947
  ewwwio_debug_message( 'home url: ' . get_home_url() );
6948
  ewwwio_debug_message( 'site url: ' . get_site_url() );
6949
  ewwwio_debug_message( 'content_url: ' . content_url() );
6950
+ if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_NOEXEC' ) ) {
6951
+ ewww_image_optimizer_tool_init();
6952
+ ewww_image_optimizer_notice_utils( 'quiet' );
6953
+ }
6954
  $network_class = $network;
6955
  if ( empty( $network ) ) {
6956
  $network_class = 'singlesite';
6984
  $output[] = "<h1>EWWW Image Optimizer</h1>\n";
6985
  $output[] = "<div id='ewww-container-left' style='float: left; margin-right: 225px;'>\n";
6986
  $output[] = "<p><a href='https://ewww.io/'>" . esc_html__( 'Plugin Home Page', 'ewww-image-optimizer' ) . '</a> | ' .
6987
+ "<a class='ewww-docs-root' href='https://docs.ewww.io/'>" . esc_html__( 'Documentation', 'ewww-image-optimizer' ) . '</a> | ' .
6988
+ "<a class='ewww-docs-root' href='https://ewww.io/contact-us/'>" . esc_html__( 'Plugin Support', 'ewww-image-optimizer' ) . '</a> | ' .
6989
+ "<a href='https://ewww.io/status/'>" . esc_html__( 'Server Status', 'ewww-image-optimizer' ) . '</a> | ' .
6990
  "<a href='https://ewww.io/downloads/s3-image-optimizer/'>" . esc_html__( 'S3 Image Optimizer', 'ewww-image-optimizer' ) . "</a></p>\n";
6991
  if ( 'network-multisite' == $network ) {
6992
  $bulk_link = esc_html__( 'Media Library', 'ewww-image-optimizer' ) . ' -> ' . esc_html__( 'Bulk Optimize', 'ewww-image-optimizer' );
6999
  /* translators: %s: Bulk Optimize (link) */
7000
  esc_html__( 'New images uploaded to the Media Library will be optimized automatically. If you have existing images you would like to optimize, you can use the %s tool.', 'ewww-image-optimizer' ),
7001
  $bulk_link
7002
+ ) . ewwwio_help_link( 'https://docs.ewww.io/article/4-getting-started', '5853713bc697912ffd6c0b98' ) . ' ' .
7003
  sprintf(
7004
  /* translators: %s: S3 Image Optimizer (link) */
7005
  esc_html__( 'Images stored in an Amazon S3 bucket can be optimized using our %s.' ),
7006
  $s3_link
7007
  ) .
7008
  "</p>\n";
7009
+
7010
+ $compress_score = 0;
7011
+ $resize_score = 0;
7012
+ $status_notices = '';
7013
+
7014
+ $compress_recommendations = array();
7015
+ $resize_recommendations = array();
7016
+
7017
  $status_output = "<div id='ewww-widgets' class='metabox-holder'><div class='meta-box-sortables'><div id='ewww-status' class='postbox'>\n" .
7018
+ "<h2 class='ewww-hndle'>" . esc_html__( 'Optimization Status', 'ewww-image-optimizer' ) . "</h2>\n<div class='inside'>";
7019
+
 
 
 
 
 
 
7020
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
7021
+ $status_notices .= '<p><b>' . esc_html__( 'Cloud optimization API Key', 'ewww-image-optimizer' ) . ':</b> ';
7022
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_cloud_exceeded', 0 );
7023
  $verify_cloud = ewww_image_optimizer_cloud_verify( false );
7024
+ if ( false !== strpos( $verify_cloud, 'great' ) ) {
7025
+ $compress_score += 30;
7026
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) > 20 ) {
7027
+ $compress_score += 50;
7028
+ } else {
7029
+ $compress_recommendations[] = esc_html__( 'Enable premium lossy compression for JPG images.', 'ewww-image-optimizer' );
7030
+ }
7031
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) > 20 ) {
7032
+ $compress_score += 20;
7033
+ } else {
7034
+ $compress_recommendations[] = esc_html__( 'Enable premium lossy compression for PNG images.', 'ewww-image-optimizer' );
7035
+ }
7036
+ $status_notices .= '<span style="color: #3eadc9; font-weight: bolder">' . esc_html__( 'Verified,', 'ewww-image-optimizer' ) . ' </span>' . ewww_image_optimizer_cloud_quota();
7037
+ } elseif ( false !== strpos( $verify_cloud, 'exceeded' ) ) {
7038
+ $status_notices .= '<span style="color: orange; font-weight: bolder">' . esc_html__( 'Out of credits', 'ewww-image-optimizer' ) . '</span> - <a href="https://ewww.io/plans/" target="_blank">' . esc_html__( 'Purchase more', 'ewww-image-optimizer' ) . '</a>';
7039
  } else {
7040
+ $status_notices .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Not Verified', 'ewww-image-optimizer' ) . '</span>';
 
7041
  }
7042
+ if ( false !== strpos( $verify_cloud, 'great' ) ) {
7043
+ $status_notices .= ' <a target="_blank" href="https://history.exactlywww.com/show/?api_key=' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) . '">' . esc_html__( 'View Usage', 'ewww-image-optimizer' ) . '</a>';
7044
+ }
7045
+ $status_notices .= "</p>\n";
7046
+ $disable_level = '';
7047
  } else {
7048
+ if ( ! class_exists( 'ExactDN' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
7049
+ $compress_recommendations[] = esc_html__( 'Enable premium compression with an API key or ExactDN.', 'ewww-image-optimizer' );
7050
+ }
7051
  $disable_level = "disabled='disabled'";
7052
  }
7053
  if ( class_exists( 'Jetpack_Photon' ) && Jetpack::is_module_active( 'photon' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
7054
+ $status_notices .= '<p><b>ExactDN:</b> <span style="color: red">' . esc_html__( 'Inactive, please disable the Image Performance option on the Jetpack Dashboard.', 'ewww-image-optimizer' ) . '</span></p>';
 
7055
  } elseif ( class_exists( 'ExactDN' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
7056
+ $status_notices .= '<p><b>ExactDN:</b> ';
7057
  global $exactdn;
7058
  if ( $exactdn->get_exactdn_domain() && $exactdn->verify_domain( $exactdn->get_exactdn_domain() ) ) {
7059
+ $status_notices .= '<span style="color: #3eadc9; font-weight: bolder">' . esc_html__( 'Verified', 'ewww-image-optimizer' ) . ' </span>';
7060
  if ( defined( 'WP_ROCKET_VERSION' ) ) {
7061
+ $status_notices .= '<br><i>' . esc_html__( 'If you use the File Optimization options within WP Rocket, you should also enter your ExactDN CNAME in the WP Rocket CDN settings (reserved for CSS and Javascript):', 'ewww-image-optimizer' ) . ' ' . $exactdn->get_exactdn_domain() . '</i>';
7062
+ }
7063
+ if ( $compress_score < 50 ) {
7064
+ $compress_score = 50;
7065
+ }
7066
+ $resize_score += 50;
7067
+ if ( ewww_image_optimizer_get_option( 'exactdn_lossy' ) ) {
7068
+ $compress_score = 100;
7069
+ } elseif ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) < 30 ) {
7070
+ $compress_recommendations[] = esc_html__( 'Enable premium lossy compression.', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/47-getting-more-from-exactdn', '59de6631042863379ddc953c' );
7071
  }
7072
  } elseif ( $exactdn->get_exactdn_domain() && $exactdn->get_exactdn_option( 'verified' ) ) {
7073
+ $status_notices .= '<span style="color: orange; font-weight: bolder">' . esc_html__( 'Temporarily disabled.', 'ewww-image-optimizer' ) . ' </span>';
 
7074
  } elseif ( $exactdn->get_exactdn_domain() && $exactdn->get_exactdn_option( 'suspended' ) ) {
7075
+ $status_notices .= '<span style="color: orange; font-weight: bolder">' . esc_html__( 'Active, not yet verified.', 'ewww-image-optimizer' ) . ' </span>';
 
7076
  } else {
7077
  ewwwio_debug_message( 'could not verify: ' . $exactdn->get_exactdn_domain() );
7078
+ $status_notices .= '<span style="color: red; font-weight: bolder"><a href="https://ewww.io/manage-sites/" target="_blank">' . esc_html__( 'Not Verified', 'ewww-image-optimizer' ) . '</a></span>';
 
7079
  }
7080
  if ( function_exists( 'remove_query_strings_link' ) || function_exists( 'rmqrst_loader_src' ) || function_exists( 'qsr_remove_query_strings_1' ) ) {
7081
+ $status_notices .= '<br><i>' . esc_html__( 'Plugins that remove query strings are unnecessary with ExactDN. You may remove them at your convenience.', 'ewww-image-optimizer' ) . '</i>' . ewwwio_help_link( 'https://docs.ewww.io/article/50-exactdn-and-query-strings', '5a3d278a2c7d3a1943677b52' );
7082
  }
7083
+ $status_notices .= '</p>';
7084
  } elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
7085
+ $status_notices .= '<p><b>ExactDN:</b> ' . esc_html__( 'Inactive, enable to activate automatic resizing and more', 'ewww-image-optimizer' ) . '</p>';
7086
+ $resize_recommendations[] = esc_html__( 'Enable ExactDN for automatic resizing.', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/44-introduction-to-exactdn', '59bc5ad6042863033a1ce370,59de6631042863379ddc953c,59c44349042863033a1d06d3,5ada43a12c7d3a0e93678b8c,5a3d278a2c7d3a1943677b52,5a9868eb04286374f7087795,59de68482c7d3a40f0ed6035,592dd69b2c7d3a074e8aed5b' );
7087
  delete_option( 'ewww_image_optimizer_exactdn_domain' );
7088
  delete_option( 'ewww_image_optimizer_exactdn_failures' );
7089
  delete_option( 'ewww_image_optimizer_exactdn_checkin' );
7097
  delete_site_option( 'ewww_image_optimizer_exactdn_validation' );
7098
  delete_site_option( 'ewww_image_optimizer_exactdn_suspended' );
7099
  }
7100
+ if (
7101
+ ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' ) ||
7102
+ ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' ) ||
7103
+ ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherwidth' ) ||
7104
+ ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherheight' )
7105
+ ) {
7106
+ $resize_score += 30;
7107
+ } else {
7108
+ $resize_recommendations[] = esc_html__( 'Configure maximum image dimensions in Resize settings.', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/41-resize-settings', '59849911042863033a1ba5f9' );
7109
+ }
7110
+ $jpg_quality = apply_filters( 'jpeg_quality', 82, 'image_resize' );
7111
+ if ( $jpg_quality < 90 && $jpg_quality > 50 ) {
7112
+ $resize_score += 20;
7113
+ } else {
7114
+ $resize_recommendations[] = esc_html__( 'JPG quality level should be between 50 and 90 for optimal resizing.', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/11-advanced-configuration', '58542afac697912ffd6c18c0,58543c69c697912ffd6c19a7' );
7115
  }
7116
+ $skip = ewww_image_optimizer_skip_tools();
 
7117
  if ( ! $skip['jpegtran'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
 
7118
  if ( EWWW_IMAGE_OPTIMIZER_JPEGTRAN ) {
7119
  $jpegtran_installed = ewww_image_optimizer_tool_found( EWWW_IMAGE_OPTIMIZER_JPEGTRAN, 'j' );
7120
  if ( ! $jpegtran_installed ) {
7122
  }
7123
  }
7124
  if ( ! empty( $jpegtran_installed ) ) {
7125
+ $compress_score += 5;
7126
  } else {
7127
+ $compress_recommendations[] = esc_html__( 'Install jpegtran.', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/6-the-plugin-says-i-m-missing-something', '585371e3c697912ffd6c0ba1' );
 
7128
  }
7129
  }
7130
  if ( ! $skip['optipng'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
 
7131
  if ( EWWW_IMAGE_OPTIMIZER_OPTIPNG ) {
7132
  $optipng_version = ewww_image_optimizer_tool_found( EWWW_IMAGE_OPTIMIZER_OPTIPNG, 'o' );
7133
  if ( ! $optipng_version ) {
7135
  }
7136
  }
7137
  if ( ! empty( $optipng_version ) ) {
7138
+ $compress_score += 5;
7139
  } else {
7140
+ $compress_recommendations[] = esc_html__( 'Install optipng.', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/6-the-plugin-says-i-m-missing-something', '585371e3c697912ffd6c0ba1' );
 
7141
  }
7142
  }
7143
  if ( ! $skip['pngout'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
 
7144
  if ( EWWW_IMAGE_OPTIMIZER_PNGOUT ) {
7145
  $pngout_version = ewww_image_optimizer_tool_found( EWWW_IMAGE_OPTIMIZER_PNGOUT, 'p' );
7146
  if ( ! $pngout_version ) {
7148
  }
7149
  }
7150
  if ( ! empty( $pngout_version ) ) {
7151
+ $compress_score += 5;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7152
  } else {
7153
+ $compress_recommendations[] = esc_html__( 'Install pngout', 'ewww-image-optimizer' ) . ': <a href="admin.php?action=ewww_image_optimizer_install_pngout">' . esc_html__( 'automatically', 'ewww-image-optimizer' ) . '</a> | <a href="https://docs.ewww.io/article/13-installing-pngout" data-beacon-article="5854531bc697912ffd6c1afa">' . esc_html__( 'manually', 'ewww-image-optimizer' ) . '</a>';
 
7154
  }
7155
  }
7156
  if ( ! $skip['pngquant'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
 
7157
  if ( EWWW_IMAGE_OPTIMIZER_PNGQUANT ) {
7158
  $pngquant_version = ewww_image_optimizer_tool_found( EWWW_IMAGE_OPTIMIZER_PNGQUANT, 'q' );
7159
  if ( ! $pngquant_version ) {
7161
  }
7162
  }
7163
  if ( ! empty( $pngquant_version ) ) {
7164
+ $compress_score += 5;
7165
+ } else {
7166
+ $compress_recommendations[] = esc_html__( 'Install pngquant.', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/6-the-plugin-says-i-m-missing-something', '585371e3c697912ffd6c0ba1' );
7167
+ }
7168
+ }
7169
+ if ( ! $skip['gifsicle'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
7170
+ if ( EWWW_IMAGE_OPTIMIZER_GIFSICLE ) {
7171
+ $gifsicle_version = ewww_image_optimizer_tool_found( EWWW_IMAGE_OPTIMIZER_GIFSICLE, 'g' );
7172
+ if ( ! $gifsicle_version ) {
7173
+ $gifsicle_version = ewww_image_optimizer_tool_found( EWWW_IMAGE_OPTIMIZER_GIFSICLE, 'gb' );
7174
+ }
7175
+ }
7176
+ if ( ! empty( $gifsicle_version ) ) {
7177
+ $compress_score += 5;
7178
  } else {
7179
+ $compress_recommendations[] = esc_html__( 'Install gifsicle.', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/6-the-plugin-says-i-m-missing-something', '585371e3c697912ffd6c0ba1' );
 
7180
  }
7181
  }
7182
  if ( EWWW_IMAGE_OPTIMIZER_CWEBP && ! $skip['webp'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
 
7183
  if ( EWWW_IMAGE_OPTIMIZER_CWEBP ) {
7184
  $webp_version = ewww_image_optimizer_tool_found( EWWW_IMAGE_OPTIMIZER_CWEBP, 'w' );
7185
  if ( ! $webp_version ) {
7187
  }
7188
  }
7189
  if ( ! empty( $webp_version ) ) {
7190
+ $compress_score += 5;
7191
  } else {
7192
+ $compress_recommendations[] = esc_html__( 'Install webp.', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/6-the-plugin-says-i-m-missing-something', '585371e3c697912ffd6c0ba1' );
 
7193
  }
7194
  }
7195
+ // Check that an image library exists for converting resizes. Originals can be done via the API, but resizes are done locally for speed.
7196
+ $toolkit_found = false;
7197
+ if ( ewww_image_optimizer_gd_support() ) {
7198
+ $toolkit_found = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7199
  }
7200
+ if ( ewww_image_optimizer_gmagick_support() ) {
7201
+ $toolkit_found = true;
 
 
 
 
 
 
7202
  }
7203
+ if ( ewww_image_optimizer_imagick_support() ) {
7204
+ $toolkit_found = true;
 
 
 
 
7205
  }
 
7206
  if ( PHP_OS != 'WINNT' && ! ewww_image_optimizer_full_cloud() && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
7207
+ ewww_image_optimizer_find_nix_binary( 'nice', 'n' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7208
  }
7209
+ $status_notices .= "<p>\n"; // This line encloses everything up to the end of the async stuff.
7210
+ $status_notices .= '<strong>' . esc_html( 'Background and Parallel optimization (faster uploads):', 'ewww-image-optimizer' ) . '</strong><br>';
 
 
 
 
 
 
 
 
 
7211
  if ( defined( 'EWWW_DISABLE_ASYNC' ) && EWWW_DISABLE_ASYNC ) {
7212
+ $status_notices .= '<span>' . esc_html__( 'Disabled by administrator', 'ewww-image-optimizer' ) . '</span>';
7213
  } elseif ( ! ewww_image_optimizer_function_exists( 'sleep' ) ) {
7214
+ $status_notices .= '<span style="color: orange; font-weight: bolder">' . esc_html__( 'Disabled, sleep function missing', 'ewww-image-optimizer' ) . '</span>';
7215
  } elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_background_optimization' ) ) {
7216
+ $status_notices .= '<span style="color: orange; font-weight: bolder">' . esc_html__( 'Disabled automatically, async requests blocked', 'ewww-image-optimizer' ) . " - <a href='admin.php?action=ewww_image_optimizer_retest_background_optimization'>" . esc_html__( 'Re-test', 'ewww-image-optimizer' ) . '</a><span>';
7217
  } elseif ( ewww_image_optimizer_detect_wpsf_location_lock() ) {
7218
+ $status_notices .= '<span style="color: orange; font-weight: bolder">' . esc_html__( "Disabled by Shield's Lock to Location feature", 'ewww-image-optimizer' ) . '</span>';
7219
  } elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_parallel_optimization' ) ) {
7220
+ $status_notices .= '<span>' . esc_html__( 'Background mode active, enable Parallel Optimization in Advanced Settings', 'ewww-image-optimizer' ) . '</span>';
7221
  } else {
7222
+ $status_notices .= '<span style="color: #3eadc9; font-weight: bolder">' . esc_html__( 'Fully Enabled', 'ewww-image-optimizer' ) . '</span>';
7223
  }
7224
+ $status_notices .= "</p>\n";
7225
+ if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
7226
+ $status_notices .= "<p><a href='https://ewww.io/plans' target='_blank' class='button button-primary' style='background:#3eadc9'>" . esc_html__( 'Premium Upgrades', 'ewww-image-optimizer' ) . "</a></p>\n";
7227
+ }
7228
+
7229
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) == true ) {
7230
+ $compress_score += 5;
7231
  } else {
7232
+ $compress_recommendations[] = esc_html__( 'Remove metadata from JPG images.', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/7-basic-configuration', '585373d5c697912ffd6c0bb2' );
7233
+ }
7234
+
7235
+ // Begin building of status inside section.
7236
+ $status_output .= '<div class="ewww-row"><ul class="ewww-blocks">';
7237
+ $compress_score = min( $compress_score, 100 );
7238
+ $resize_score = min( $resize_score, 100 );
7239
+
7240
+ $guage_stroke_dasharray = 2 * pi() * 54;
7241
+ $compress_stroke_dashoffset = $guage_stroke_dasharray * ( 1 - $compress_score / 100 );
7242
+ $resize_stroke_dashoffset = $guage_stroke_dasharray * ( 1 - $resize_score / 100 );
7243
+
7244
+ $status_output .= '<li><div id="ewww-compress" class="ewww-status-detail">';
7245
+ $compress_guage = '<div id="ewww-compress-guage" class="ewww-guage" data-score="' . $compress_score . '">' .
7246
+ '<svg width="120" height="120">' .
7247
+ '<circle class="ewww-inactive" r="54" cy="60" cx="60" stroke-width="12"/>' .
7248
+ '<circle class="ewww-active" r="54" cy="60" cx="60" stroke-width="12" style="stroke-dasharray: ' . $guage_stroke_dasharray . 'px; stroke-dashoffset: ' . $compress_stroke_dashoffset . 'px;"/>' .
7249
+ '</svg>' .
7250
+ '<div class="ewww-score">' . $compress_score . '%</div>' .
7251
+ '</div><!-- end .ewww-guage -->';
7252
+ $status_output .= $compress_guage;
7253
+ $status_output .= '<div id="ewww-compress-recommend" class="ewww-recommend"><strong>' . ( $compress_score < 100 ? esc_html__( 'How do I get to 100%?', 'ewww-image-optimizer' ) : esc_html__( 'You got the perfect score!', 'ewww-image-optimizer' ) ) . '</strong>';
7254
+ if ( $compress_score < 100 ) {
7255
+ $status_output .= '<ul class="ewww-tooltip">';
7256
+ foreach ( $compress_recommendations as $c_recommend ) {
7257
+ $status_output .= "<li>$c_recommend</li>";
7258
+ }
7259
+ $status_output .= '</ul>';
7260
+ }
7261
+ $status_output .= '</div><!-- end .ewww-recommend -->';
7262
+ $status_output .= '<p><strong>' . esc_html__( 'Compress', 'ewww-image-optimizer' ) . '</strong></p>';
7263
+ $status_output .= '<p>' . esc_html__( 'Reduce the file size of your images without affecting quality.', 'ewww-image-optimizer' ) . '</p>';
7264
+ $status_output .= '</div><!-- end .ewww-status-detail --></li>';
7265
+
7266
+ $status_output .= '<li><div id="ewww-resize" class="ewww-status-detail">';
7267
+ $resize_guage = '<div id="ewww-resize-guage" class="ewww-guage" data-score="' . $resize_score . '">' .
7268
+ '<svg width="120" height="120">' .
7269
+ '<circle class="ewww-inactive" r="54" cy="60" cx="60" stroke-width="12"/>' .
7270
+ '<circle class="ewww-active" r="54" cy="60" cx="60" stroke-width="12" style="stroke-dasharray: ' . $guage_stroke_dasharray . 'px; stroke-dashoffset: ' . $resize_stroke_dashoffset . 'px;"/>' .
7271
+ '</svg>' .
7272
+ '<div class="ewww-score">' . $resize_score . '%</div>' .
7273
+ '</div><!-- end .ewww-guage -->';
7274
+ $status_output .= $resize_guage;
7275
+ $status_output .= '<div id="ewww-resize-recommend" class="ewww-recommend"><strong>' . ( $resize_score < 100 ? esc_html__( 'How do I get to 100%?', 'ewww-image-optimizer' ) : esc_html__( 'You got the perfect score!', 'ewww-image-optimizer' ) ) . '</strong>';
7276
+ if ( $resize_score < 100 ) {
7277
+ $status_output .= '<ul class="ewww-tooltip">';
7278
+ foreach ( $resize_recommendations as $r_recommend ) {
7279
+ $status_output .= "<li>$r_recommend</li>";
7280
+ }
7281
+ $status_output .= '</ul>';
7282
+ }
7283
+ $status_output .= '</div><!-- end .ewww-recommend -->';
7284
+ $status_output .= '<p><strong>' . esc_html__( 'Resize', 'ewww-image-optimizer' ) . '</strong></p>';
7285
+ $status_output .= '<p>' . esc_html__( 'Scale or reduce the dimensions of your images for more savings.', 'ewww-image-optimizer' ) . '</p>';
7286
+ $status_output .= '</div><!-- end .ewww-status-detail --></li>';
7287
+
7288
+ $total_sizes = ewww_image_optimizer_savings();
7289
+ $total_savings = $total_sizes[1] - $total_sizes[0];
7290
+ if ( $total_savings > 0 ) {
7291
+ $savings_stroke_dashoffset = $guage_stroke_dasharray * ( 1 - $total_savings / $total_sizes[1] );
7292
+
7293
+ $status_output .= '<li><div id="ewww-compress" class="ewww-status-detail">';
7294
+ $savings_guage = '<div id="ewww-savings-guage" class="ewww-guage" data-score="' . $total_savings / $total_sizes[1] . '">' .
7295
+ '<svg width="120" height="120">' .
7296
+ '<title>' . round( $total_savings / $total_sizes[1], 3 ) * 100 . '%</title>' .
7297
+ '<circle class="ewww-inactive" r="54" cy="60" cx="60" stroke-width="12"/>' .
7298
+ '<circle class="ewww-active" r="54" cy="60" cx="60" stroke-width="12" style="stroke-dasharray: ' . $guage_stroke_dasharray . 'px; stroke-dashoffset: ' . $savings_stroke_dashoffset . 'px;"/>' .
7299
+ '</svg>' .
7300
+ '<div class="ewww-score">' . ewww_image_optimizer_size_format( $total_savings, 2 ) . '</div>' .
7301
+ '</div><!-- end .ewww-guage -->';
7302
+ $status_output .= $savings_guage;
7303
+ $status_output .= '<p style="text-align:center"><strong>' . esc_html__( 'Savings', 'ewww-image-optimizer' ) . '</strong></p>';
7304
+ $status_output .= '</div><!-- end .ewww-status-detail --></li>';
7305
  }
7306
+ ewwwio_debug_message( ewww_image_optimizer_aux_images_table_count() . ' images have been optimized' );
7307
+
7308
+ $status_output .= '<li><div class="ewww-status-detail"><div id="ewww-notices">' . $status_notices . '</div></div></li>';
7309
+
7310
+ $status_output .= '</ul><!-- end .ewww-blocks --></div><!-- end .ewww-row -->';
7311
+ $status_output .= '</div><!-- end .inside -->';
7312
+ $status_output .= "</div></div></div>\n";
7313
+
7314
+ // End status section.
7315
+ $output[] = $status_output;
7316
+
7317
  if ( ( 'network-multisite' != $network || ! get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) ) && // Display tabs so long as this isn't the network admin OR single-site override is disabled.
7318
  ! ( 'network-singlesite' == $network && ! get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) ) ) { // Also make sure that this isn't single site without override mode.
7319
  $output[] = "<ul class='ewww-tab-nav'>\n" .
7320
+ "<li class='ewww-tab ewww-general-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Basic', 'ewww-image-optimizer' ) . "</span></li>\n" .
7321
+ "<li class='ewww-tab ewww-exactdn-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'ExactDN', 'ewww-image-optimizer' ) . "</span></li>\n" .
7322
+ "<li class='ewww-tab ewww-optimization-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Advanced', 'ewww-image-optimizer' ) . "</span></li>\n" .
7323
+ "<li class='ewww-tab ewww-resize-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Resize', 'ewww-image-optimizer' ) . "</span></li>\n" .
7324
+ "<li class='ewww-tab ewww-conversion-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Convert', 'ewww-image-optimizer' ) . "</span></li>\n" .
7325
+ "<li class='ewww-tab ewww-webp-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'WebP', 'ewww-image-optimizer' ) . "</span></li>\n" .
7326
+ "<li class='ewww-tab ewww-overrides-nav'><span class='ewww-tab-hidden'><a href='https://docs.ewww.io/article/40-override-options' target='_blank'><span class='ewww-tab-hidden'>" . esc_html__( 'Overrides', 'ewww-image-optimizer' ) . "</a></span></li>\n" .
7327
  "</ul>\n";
7328
  }
7329
  if ( 'network-multisite' == $network ) {
7341
  $output[] = "<table class='form-table'>\n";
7342
  if ( is_multisite() ) {
7343
  if ( is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) ) {
7344
+ $output[] = "<tr class='network-only'><th scope='row'><label for='ewww_image_optimizer_allow_multisite_override'>" . esc_html__( 'Allow Single-site Override', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_allow_multisite_override' name='ewww_image_optimizer_allow_multisite_override' value='true' " . ( get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Allow individual sites to configure their own settings and override all network options.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7345
  }
7346
  if ( 'network-multisite' == $network && get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) ) {
7347
+ $output[] = "<tr><th scope='row'><label for='ewww_image_optimizer_allow_tracking'>" . esc_html__( 'Allow Usage Tracking?', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_allow_tracking' name='ewww_image_optimizer_allow_tracking' value='true' " . ( get_site_option( 'ewww_image_optimizer_allow_tracking' ) == true ? "checked='true'" : '' ) . ' /> ' .
7348
  esc_html__( 'Allow EWWW Image Optimizer to anonymously track how this plugin is used and help us make the plugin better. Opt-in to tracking and receive 500 API image credits free. No sensitive data is tracked.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7349
  $output[] = "<input type='hidden' id='ewww_image_optimizer_allow_multisite_override_active' name='ewww_image_optimizer_allow_multisite_override_active' value='0'>";
7350
  if ( get_site_option( 'ewww_image_optimizer_cloud_key' ) ) {
7360
  }
7361
  }
7362
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
7363
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_cloud_notkey'>" . esc_html__( 'Optimization API Key', 'ewww-image-optimizer' ) . "</label></th><td><input type='text' id='ewww_image_optimizer_cloud_notkey' name='ewww_image_optimizer_cloud_notkey' readonly='readonly' value='****************************" . substr( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ), 28 ) . "' size='32' /> <a href='admin.php?action=ewww_image_optimizer_remove_cloud_key'>" . esc_html__( 'Remove API key', 'ewww-image-optimizer' ) . "</a></td></tr>\n";
7364
  $output[] = "<input type='hidden' id='ewww_image_optimizer_cloud_key' name='ewww_image_optimizer_cloud_key' value='" . ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) . "' />\n";
7365
  } else {
7366
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_cloud_key'>" . esc_html__( 'Optimization API Key', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/7-basic-configuration', '585373d5c697912ffd6c0bb2,5ad0c8e7042863075092650b,5a9efec62c7d3a7549516550' ) . "</th><td><input type='text' id='ewww_image_optimizer_cloud_key' name='ewww_image_optimizer_cloud_key' value='' size='32' /> " . esc_html__( 'API Key will be validated when you save your settings.', 'ewww-image-optimizer' ) . " <a href='https://ewww.io/plans/' target='_blank'>" . esc_html__( 'Purchase an API key.', 'ewww-image-optimizer' ) . "</a></td></tr>\n";
7367
  }
7368
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_debug'>" . esc_html__( 'Debugging', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/7-basic-configuration', '585373d5c697912ffd6c0bb2' ) . '</th>' .
7369
+ "<td><input type='checkbox' id='ewww_image_optimizer_debug' name='ewww_image_optimizer_debug' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Use this to provide information for support purposes, or if you feel comfortable digging around in the code to fix a problem you are experiencing.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7370
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_jpegtran_copy'>" . esc_html__( 'Remove Metadata', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/7-basic-configuration', '585373d5c697912ffd6c0bb2' ) . "</th>\n" .
7371
  "<td><input type='checkbox' id='ewww_image_optimizer_jpegtran_copy' name='ewww_image_optimizer_jpegtran_copy' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'This will remove ALL metadata: EXIF, comments, color profiles, and anything else that is not pixel data.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7372
  ewwwio_debug_message( 'remove metadata: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) == true ? 'on' : 'off' ) );
7373
  $output[] = "<tr class='$network_class'><th>&nbsp;</th><td>" .
7375
  ' ' . esc_html__( 'Lossless compression is actually identical to the original, while lossy reduces the quality a small amount.', 'ewww-image-optimizer' ) . "</p>\n" .
7376
  ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ? "<p class='$network_class nocloud'><strong>* <a href='https://ewww.io/plans/' target='_blank'>" . esc_html__( 'Get an API key to achieve up to 80% compression and see the quality for yourself.', 'ewww-image-optimizer' ) . "</a></strong></p>\n" : '' );
7377
  $output[] = "</td></tr>\n";
7378
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_jpg_level'>" . esc_html__( 'JPG Optimization Level', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/7-basic-configuration', '585373d5c697912ffd6c0bb2' ) . "</th>\n" .
7379
  "<td><span><select id='ewww_image_optimizer_jpg_level' name='ewww_image_optimizer_jpg_level'>\n" .
7380
  "<option value='0'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ), 0, false ) . '>' . esc_html__( 'No Compression', 'ewww-image-optimizer' ) . "</option>\n";
7381
  if ( defined( 'EWWW_IMAGE_OPTIMIZER_TOOL_PATH' ) ) {
7386
  "<option $disable_level value='40'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ), 40, false ) . '>' . esc_html__( 'Maximum Lossy Compression', 'ewww-image-optimizer' ) . " *</option>\n" .
7387
  "</select></td></tr>\n";
7388
  ewwwio_debug_message( 'jpg level: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) );
7389
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_png_level'>" . esc_html__( 'PNG Optimization Level', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/7-basic-configuration', '585373d5c697912ffd6c0bb2,5854531bc697912ffd6c1afa' ) . "</th>\n" .
7390
  "<td><span><select id='ewww_image_optimizer_png_level' name='ewww_image_optimizer_png_level'>\n" .
7391
  "<option value='0'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ), 0, false ) . '>' . esc_html__( 'No Compression', 'ewww-image-optimizer' ) . "</option>\n";
7392
  if ( defined( 'EWWW_IMAGE_OPTIMIZER_TOOL_PATH' ) ) {
7398
  "<option $disable_level value='50'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ), 50, false ) . '>' . esc_html__( 'Maximum Lossy Compression', 'ewww-image-optimizer' ) . " *</option>\n" .
7399
  "</select></td></tr>\n";
7400
  ewwwio_debug_message( 'png level: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) );
7401
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_gif_level'>" . esc_html__( 'GIF Optimization Level', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/7-basic-configuration', '585373d5c697912ffd6c0bb2' ) . "</th>\n" .
7402
  "<td><span><select id='ewww_image_optimizer_gif_level' name='ewww_image_optimizer_gif_level'>\n" .
7403
  "<option value='0'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' ), 0, false ) . '>' . esc_html__( 'No Compression', 'ewww-image-optimizer' ) . "</option>\n" .
7404
  "<option value='10'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' ), 10, false ) . '>' . esc_html__( 'Lossless Compression', 'ewww-image-optimizer' ) . "</option>\n" .
7405
  "</select></td></tr>\n";
7406
  ewwwio_debug_message( 'gif level: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' ) );
7407
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_pdf_level'>" . esc_html__( 'PDF Optimization Level', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/7-basic-configuration', '585373d5c697912ffd6c0bb2' ) . "</th>\n" .
 
 
 
 
 
 
7408
  "<td><span><select id='ewww_image_optimizer_pdf_level' name='ewww_image_optimizer_pdf_level'>\n" .
7409
  "<option value='0'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ), 0, false ) . '>' . esc_html__( 'No Compression', 'ewww-image-optimizer' ) . "</option>\n" .
7410
+ "<option $disable_level value='10'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ), 10, false ) . '>' . esc_html__( 'Lossless Compression', 'ewww-image-optimizer' ) . " *</option>\n" .
7411
+ "<option $disable_level value='20'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ), 20, false ) . '>' . esc_html__( 'Lossy Compression', 'ewww-image-optimizer' ) . " *</option>\n" .
7412
  "</select></td></tr>\n";
7413
  ewwwio_debug_message( 'pdf level: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ) );
7414
  ewwwio_debug_message( 'bulk delay: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_delay' ) );
7415
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_backup_files'>" . esc_html__( 'Backup Originals', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/7-basic-configuration', '585373d5c697912ffd6c0bb2' ) . '</th>' .
7416
+ "<td><input type='checkbox' id='ewww_image_optimizer_backup_files' name='ewww_image_optimizer_backup_files' value='true' " .
7417
  ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_backup_files' ) ? "checked='true'" : '' ) . " $disable_level > " . esc_html__( 'Store a copy of your original images on our secure server for 30 days. *Requires an active API key.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7418
  ewwwio_debug_message( 'backup mode: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_backup_files' ) ? 'on' : 'off' ) );
7419
  if ( class_exists( 'Cloudinary' ) && Cloudinary::config_get( 'api_secret' ) ) {
7420
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_enable_cloudinary'>" . esc_html__( 'Automatic Cloudinary Upload', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_enable_cloudinary' name='ewww_image_optimizer_enable_cloudinary' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_cloudinary' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'When enabled, uploads to the Media Library will be transferred to Cloudinary after optimization. Cloudinary generates resizes, so only the full-size image is uploaded.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7421
  ewwwio_debug_message( 'cloudinary upload: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_cloudinary' ) == true ? 'on' : 'off' ) );
7422
  }
7423
  $output[] = "</table>\n</div>\n";
7424
+ $output[] = "<div id='ewww-exactdn-settings'>\n";
7425
+ $output[] = "<table class='form-table'>\n";
7426
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_exactdn'>" . esc_html__( 'ExactDN', 'ewww-image-optimizer' ) .
7427
+ '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/44-introduction-to-exactdn', '59bc5ad6042863033a1ce370,59de6631042863379ddc953c,59c44349042863033a1d06d3,5ada43a12c7d3a0e93678b8c,5a3d278a2c7d3a1943677b52,5a9868eb04286374f7087795,59de68482c7d3a40f0ed6035,592dd69b2c7d3a074e8aed5b' ) . "</th><td><input type='checkbox' id='ewww_image_optimizer_exactdn' name='ewww_image_optimizer_exactdn' value='true' " .
7428
+ ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) == true ? "checked='true'" : '' ) . ' /> ' .
7429
+ esc_html__( 'Enables CDN and automatic image resizing to fit your pages.', 'ewww-image-optimizer' ) .
7430
+ ' <a href="https://ewww.io/resize/" target="_blank">' . esc_html__( 'Purchase a subscription for your site.', 'ewww-image-optimizer' ) . '</a>' .
7431
+ '<p class="description">' .
7432
+ esc_html__( 'WebP Conversion', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/16-ewww-io-and-webp-images', '5854745ac697912ffd6c1c89' ) . '<br>' .
7433
+ esc_html__( 'Retina Support, use with WP Retina 2x for best results', 'ewww-image-optimizer' ) . '<br>' .
7434
+ esc_html__( 'Premium Compression', 'ewww-image-optimizer' ) . '<br>' .
7435
+ esc_html__( 'Adjustable Quality', 'ewww-image-optimizer' ) . '<br>' .
7436
+ esc_html__( 'JS/CSS Minification and Compression', 'ewww-image-optimizer' ) . '<br>' .
7437
+ '<a href="https://docs.ewww.io/article/44-introduction-to-exactdn" target="_blank" data-beacon-article="59bc5ad6042863033a1ce370">' . esc_html__( 'Learn more about ExactDN', 'ewww-image-optimizer' ) . '</a>' .
7438
+ "</p></td></tr>\n";
7439
+ ewwwio_debug_message( 'ExactDN enabled: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) == true ? 'on' : 'off' ) );
7440
+ ewwwio_debug_message( 'ExactDN all the things: ' . ( ewww_image_optimizer_get_option( 'exactdn_all_the_things' ) == true ? 'on' : 'off' ) );
7441
+ ewwwio_debug_message( 'ExactDN lossy: ' . intval( ewww_image_optimizer_get_option( 'exactdn_lossy' ) ) );
7442
+ ewwwio_debug_message( 'ExactDN resize existing: ' . ( ewww_image_optimizer_get_option( 'exactdn_resize_existing' ) == true ? 'on' : 'off' ) );
7443
+ ewwwio_debug_message( 'ExactDN attachment queries: ' . ( ewww_image_optimizer_get_option( 'exactdn_prevent_db_queries' ) == true ? 'off' : 'on' ) );
7444
+ if ( defined( 'EXACTDN_EXCLUDE' ) && EXACTDN_EXCLUDE ) {
7445
+ if ( is_string( EXACTDN_EXCLUDE ) ) {
7446
+ ewwwio_debug_message( 'ExactDN user exclusions : ' . EXACTDN_EXCLUDE );
7447
+ } elseif ( is_array( EXACTDN_EXCLUDE ) ) {
7448
+ ewwwio_debug_message( 'ExactDN user exclusions : ' . implode( ',', EXACTDN_EXCLUDE ) );
7449
+ } else {
7450
+ ewwwio_debug_message( 'ExactDN user exclusions invalid data type' );
7451
+ }
7452
+ }
7453
+ $output[] = "</table>\n</div>\n";
7454
  $output[] = "<div id='ewww-optimization-settings'>\n";
7455
  $output[] = "<table class='form-table'>\n";
7456
  if ( ! ewww_image_optimizer_full_cloud() ) {
7458
  ewwwio_debug_message( 'pngout disabled: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_pngout' ) == true ? 'yes' : 'no' ) );
7459
  ewwwio_debug_message( 'pngout level: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_pngout_level' ) );
7460
  }
7461
+ $output[] = "<tr class='$network_class'><th scope='row'><span><label for='ewww_image_optimizer_jpg_quality'>" . esc_html__( 'JPG Quality Level:', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/11-advanced-configuration', '58542afac697912ffd6c18c0,58543c69c697912ffd6c19a7' ) . "</th><td><input type='text' id='ewww_image_optimizer_jpg_quality' name='ewww_image_optimizer_jpg_quality' class='small-text' value='" . ewww_image_optimizer_jpg_quality() . "' /> " . esc_html__( 'Valid values are 1-100.', 'ewww-image-optimizer' ) . "\n<p class='description'>" . esc_html__( 'Use this to override the default WordPress quality level of 82. Applies to image editing, resizing, PNG to JPG conversion, and JPG to WebP conversion. Does not affect the original uploaded image unless maximum dimensions are set and resizing occurs.', 'ewww-image-optimizer' ) . "</p></td></tr>\n";
7462
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_parallel_optimization'>" . esc_html__( 'Parallel Optimization', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/11-advanced-configuration', '58542afac697912ffd6c18c0,598cb8be2c7d3a73488be237' ) . "</th><td><input type='checkbox' id='ewww_image_optimizer_parallel_optimization' name='ewww_image_optimizer_parallel_optimization' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_parallel_optimization' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'All resizes generated from a single upload are optimized in parallel for faster optimization. If this is causing performance issues, disable parallel optimization to reduce the load on your server.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7463
  ewwwio_debug_message( 'parallel optimization: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_parallel_optimization' ) == true ? 'on' : 'off' ) );
7464
  ewwwio_debug_message( 'background optimization: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_background_optimization' ) == true ? 'on' : 'off' ) );
7465
  if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_background_optimization' ) ) {
7505
  ewwwio_debug_message( "invalid admin ajax url: $admin_ajax_url" );
7506
  }
7507
  }
7508
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_auto'>" . esc_html__( 'Scheduled Optimization', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/11-advanced-configuration', '58542afac697912ffd6c18c0,5853713bc697912ffd6c0b98' ) . "</th><td><input type='checkbox' id='ewww_image_optimizer_auto' name='ewww_image_optimizer_auto' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_auto' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'This will enable scheduled optimization of unoptimized images for your theme, buddypress, and any additional folders you have configured below. Runs hourly: wp_cron only runs when your site is visited, so it may be even longer between optimizations.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7509
  ewwwio_debug_message( 'scheduled optimization: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_auto' ) == true ? 'on' : 'off' ) );
7510
  $media_include_disable = '';
7511
  if ( get_option( 'ewww_image_optimizer_disable_resizes_opt' ) ) {
7512
  $media_include_disable = 'disabled="disabled"';
7513
  $output[] = "<tr class='$network_class'><th>&nbsp;</th><td>" .
7514
+ '<p><span style="color: #3eadc9">' . esc_html__( '*Include Media Library Folders has been disabled because it will cause the scanner to ignore the disabled resizes.', 'ewww-image-optimizer' ) . "</span></p></td></tr>\n";
7515
  }
7516
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_include_media_paths'>" . esc_html__( 'Include Media Folders', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/11-advanced-configuration', '58542afac697912ffd6c18c0,5853713bc697912ffd6c0b98' ) . "</th><td><input type='checkbox' id='ewww_image_optimizer_include_media_paths' name='ewww_image_optimizer_include_media_paths' $media_include_disable value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_include_media_paths' ) == true && ! get_option( 'ewww_image_optimizer_disable_resizes_opt' ) ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Scan all images from the latest two folders of the Media Library during the Bulk Optimizer and Scheduled Optimization.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7517
  ewwwio_debug_message( 'include media library: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_include_media_paths' ) == true ? 'on' : 'off' ) );
7518
  $aux_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_aux_paths' ) ? esc_html( implode( "\n", ewww_image_optimizer_get_option( 'ewww_image_optimizer_aux_paths' ) ) ) : '';
7519
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_aux_paths'>" . esc_html__( 'Folders to Optimize', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/11-advanced-configuration', '58542afac697912ffd6c18c0,5853713bc697912ffd6c0b98' ) . '</th><td>' .
7520
  /* translators: %s: the folder where WordPress is installed */
7521
  sprintf( esc_html__( 'One path per line, must be within %s. Use full paths, not relative paths.', 'ewww-image-optimizer' ), ABSPATH ) . "<br>\n" .
7522
  "<textarea id='ewww_image_optimizer_aux_paths' name='ewww_image_optimizer_aux_paths' rows='3' cols='60'>$aux_paths</textarea>\n" .
7525
  ewwwio_debug_message( $aux_paths );
7526
 
7527
  $exclude_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_exclude_paths' ) ? esc_html( implode( "\n", ewww_image_optimizer_get_option( 'ewww_image_optimizer_exclude_paths' ) ) ) : '';
7528
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_exclude_paths'>" . esc_html__( 'Folders to Ignore', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/11-advanced-configuration', '58542afac697912ffd6c18c0,5853713bc697912ffd6c0b98' ) . '</th><td>' . esc_html__( 'One path per line, partial paths allowed, but no urls.', 'ewww-image-optimizer' ) . "<br>\n" .
7529
  "<textarea id='ewww_image_optimizer_exclude_paths' name='ewww_image_optimizer_exclude_paths' rows='3' cols='60'>$exclude_paths</textarea>\n" .
7530
  "<p class='description'>" . esc_html__( 'A file that matches any pattern or path provided will not be optimized.', 'ewww-image-optimizer' ) . "</p></td></tr>\n";
7531
  ewwwio_debug_message( 'folders to ignore:' );
7535
  ewwwio_debug_message( 'exclude originals from lossy: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_lossy_skip_full' ) == true ? 'on' : 'off' ) );
7536
  ewwwio_debug_message( 'exclude originals from metadata removal: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_skip_full' ) == true ? 'on' : 'off' ) );
7537
  ewwwio_debug_message( 'use system binaries: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_skip_bundle' ) == true ? 'yes' : 'no' ) );
7538
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_enable_help'>" . esc_html__( 'Enable Embedded Help', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_enable_help' name='ewww_image_optimizer_enable_help' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_help' ) == true ? "checked='true'" : '' ) . ' /> ' .
7539
  esc_html__( 'Enable the support beacon, which gives you access to documentation and our support team right from your WordPress dashboard. To assist you more efficiently, we may collect the current url, IP address, browser/device information, and debugging information.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7540
  ewwwio_debug_message( 'enable help beacon: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_help' ) == true ? 'yes' : 'no' ) );
7541
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_allow_tracking'>" . esc_html__( 'Allow Usage Tracking?', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/23-usage-tracking', '591f3a8e2c7d3a057f893d91' ) . "</th><td><input type='checkbox' id='ewww_image_optimizer_allow_tracking' name='ewww_image_optimizer_allow_tracking' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_allow_tracking' ) == true ? "checked='true'" : '' ) . ' /> ' .
7542
  esc_html__( 'Allow EWWW Image Optimizer to anonymously track how this plugin is used and help us make the plugin better. Opt-in to tracking and receive 500 API image credits free. No sensitive data is tracked.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7543
  $output[] = "</table>\n</div>\n";
7544
 
7545
  $output[] = "<div id='ewww-resize-settings'>\n";
7546
  $output[] = "<table class='form-table'>\n";
7547
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_resize_detection'>" . esc_html__( 'Resize Detection', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/41-resize-settings', '59849911042863033a1ba5f9' ) . "</th><td><input type='checkbox' id='ewww_image_optimizer_resize_detection' name='ewww_image_optimizer_resize_detection' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_detection' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Highlight images that need to be resized because the browser is scaling them down. Only visible for Admin users and adds a button to the admin bar to detect scaled images that have been lazy loaded.', 'ewww-image-optimizer' ) . "</td></tr>\n";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7548
  ewwwio_debug_message( 'resize detection: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_detection' ) == true ? 'on' : 'off' ) );
7549
  if ( function_exists( 'imsanity_get_max_width_height' ) ) {
7550
  $output[] = "<tr class='$network_class'><th>&nbsp;</th><td>" .
7551
+ '<p><span style="color: #3eadc9">' . esc_html__( '*Imsanity settings override the EWWW resize dimensions.', 'ewww-image-optimizer' ) . "</span></p></td></tr>\n";
7552
  }
7553
+ $output[] = "<tr class='$network_class'><th scope='row'>" . esc_html__( 'Resize Media Images', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/41-resize-settings', '59849911042863033a1ba5f9' ) . "</th><td><label for='ewww_image_optimizer_maxmediawidth'>" . esc_html__( 'Max Width', 'ewww-image-optimizer' ) . "</label> <input type='number' step='1' min='0' class='small-text' id='ewww_image_optimizer_maxmediawidth' name='ewww_image_optimizer_maxmediawidth' value='" . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' ) . ( function_exists( 'imsanity_get_max_width_height' ) ? "' disabled='disabled" : '' ) . "' /> <label for='ewww_image_optimizer_maxmediaheight'>" . esc_html__( 'Max Height', 'ewww-image-optimizer' ) . "</label> <input type='number' step='1' min='0' class='small-text' id='ewww_image_optimizer_maxmediaheight' name='ewww_image_optimizer_maxmediaheight' value='" . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' ) . ( function_exists( 'imsanity_get_max_width_height' ) ? "' disabled='disabled" : '' ) . "' /> " . esc_html__( 'in pixels', 'ewww-image-optimizer' ) . "\n" .
7554
+ "<p class='description'>" . esc_html__( 'Resizes images uploaded to the Media Library.', 'ewww-image-optimizer' ) .
7555
  "</td></tr>\n";
7556
  ewwwio_debug_message( 'max media dimensions: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' ) . ' x ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' ) );
 
 
 
7557
  ewwwio_debug_message( 'max other dimensions: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherwidth' ) . ' x ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherheight' ) );
7558
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_resize_existing'>" . esc_html__( 'Resize Existing Images', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/41-resize-settings', '59849911042863033a1ba5f9' ) . "</th><td><input type='checkbox' id='ewww_image_optimizer_resize_existing' name='ewww_image_optimizer_resize_existing' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Allow resizing of existing Media Library images.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7559
  ewwwio_debug_message( 'resize existing images: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' ) == true ? 'on' : 'off' ) );
7560
 
7561
+ $output[] = '<tr class="network-singlesite"><th scope="row">' . esc_html__( 'Disable Resizes', 'ewww-image-optimizer' ) .
7562
+ ewwwio_help_link( 'https://docs.ewww.io/article/41-resize-settings', '59849911042863033a1ba5f9,58598744c697912ffd6c3eb4' ) . '</th><td><p>' .
7563
+ esc_html__( 'WordPress, your theme, and other plugins generate various image sizes. You may disable optimization for certain sizes, or completely prevent those sizes from being created.', 'ewww-image-optimizer' ) . '<br>' .
7564
+ '<i>' . esc_html__( 'Remember that each image size will affect your API credits.', 'ewww-image-optimizer' ) . "</i></p>\n";
7565
  $image_sizes = ewww_image_optimizer_get_image_sizes();
7566
  $disabled_sizes = get_option( 'ewww_image_optimizer_disable_resizes' );
7567
  $disabled_sizes_opt = get_option( 'ewww_image_optimizer_disable_resizes_opt' );
7568
+ $output[] = '<table><tr class="network-singlesite"><th scope="col">' . esc_html__( 'Disable Optimization', 'ewww-image-optimizer' ) . '</th><th scope="col">' . esc_html__( 'Disable Creation', 'ewww-image-optimizer' ) . "</th></tr>\n";
7569
  ewwwio_debug_message( 'disabled resizes:' );
7570
  foreach ( $image_sizes as $size => $dimensions ) {
7571
  if ( 'thumbnail' == $size ) {
7581
  $output[] = "</table>\n";
7582
  $output[] = "</td></tr>\n";
7583
  } else {
7584
+ $output[] = '<tr><th scope="row">' . esc_html__( 'Disable Resizes', 'ewww-image-optimizer' ) . '</th><td>';
7585
+ $output[] = '<p><span style="color: #3eadc9">' . esc_html__( '*Settings to disable creation and optimization of individual sizes must be configured for each individual site.', 'ewww-image-optimizer' ) . "</span></p></td></tr>\n";
7586
  }
7587
  $output[] = "</table>\n</div>\n";
7588
  $output[] = "<div id='ewww-conversion-settings'>\n";
7590
  '<b>' . esc_html__( 'NOTE:', 'ewww-image-optimizer' ) . '</b> ' . esc_html__( 'The plugin will attempt to update image locations for any posts that contain the images. You may still need to manually update locations/urls for converted images.', 'ewww-image-optimizer' ) . "\n" .
7591
  "</p>\n";
7592
  $output[] = "<table class='form-table'>\n";
7593
+ if ( $toolkit_found ) {
7594
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_disable_convert_links'>" . esc_html__( 'Hide Conversion Links', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/14-converting-images', '58545a86c697912ffd6c1b53' ) . "</th><td><input type='checkbox' id='ewww_image_optimizer_disable_convert_links' name='ewww_image_optimizer_disable_convert_links' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_convert_links' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Site or Network admins can use this to prevent other users from using the conversion links in the Media Library which bypass the settings below.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7595
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_delete_originals'>" . esc_html__( 'Delete Originals', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/14-converting-images', '58545a86c697912ffd6c1b53' ) . "</th><td><input type='checkbox' id='ewww_image_optimizer_delete_originals' name='ewww_image_optimizer_delete_originals' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'This will remove the original image from the server after a successful conversion.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7596
+ ewwwio_debug_message( 'delete originals: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' ) == true ? 'on' : 'off' ) );
7597
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_jpg_to_png'>" .
7598
+ /* translators: 1: JPG, GIF or PNG 2: JPG or PNG */
7599
+ sprintf( esc_html__( '%1$s to %2$s Conversion', 'ewww-image-optimizer' ), 'JPG', 'PNG' ) .
7600
+ '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/14-converting-images', '58545a86c697912ffd6c1b53' ) . "</th><td><span><input type='checkbox' id='ewww_image_optimizer_jpg_to_png' name='ewww_image_optimizer_jpg_to_png' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_to_png' ) == true ? "checked='true'" : '' ) . ' /> <b>' . esc_html__( 'WARNING:', 'ewww-image-optimizer' ) . '</b> ' . esc_html__( 'Removes metadata and increases cpu usage dramatically.', 'ewww-image-optimizer' ) . "</span>\n" .
7601
+ "<p class='description'>" . esc_html__( 'PNG is generally much better than JPG for logos and other images with a limited range of colors. Checking this option will slow down JPG processing significantly, and you may want to enable it only temporarily.', 'ewww-image-optimizer' ) . "</p></td></tr>\n";
7602
+ ewwwio_debug_message( 'jpg2png: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_to_png' ) == true ? 'on' : 'off' ) );
7603
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_png_to_jpg'>" .
7604
+ /* translators: 1: JPG, GIF or PNG 2: JPG or PNG */
7605
+ sprintf( esc_html__( '%1$s to %2$s Conversion', 'ewww-image-optimizer' ), 'PNG', 'JPG' ) .
7606
+ '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/14-converting-images', '58545a86c697912ffd6c1b53,58543c69c697912ffd6c19a7,58542afac697912ffd6c18c0' ) . "</th><td><span><input type='checkbox' id='ewww_image_optimizer_png_to_jpg' name='ewww_image_optimizer_png_to_jpg' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_to_jpg' ) == true ? "checked='true'" : '' ) . ' /> <b>' . esc_html__( 'WARNING:', 'ewww-image-optimizer' ) . '</b> ' . esc_html__( 'This is not a lossless conversion.', 'ewww-image-optimizer' ) . "</span>\n" .
7607
+ "<p class='description'>" . esc_html__( 'JPG is generally much better than PNG for photographic use because it compresses the image and discards data. PNGs with transparency are not converted by default.', 'ewww-image-optimizer' ) . "</p>\n" .
7608
+ "<span><label for='ewww_image_optimizer_jpg_background'> " . esc_html__( 'JPG Background Color:', 'ewww-image-optimizer' ) . "</label> #<input type='text' id='ewww_image_optimizer_jpg_background' name='ewww_image_optimizer_jpg_background' size='6' value='" . ewww_image_optimizer_jpg_background() . "' /> <span style='padding-left: 12px; font-size: 12px; border: solid 1px #555555; background-color: #" . ewww_image_optimizer_jpg_background() . "'>&nbsp;</span> " . esc_html__( 'HEX format (#123def)', 'ewww-image-optimizer' ) . ".</span>\n" .
7609
+ "<p class='description'>" . esc_html__( 'Background color is used only if the PNG has transparency. Leave this value blank to skip PNGs with transparency.', 'ewww-image-optimizer' ) . "</p></td></tr>\n";
7610
+ ewwwio_debug_message( 'png2jpg: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_to_jpg' ) == true ? 'on' : 'off' ) );
7611
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_gif_to_png'>" .
7612
+ /* translators: 1: JPG, GIF or PNG 2: JPG or PNG */
7613
+ sprintf( esc_html__( '%1$s to %2$s Conversion', 'ewww-image-optimizer' ), 'GIF', 'PNG' ) .
7614
+ '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/14-converting-images', '58545a86c697912ffd6c1b53' ) . "</th><td><span><input type='checkbox' id='ewww_image_optimizer_gif_to_png' name='ewww_image_optimizer_gif_to_png' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_to_png' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'No warnings here, just do it.', 'ewww-image-optimizer' ) . "</span>\n" .
7615
+ "<p class='description'> " . esc_html__( 'PNG is generally better than GIF, but animated images cannot be converted.', 'ewww-image-optimizer' ) . "</p></td></tr>\n";
7616
+ ewwwio_debug_message( 'gif2png: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_to_png' ) == true ? 'on' : 'off' ) );
7617
+ } else {
7618
+ $output[] = "<tr class='$network_class'><th>&nbsp;</th><td>" .
7619
+ '<p><span style="color: #3eadc9">' . esc_html__( 'Image conversion requires one of the following PHP libraries: GD, Imagick, or GMagick.', 'ewww-image-optimizer' ) . "</span></p></td></tr>\n";
7620
+ }
7621
  $output[] = "</table>\n</div>\n";
7622
  $output[] = "<div id='ewww-webp-settings'>\n";
7623
  $output[] = "<table class='form-table'>\n";
7624
+ if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
7625
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_webp'>" . esc_html__( 'JPG/PNG to WebP', 'ewww-image-optimizer' ) . '</label>' .
7626
+ ewwwio_help_link( 'https://docs.ewww.io/article/16-ewww-io-and-webp-images', '5854745ac697912ffd6c1c89' ) .
7627
+ "</th><td><span><input type='checkbox' id='ewww_image_optimizer_webp' name='ewww_image_optimizer_webp' value='true' " .
7628
+ ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) == true ? "checked='true'" : '' ) . ' /> <b>' .
7629
+ esc_html__( 'WARNING:', 'ewww-image-optimizer' ) . '</b> ' . esc_html__( 'JPG to WebP conversion is lossy, but quality loss is minimal. PNG to WebP conversion is lossless.', 'ewww-image-optimizer' ) .
7630
+ "</span>\n<p class='description'>" . esc_html__( 'Originals are never deleted, and WebP images should only be served to supported browsers.', 'ewww-image-optimizer' ) .
7631
+ " <a href='#webp-rewrite'>" . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) ? esc_html__( 'You can use the rewrite rules below to serve WebP images with Apache.', 'ewww-image-optimizer' ) : '' ) . "</a></td></tr>\n";
7632
+ ewwwio_debug_message( 'webp conversion: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) == true ? 'on' : 'off' ) );
7633
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_webp_force'>" . esc_html__( 'Force WebP', 'ewww-image-optimizer' ) . '</label>' .
7634
+ ewwwio_help_link( 'https://docs.ewww.io/article/16-ewww-io-and-webp-images', '5854745ac697912ffd6c1c89' ) .
7635
+ "</th><td><span><input type='checkbox' id='ewww_image_optimizer_webp_force' name='ewww_image_optimizer_webp_force' value='true' " .
7636
+ ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) == true ? "checked='true'" : '' ) . ' /> ' .
7637
+ esc_html__( 'WebP images will be generated and saved for all JPG/PNG images regardless of their size. The Alternative WebP Rewriting will not check if a file exists, only that the domain matches the home url.', 'ewww-image-optimizer' ) . "</span></td></tr>\n";
7638
+ ewwwio_debug_message( 'forced webp: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) == true ? 'on' : 'off' ) );
7639
+ }
7640
  if ( ! ewww_image_optimizer_ce_webp_enabled() ) {
7641
+ if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
7642
+ $webp_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' ) ? esc_html( implode( "\n", ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' ) ) ) : '';
7643
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_webp_paths'>" . esc_html__( 'WebP URLs', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/16-ewww-io-and-webp-images', '5854745ac697912ffd6c1c89' ) . '</th><td>' . esc_html__( 'If Force WebP is enabled, enter URL patterns that should be permitted for Alternative WebP Rewriting. One pattern per line, may be partial URLs, but must include the domain name.', 'ewww-image-optimizer' ) . '<br>' .
7644
+ "<textarea id='ewww_image_optimizer_webp_paths' name='ewww_image_optimizer_webp_paths' rows='3' cols='60'>$webp_paths</textarea></td></tr>\n";
7645
+ ewwwio_debug_message( 'webp paths:' );
7646
+ ewwwio_debug_message( $webp_paths );
7647
+ }
7648
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_webp_for_cdn'>" .
7649
  esc_html__( 'Alternative WebP Rewriting', 'ewww-image-optimizer' ) .
7650
+ '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/16-ewww-io-and-webp-images', '5854745ac697912ffd6c1c89,59443d162c7d3a0747cdf9f0' ) . "</th><td><span><input type='checkbox' id='ewww_image_optimizer_webp_for_cdn' name='ewww_image_optimizer_webp_for_cdn' value='true' " .
7651
  ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) == true ? "checked='true'" : '' ) . ' /> ' .
7652
+ esc_html__( 'Use this if the Apache rewrite rules do not work, or if your images are served from a CDN.', 'ewww-image-optimizer' ) . ' ' .
7653
  /* translators: %s: Cache Enabler (link) */
7654
+ ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ? sprintf( esc_html__( 'Sites using a CDN may also use the WebP option in the %s plugin.', 'ewww-image-optimizer' ), '<a href="https://wordpress.org/plugins/cache-enabler/">Cache Enabler</a>' ) : '' ) . '</span></td></tr>';
7655
  }
7656
  ewwwio_debug_message( 'alt webp rewriting: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) == true ? 'on' : 'off' ) );
7657
  $output[] = "</table>\n</div>\n";
7710
  '<p>' . esc_html__( 'Would you like to help support development of this plugin?', 'ewww-image-optimizer' ) . "</p>\n" .
7711
  "<p><a href='https://translate.wordpress.org/projects/wp-plugins/ewww-image-optimizer/'>" . esc_html__( 'Help translate EWWW I.O.', 'ewww-image-optimizer' ) . "</a></p>\n" .
7712
  "<p><a href='https://wordpress.org/support/view/plugin-reviews/ewww-image-optimizer#postform'>" . esc_html__( 'Write a review.', 'ewww-image-optimizer' ) . "</a></p>\n" .
 
 
7713
  '<p>' . esc_html__( 'Signup for premium image optimization:', 'ewww-image-optimizer' ) . "<br>\n" .
7714
  "<a target='_blank' href='https://ewww.io/plans/'>" . esc_html__( 'Compress', 'ewww-image-optimizer' ) . "</a><br>\n" .
7715
  "<a target='_blank' href='https://ewww.io/resize/'>" . esc_html__( 'Resize', 'ewww-image-optimizer' ) . "</a></p>\n" .
7718
  "</div>\n";
7719
  ewwwio_debug_message( 'max_execution_time: ' . ini_get( 'max_execution_time' ) );
7720
  ewww_image_optimizer_stl_check();
7721
+ ewww_image_optimizer_function_exists( 'sleep', true );
 
 
 
 
 
7722
  ewwwio_check_memory_available();
7723
  if ( 'debug-silent' === $network ) {
7724
  return;
7725
  }
7726
  echo apply_filters( 'ewww_image_optimizer_settings', $output );
7727
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) && ! ewww_image_optimizer_ce_webp_enabled() ) {
7728
+ global $ewwwio_alt_webp;
7729
+ $ewwwio_alt_webp->inline_script();
7730
  }
7731
 
7732
  $help_instructions = esc_html__( 'Enable the Debugging option and refresh this page to include debugging information with your question.', 'ewww-image-optimizer' ) . ' ' .
7733
  esc_html__( 'This will allow us to assist you more quickly.', 'ewww-image-optimizer' );
7734
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7735
  global $ewww_debug;
7736
+ echo '<p style="clear:both"><b>' . esc_html__( 'Debugging Information', 'ewww-image-optimizer' ) . ':</b> <button id="ewww-copy-debug" class="button button-secondary">' . esc_html__( 'Copy', 'ewww-image-optimizer' ) . '</button>';
7737
  if ( is_file( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'debug.log' ) ) {
7738
  $debug_log_url = plugins_url( '/debug.log', __FILE__ );
7739
  echo "&emsp;<a href='$debug_log_url'>" . esc_html( 'View Debug Log', 'ewww-image-optimizer' ) . "</a> - <a href='admin.php?action=ewww_image_optimizer_delete_debug_log'>" . esc_html( 'Remove Debug Log', 'ewww-image-optimizer' ) . '</a>';
7744
  esc_html__( 'This will allow us to assist you more quickly.', 'ewww-image-optimizer' );
7745
  }
7746
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_help' ) ) {
 
7747
  $current_user = wp_get_current_user();
7748
  $help_email = $current_user->user_email;
7749
  $hs_config = array(
7842
  return $output;
7843
  }
7844
 
7845
+ /**
7846
+ * Displays a help icon linked to the docs.
7847
+ *
7848
+ * @param string $link A link to the documentation.
7849
+ * @param string $hsid The HelpScout ID for the docs article. Optional.
7850
+ * @return string An HTML hyperlink element with a help icon.
7851
+ */
7852
+ function ewwwio_help_link( $link, $hsid = '' ) {
7853
+ $help_icon = plugins_url( '/images/question-circle.png', __FILE__ );
7854
+ $beacon_attr = '';
7855
+ $link_class = 'ewww-help-icon';
7856
+ if ( strpos( $hsid, ',' ) ) {
7857
+ $beacon_attr = " data-beacon-articles='$hsid'";
7858
+ $link_class = 'ewww-help-beacon-multi';
7859
+ } elseif ( $hsid ) {
7860
+ $beacon_attr = " data-beacon-article='$hsid'";
7861
+ $link_class = 'ewww-help-beacon-single';
7862
+ }
7863
+ return "<a class='$link_class' href='$link' target='_blank' style='margin: 3px'$beacon_attr><img title='" . esc_attr__( 'Help', 'ewww-image-optimizer' ) . "' src='$help_icon'></a>";
7864
+ }
7865
+
7866
  /**
7867
  * Removes the API key currently installed.
7868
  *
8313
  $ewww_memory = '';
8314
  }
8315
  }
8316
+
8317
+ /**
8318
+ * Dumps data from any filter.
8319
+ *
8320
+ * @param mixed $var Could be anything, really.
8321
+ * @param mixed $var2 Default false. Could be anything, really.
8322
+ * @param mixed $var3 Default false. Could be anything, really.
8323
+ * @return mixed Whatever they gave us.
8324
+ */
8325
+ function ewwwio_dump_var( $var, $var2 = false, $var3 = false ) {
8326
+ if ( ! ewww_image_optimizer_function_exists( 'print_r' ) ) {
8327
+ return $var;
8328
+ }
8329
+ ewwwio_debug_message( 'dumping var' );
8330
+ ewwwio_debug_message( print_r( $var, true ) );
8331
+ ewwwio_debug_message( 'dumping var2' );
8332
+ ewwwio_debug_message( print_r( $var2, true ) );
8333
+ ewwwio_debug_message( 'dumping var3' );
8334
+ ewwwio_debug_message( print_r( $var3, true ) );
8335
+ return $var;
8336
+ }
8337
  ?>
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.2.3
18
  Author URI: https://ewww.io/
19
  License: GPLv3
20
  */
@@ -38,12 +38,6 @@ if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_TOOL_PATH' ) ) {
38
 
39
  // Check the PHP version.
40
  if ( ! defined( 'PHP_VERSION_ID' ) || PHP_VERSION_ID < 50400 ) {
41
- /**
42
- * This is the full system path to the plugin folder.
43
- *
44
- * @var string EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH
45
- */
46
- define( 'EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH', plugin_dir_path( __FILE__ ) );
47
  add_action( 'network_admin_notices', 'ewww_image_optimizer_unsupported_php' );
48
  add_action( 'admin_notices', 'ewww_image_optimizer_unsupported_php' );
49
  // Loads the plugin translations.
@@ -57,21 +51,25 @@ if ( ! defined( 'PHP_VERSION_ID' ) || PHP_VERSION_ID < 50400 ) {
57
  } elseif ( defined( 'KINSTAMU_VERSION' ) ) {
58
  add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_kinsta' );
59
  add_action( 'admin_notices', 'ewww_image_optimizer_notice_kinsta' );
 
60
  // Loads the plugin translations.
61
  add_action( 'plugins_loaded', 'ewww_image_optimizer_false_init' );
62
  } elseif ( defined( 'WPE_PLUGIN_VERSION' ) ) {
63
  add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_wpengine' );
64
  add_action( 'admin_notices', 'ewww_image_optimizer_notice_wpengine' );
 
65
  // Loads the plugin translations.
66
  add_action( 'plugins_loaded', 'ewww_image_optimizer_false_init' );
67
  } elseif ( defined( 'FLYWHEEL_CONFIG_DIR' ) ) {
68
  add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_flywheel' );
69
  add_action( 'admin_notices', 'ewww_image_optimizer_notice_flywheel' );
 
70
  // Loads the plugin translations.
71
  add_action( 'plugins_loaded', 'ewww_image_optimizer_false_init' );
72
  } elseif ( defined( 'WPNET_INIT_PLUGIN_VERSION' ) ) {
73
  add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_wpnetnz' );
74
  add_action( 'admin_notices', 'ewww_image_optimizer_notice_wpnetnz' );
 
75
  // Loads the plugin translations.
76
  add_action( 'plugins_loaded', 'ewww_image_optimizer_false_init' );
77
  } elseif ( empty( $_GET['ewwwio_disable'] ) ) {
@@ -151,7 +149,7 @@ if ( ! function_exists( 'ewww_image_optimizer_unsupported_php' ) ) {
151
  * Runs on 'plugins_loaded' to load the language files when EWWW is not loading.
152
  */
153
  function ewww_image_optimizer_false_init() {
154
- load_plugin_textdomain( 'ewww-image-optimizer', false, EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'languages/' );
155
  }
156
  }
157
 
@@ -159,26 +157,30 @@ if ( ! function_exists( 'ewww_image_optimizer_unsupported_php' ) ) {
159
  * Inform the user that only ewww-image-optimizer-cloud is permitted on WP Engine.
160
  */
161
  function ewww_image_optimizer_notice_wpengine() {
162
- echo "<div id='ewww-image-optimizer-warning-wpengine' class='error'><p>" . esc_html__( 'The regular version of the EWWW Image Optimizer plugin is not permitted on WP Engine sites. However, the cloud version has been approved by WP Engine. Please deactivate EWWW Image Optimizer and install EWWW Image Optimizer Cloud to optimize your images.', 'ewww-image-optimizer' ) . '</p></div>';
 
163
  }
164
 
165
  /**
166
  * Inform the user that only ewww-image-optimizer-cloud is permitted on Kinsta.
167
  */
168
  function ewww_image_optimizer_notice_kinsta() {
169
- echo "<div id='ewww-image-optimizer-warning-kinsta' class='error'><p>" . esc_html__( 'The regular version of the EWWW Image Optimizer plugin is not permitted on Kinsta sites. Please deactivate EWWW Image Optimizer and install EWWW Image Optimizer Cloud to optimize your images.', 'ewww-image-optimizer' ) . '</p></div>';
 
170
  }
171
 
172
  /**
173
  * Inform the user that only ewww-image-optimizer-cloud is permitted on Flywheel.
174
  */
175
  function ewww_image_optimizer_notice_flywheel() {
176
- echo "<div id='ewww-image-optimizer-warning-flywheel' class='error'><p>" . esc_html__( 'The regular version of the EWWW Image Optimizer plugin is not permitted on Flywheel sites. Please deactivate EWWW Image Optimizer and install EWWW Image Optimizer Cloud to optimize your images.', 'ewww-image-optimizer' ) . '</p></div>';
 
177
  }
178
 
179
  /**
180
  * Inform the user that only ewww-image-optimizer-cloud is permitted on WP NET (nz).
181
  */
182
  function ewww_image_optimizer_notice_wpnetnz() {
183
- echo "<div id='ewww-image-optimizer-warning-wpnetnz' class='error'><p>" . esc_html__( 'The regular version of the EWWW Image Optimizer plugin is not permitted on WP NET sites. Please deactivate EWWW Image Optimizer and install EWWW Image Optimizer Cloud to optimize your images.', 'ewww-image-optimizer' ) . '</p></div>';
 
184
  }
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.3.0
18
  Author URI: https://ewww.io/
19
  License: GPLv3
20
  */
38
 
39
  // Check the PHP version.
40
  if ( ! defined( 'PHP_VERSION_ID' ) || PHP_VERSION_ID < 50400 ) {
 
 
 
 
 
 
41
  add_action( 'network_admin_notices', 'ewww_image_optimizer_unsupported_php' );
42
  add_action( 'admin_notices', 'ewww_image_optimizer_unsupported_php' );
43
  // Loads the plugin translations.
51
  } elseif ( defined( 'KINSTAMU_VERSION' ) ) {
52
  add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_kinsta' );
53
  add_action( 'admin_notices', 'ewww_image_optimizer_notice_kinsta' );
54
+ require_once( plugin_dir_path( __FILE__ ) . 'classes/class-ewwwio-install-cloud.php' );
55
  // Loads the plugin translations.
56
  add_action( 'plugins_loaded', 'ewww_image_optimizer_false_init' );
57
  } elseif ( defined( 'WPE_PLUGIN_VERSION' ) ) {
58
  add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_wpengine' );
59
  add_action( 'admin_notices', 'ewww_image_optimizer_notice_wpengine' );
60
+ require_once( plugin_dir_path( __FILE__ ) . 'classes/class-ewwwio-install-cloud.php' );
61
  // Loads the plugin translations.
62
  add_action( 'plugins_loaded', 'ewww_image_optimizer_false_init' );
63
  } elseif ( defined( 'FLYWHEEL_CONFIG_DIR' ) ) {
64
  add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_flywheel' );
65
  add_action( 'admin_notices', 'ewww_image_optimizer_notice_flywheel' );
66
+ require_once( plugin_dir_path( __FILE__ ) . 'classes/class-ewwwio-install-cloud.php' );
67
  // Loads the plugin translations.
68
  add_action( 'plugins_loaded', 'ewww_image_optimizer_false_init' );
69
  } elseif ( defined( 'WPNET_INIT_PLUGIN_VERSION' ) ) {
70
  add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_wpnetnz' );
71
  add_action( 'admin_notices', 'ewww_image_optimizer_notice_wpnetnz' );
72
+ require_once( plugin_dir_path( __FILE__ ) . 'classes/class-ewwwio-install-cloud.php' );
73
  // Loads the plugin translations.
74
  add_action( 'plugins_loaded', 'ewww_image_optimizer_false_init' );
75
  } elseif ( empty( $_GET['ewwwio_disable'] ) ) {
149
  * Runs on 'plugins_loaded' to load the language files when EWWW is not loading.
150
  */
151
  function ewww_image_optimizer_false_init() {
152
+ load_plugin_textdomain( 'ewww-image-optimizer', false, plugin_dir_path( __FILE__ ) . 'languages/' );
153
  }
154
  }
155
 
157
  * Inform the user that only ewww-image-optimizer-cloud is permitted on WP Engine.
158
  */
159
  function ewww_image_optimizer_notice_wpengine() {
160
+ echo "<div id='ewww-image-optimizer-warning-wpengine' class='error'><p>" . esc_html__( 'The regular version of the EWWW Image Optimizer plugin is not permitted on WP Engine sites. However, the cloud version has been approved by WP Engine. Please deactivate EWWW Image Optimizer and install EWWW Image Optimizer Cloud to optimize your images.', 'ewww-image-optimizer' ) .
161
+ ' <a href="admin.php?action=ewwwio_install_cloud_plugin">' . esc_html__( 'Install now.', 'ewww-image-optimizer' ) . '</a></p></div>';
162
  }
163
 
164
  /**
165
  * Inform the user that only ewww-image-optimizer-cloud is permitted on Kinsta.
166
  */
167
  function ewww_image_optimizer_notice_kinsta() {
168
+ echo "<div id='ewww-image-optimizer-warning-kinsta' class='error'><p>" . esc_html__( 'The regular version of the EWWW Image Optimizer plugin is not permitted on Kinsta sites. Please deactivate EWWW Image Optimizer and install EWWW Image Optimizer Cloud to optimize your images.', 'ewww-image-optimizer' ) .
169
+ ' <a href="admin.php?action=ewwwio_install_cloud_plugin">' . esc_html__( 'Install now.', 'ewww-image-optimizer' ) . '</a></p></div>';
170
  }
171
 
172
  /**
173
  * Inform the user that only ewww-image-optimizer-cloud is permitted on Flywheel.
174
  */
175
  function ewww_image_optimizer_notice_flywheel() {
176
+ echo "<div id='ewww-image-optimizer-warning-flywheel' class='error'><p>" . esc_html__( 'The regular version of the EWWW Image Optimizer plugin is not permitted on Flywheel sites. Please deactivate EWWW Image Optimizer and install EWWW Image Optimizer Cloud to optimize your images.', 'ewww-image-optimizer' ) .
177
+ ' <a href="admin.php?action=ewwwio_install_cloud_plugin">' . esc_html__( 'Install now.', 'ewww-image-optimizer' ) . '</a></p></div>';
178
  }
179
 
180
  /**
181
  * Inform the user that only ewww-image-optimizer-cloud is permitted on WP NET (nz).
182
  */
183
  function ewww_image_optimizer_notice_wpnetnz() {
184
+ echo "<div id='ewww-image-optimizer-warning-wpnetnz' class='error'><p>" . esc_html__( 'The regular version of the EWWW Image Optimizer plugin is not permitted on WP NET sites. Please deactivate EWWW Image Optimizer and install EWWW Image Optimizer Cloud to optimize your images.', 'ewww-image-optimizer' ) .
185
+ ' <a href="admin.php?action=ewwwio_install_cloud_plugin">' . esc_html__( 'Install now.', 'ewww-image-optimizer' ) . '</a></p></div>';
186
  }
images/question-circle.png ADDED
Binary file
includes/eio.js CHANGED
@@ -1,5 +1,42 @@
1
  jQuery(document).ready(function($) {
2
  var ewww_error_counter = 30;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  if (!ewww_vars.scan_fail) {
4
  $('#ewww-webp-rewrite #ewww-webp-insert').click(function() {
5
  var ewww_webp_rewrite_action = 'ewww_webp_rewrite';
@@ -27,17 +64,8 @@ jQuery(document).ready(function($) {
27
  });
28
  return false;
29
  });
30
- $('#ewww-status-expand').click(function() {
31
- $('#ewww-collapsible-status').show();
32
- $('#ewww-status-expand').hide();
33
- $('#ewww-status-collapse').show();
34
- });
35
- $('#ewww-status-collapse').click(function() {
36
- $('#ewww-collapsible-status').hide();
37
- $('#ewww-status-expand').show();
38
- $('#ewww-status-collapse').hide();
39
- });
40
  $('#ewww-webp-settings').hide();
 
41
  $('#ewww-general-settings').show();
42
  $('li.ewww-general-nav').addClass('ewww-selected');
43
  if($('#ewww_image_optimizer_debug').length){
@@ -52,6 +80,7 @@ jQuery(document).ready(function($) {
52
  $('.ewww-tab a').blur();
53
  $('#ewww-webp-settings').show();
54
  $('#ewww-general-settings').hide();
 
55
  $('#ewww-optimization-settings').hide();
56
  $('#ewww-resize-settings').hide();
57
  $('#ewww-conversion-settings').hide();
@@ -62,6 +91,18 @@ jQuery(document).ready(function($) {
62
  $('.ewww-tab a').blur();
63
  $('#ewww-webp-settings').hide();
64
  $('#ewww-general-settings').show();
 
 
 
 
 
 
 
 
 
 
 
 
65
  $('#ewww-optimization-settings').hide();
66
  $('#ewww-resize-settings').hide();
67
  $('#ewww-conversion-settings').hide();
@@ -72,6 +113,7 @@ jQuery(document).ready(function($) {
72
  $('.ewww-tab a').blur();
73
  $('#ewww-webp-settings').hide();
74
  $('#ewww-general-settings').hide();
 
75
  $('#ewww-optimization-settings').show();
76
  $('#ewww-resize-settings').hide();
77
  $('#ewww-conversion-settings').hide();
@@ -82,6 +124,7 @@ jQuery(document).ready(function($) {
82
  $('.ewww-tab a').blur();
83
  $('#ewww-webp-settings').hide();
84
  $('#ewww-general-settings').hide();
 
85
  $('#ewww-optimization-settings').hide();
86
  $('#ewww-resize-settings').show();
87
  $('#ewww-conversion-settings').hide();
@@ -92,10 +135,63 @@ jQuery(document).ready(function($) {
92
  $('.ewww-tab a').blur();
93
  $('#ewww-webp-settings').hide();
94
  $('#ewww-general-settings').hide();
 
95
  $('#ewww-optimization-settings').hide();
96
  $('#ewww-resize-settings').hide();
97
  $('#ewww-conversion-settings').show();
98
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  return false;
100
  } else {
101
  $(function() {
@@ -108,6 +204,14 @@ jQuery(document).ready(function($) {
108
  }
109
  });
110
  });
 
 
 
 
 
 
 
 
111
  var ewww_attachments = ewww_vars.attachments;
112
  var ewww_i = 0;
113
  var ewww_k = 0;
@@ -142,30 +246,6 @@ jQuery(document).ready(function($) {
142
  var ewww_init_action = 'bulk_ngg_init';
143
  var ewww_loop_action = 'bulk_ngg_loop';
144
  var ewww_cleanup_action = 'bulk_ngg_cleanup';
145
- // this loads inline on the nextgen gallery management pages
146
- if (!document.getElementById('ewww-bulk-loading')) {
147
- var ewww_preview_data = {
148
- action: ewww_preview_action,
149
- ewww_inline: 1,
150
- };
151
- $.post(ajaxurl, ewww_preview_data, function(response) {
152
- $('.wrap').prepend(response);
153
- $(function() {
154
- $("#ewww-delay-slider").slider({
155
- min: 0,
156
- max: 30,
157
- value: $("#ewww-delay").val(),
158
- slide: function(event, ui) {
159
- $("#ewww-delay").val(ui.value);
160
- }
161
- });
162
- });
163
- $('#ewww-bulk-start').submit(function() {
164
- ewwwStartOpt();
165
- return false;
166
- });
167
- });
168
- }
169
  } else {
170
  var ewww_scan_action = 'bulk_scan';
171
  var ewww_init_action = 'bulk_init';
@@ -181,6 +261,10 @@ jQuery(document).ready(function($) {
181
  var ewww_table_count_action = 'bulk_aux_images_table_count';
182
  var ewww_import_init_action = 'bulk_import_init';
183
  var ewww_import_loop_action = 'bulk_import_loop';
 
 
 
 
184
  $('#ewww-aux-start').submit(function() {
185
  ewww_aux = true;
186
  //ewww_init_action = 'bulk_init';
@@ -640,3 +724,21 @@ function ewwwRestoreImage(imageID) {
640
  }
641
  });
642
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  jQuery(document).ready(function($) {
2
  var ewww_error_counter = 30;
3
+ $('#ewww-copy-debug').click(function() {
4
+ selectText('ewww-debug-info');
5
+ try {
6
+ var successful = document.execCommand('copy');
7
+ if ( successful ) {
8
+ unselectText();
9
+ }
10
+ } catch(err) {
11
+ console.log('browser cannot copy');
12
+ console.log(err);
13
+ }
14
+ });
15
+ $('.ewww-hndle').click(function() {
16
+ $(this).next('.inside').toggle();
17
+ var button = $(this).prev('.button-link');
18
+ if ('true' == button.attr('aria-expanded')) {
19
+ button.attr('aria-expanded', 'false');
20
+ button.closest('.postbox').addClass('closed');
21
+ button.children('.toggle-indicator').attr('aria-hidden', 'true');
22
+ } else {
23
+ button.attr('aria-expanded', 'true');
24
+ button.closest('.postbox').removeClass('closed');
25
+ button.children('.toggle-indicator').attr('aria-hidden', 'false');
26
+ }
27
+ });
28
+ $('.ewww-handlediv').click(function() {
29
+ $(this).parent().children('.inside').toggle();
30
+ if ('true' == $(this).attr('aria-expanded')) {
31
+ $(this).attr('aria-expanded', 'false');
32
+ $(this).closest('.postbox').addClass('closed');
33
+ $(this).children('.toggle-indicator').attr('aria-hidden', 'true');
34
+ } else {
35
+ $(this).attr('aria-expanded', 'true');
36
+ $(this).closest('.postbox').removeClass('closed');
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';
64
  });
65
  return false;
66
  });
 
 
 
 
 
 
 
 
 
 
67
  $('#ewww-webp-settings').hide();
68
+ $('#ewww-exactdn-settings').hide();
69
  $('#ewww-general-settings').show();
70
  $('li.ewww-general-nav').addClass('ewww-selected');
71
  if($('#ewww_image_optimizer_debug').length){
80
  $('.ewww-tab a').blur();
81
  $('#ewww-webp-settings').show();
82
  $('#ewww-general-settings').hide();
83
+ $('#ewww-exactdn-settings').hide();
84
  $('#ewww-optimization-settings').hide();
85
  $('#ewww-resize-settings').hide();
86
  $('#ewww-conversion-settings').hide();
91
  $('.ewww-tab a').blur();
92
  $('#ewww-webp-settings').hide();
93
  $('#ewww-general-settings').show();
94
+ $('#ewww-exactdn-settings').hide();
95
+ $('#ewww-optimization-settings').hide();
96
+ $('#ewww-resize-settings').hide();
97
+ $('#ewww-conversion-settings').hide();
98
+ });
99
+ $('.ewww-exactdn-nav').click(function() {
100
+ $('.ewww-tab-nav li').removeClass('ewww-selected');
101
+ $('li.ewww-exactdn-nav').addClass('ewww-selected');
102
+ $('.ewww-tab a').blur();
103
+ $('#ewww-webp-settings').hide();
104
+ $('#ewww-general-settings').hide();
105
+ $('#ewww-exactdn-settings').show();
106
  $('#ewww-optimization-settings').hide();
107
  $('#ewww-resize-settings').hide();
108
  $('#ewww-conversion-settings').hide();
113
  $('.ewww-tab a').blur();
114
  $('#ewww-webp-settings').hide();
115
  $('#ewww-general-settings').hide();
116
+ $('#ewww-exactdn-settings').hide();
117
  $('#ewww-optimization-settings').show();
118
  $('#ewww-resize-settings').hide();
119
  $('#ewww-conversion-settings').hide();
124
  $('.ewww-tab a').blur();
125
  $('#ewww-webp-settings').hide();
126
  $('#ewww-general-settings').hide();
127
+ $('#ewww-exactdn-settings').hide();
128
  $('#ewww-optimization-settings').hide();
129
  $('#ewww-resize-settings').show();
130
  $('#ewww-conversion-settings').hide();
135
  $('.ewww-tab a').blur();
136
  $('#ewww-webp-settings').hide();
137
  $('#ewww-general-settings').hide();
138
+ $('#ewww-exactdn-settings').hide();
139
  $('#ewww-optimization-settings').hide();
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() {
179
+ return $(this).next('.ewww-recommend').html();
180
+ },
181
+ open: function( event, ui ) {
182
+ HSregister();
183
+ },
184
+ close: function(event, ui) {
185
+ ui.tooltip.hover(function() {
186
+ $(this).stop(true).fadeTo(400, 1);
187
+ },
188
+ function() {
189
+ $(this).fadeOut('400', function() {
190
+ $(this).remove();
191
+ });
192
+ });
193
+ },
194
+ });
195
  return false;
196
  } else {
197
  $(function() {
204
  }
205
  });
206
  });
207
+ var ewwwdelayinput = document.getElementById("ewww-delay");
208
+ ewwwdelayinput.onblur = function() {
209
+ if (isNaN(this.value)) {
210
+ this.value = 0;
211
+ } else {
212
+ this.value = Math.ceil(this.value);
213
+ }
214
+ };
215
  var ewww_attachments = ewww_vars.attachments;
216
  var ewww_i = 0;
217
  var ewww_k = 0;
246
  var ewww_init_action = 'bulk_ngg_init';
247
  var ewww_loop_action = 'bulk_ngg_loop';
248
  var ewww_cleanup_action = 'bulk_ngg_cleanup';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249
  } else {
250
  var ewww_scan_action = 'bulk_scan';
251
  var ewww_init_action = 'bulk_init';
261
  var ewww_table_count_action = 'bulk_aux_images_table_count';
262
  var ewww_import_init_action = 'bulk_import_init';
263
  var ewww_import_loop_action = 'bulk_import_loop';
264
+ $(document).on('click', '.ewww-show-debug-meta', function() {
265
+ var post_id = $(this).data('id');
266
+ $('.ewww-debug-meta-' + post_id).toggle();
267
+ });
268
  $('#ewww-aux-start').submit(function() {
269
  ewww_aux = true;
270
  //ewww_init_action = 'bulk_init';
724
  }
725
  });
726
  }
727
+ function selectText(containerid) {
728
+ var debug_node = document.getElementById(containerid);
729
+ if (document.selection) {
730
+ var range = document.body.createTextRange();
731
+ range.moveToElementText(debug_node);
732
+ range.select();
733
+ } else if (window.getSelection) {
734
+ window.getSelection().selectAllChildren(debug_node);
735
+ }
736
+ }
737
+ function unselectText() {
738
+ var sel;
739
+ if ( (sel = document.selection) && sel.empty) {
740
+ sel.empty();
741
+ } else if (window.getSelection) {
742
+ window.getSelection().removeAllRanges();
743
+ }
744
+ }
includes/flag.js CHANGED
@@ -18,54 +18,6 @@ jQuery(document).on( 'click', '.ewww-manual-optimize', function() {
18
  });
19
  return false;
20
  });
21
- /*jQuery(document).on( 'click', '.ewww-manual-convert', function() {
22
- var post_id = jQuery(this).data('id');
23
- var ewww_nonce = jQuery(this).data('nonce');
24
- var ewww_manual_optimize_data = {
25
- action: 'ewww_manual_optimize',
26
- ewww_manual_nonce: ewww_nonce,
27
- ewww_force: 1,
28
- ewww_convert: 1,
29
- ewww_attachment_ID: post_id,
30
- };
31
- jQuery('#ewww-media-status-' + post_id ).html( ewww_vars.optimizing );
32
- jQuery.post(ajaxurl, ewww_manual_optimize_data, function(response) {
33
- var ewww_manual_response = jQuery.parseJSON(response);
34
- if (ewww_manual_response.error) {
35
- jQuery('#ewww-media-status-' + post_id ).html( ewww_manual_response.error );
36
- } else if (ewww_manual_response.success) {
37
- jQuery('#ewww-media-status-' + post_id ).html( ewww_manual_response.success );
38
- }
39
- if (ewww_manual_response.basename) {
40
- var attachment_span = jQuery('#post-' + post_id + ' .column-title .filename .screen-reader-text').html();
41
- jQuery('#post-' + post_id + ' .column-title .filename').html('<span class="screen-reader-text">' + attachment_span + '</span>' + ewww_manual_response.basename);
42
- }
43
- });
44
- return false;
45
- });
46
- jQuery(document).on( 'click', '.ewww-manual-restore', function() {
47
- var post_id = jQuery(this).data('id');
48
- var ewww_nonce = jQuery(this).data('nonce');
49
- var ewww_manual_optimize_data = {
50
- action: 'ewww_manual_restore',
51
- ewww_manual_nonce: ewww_nonce,
52
- ewww_attachment_ID: post_id,
53
- };
54
- jQuery('#ewww-media-status-' + post_id ).html( ewww_vars.restoring );
55
- jQuery.post(ajaxurl, ewww_manual_optimize_data, function(response) {
56
- var ewww_manual_response = jQuery.parseJSON(response);
57
- if (ewww_manual_response.error) {
58
- jQuery('#ewww-media-status-' + post_id ).html( ewww_manual_response.error );
59
- } else if (ewww_manual_response.success) {
60
- jQuery('#ewww-media-status-' + post_id ).html( ewww_manual_response.success );
61
- }
62
- if (ewww_manual_response.basename) {
63
- var attachment_span = jQuery('#post-' + post_id + ' .column-title .filename .screen-reader-text').html();
64
- jQuery('#post-' + post_id + ' .column-title .filename').html('<span class="screen-reader-text">' + attachment_span + '</span>' + ewww_manual_response.basename);
65
- }
66
- });
67
- return false;
68
- });*/
69
  jQuery(document).on( 'click', '.ewww-manual-cloud-restore', function() {
70
  var post_id = jQuery(this).data('id');
71
  var ewww_nonce = jQuery(this).data('nonce');
@@ -85,3 +37,7 @@ jQuery(document).on( 'click', '.ewww-manual-cloud-restore', function() {
85
  });
86
  return false;
87
  });
 
 
 
 
18
  });
19
  return false;
20
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  jQuery(document).on( 'click', '.ewww-manual-cloud-restore', function() {
22
  var post_id = jQuery(this).data('id');
23
  var ewww_nonce = jQuery(this).data('nonce');
37
  });
38
  return false;
39
  });
40
+ jQuery(document).on('click', '.ewww-show-debug-meta', function() {
41
+ var post_id = jQuery(this).data('id');
42
+ jQuery('#ewww-debug-meta-' + post_id).toggle();
43
+ });
includes/jquery-ui-1.10.1.custom.css CHANGED
@@ -221,7 +221,7 @@
221
  .ui-widget-content .ui-state-default,
222
  .ui-widget-header .ui-state-default {
223
  border: 1px solid #d3d3d3;
224
- background: #e6e6e6 /*url(images/ui-bg_glass_75_e6e6e6_1x400.png)*/ 50% 50% repeat-x;
225
  font-weight: normal;
226
  color: #555555;
227
  }
@@ -238,7 +238,7 @@
238
  .ui-widget-content .ui-state-focus,
239
  .ui-widget-header .ui-state-focus {
240
  border: 1px solid #999999;
241
- background: #dadada /*url(images/ui-bg_glass_75_dadada_1x400.png)*/ 50% 50% repeat-x;
242
  font-weight: normal;
243
  color: #212121;
244
  }
@@ -253,7 +253,7 @@
253
  .ui-widget-content .ui-state-active,
254
  .ui-widget-header .ui-state-active {
255
  border: 1px solid #aaaaaa;
256
- background: #ffffff /*url(images/ui-bg_glass_65_ffffff_1x400.png)*/ 50% 50% repeat-x;
257
  font-weight: normal;
258
  color: #212121;
259
  }
@@ -316,27 +316,24 @@
316
  filter:Alpha(Opacity=35); /* For IE8 - See #6059 */
317
  }
318
  /* jQuery UI Tooltip 1.10.1 */
319
-
320
  .ui-tooltip {
321
  padding: 8px;
322
  position: absolute;
323
  z-index: 9999;
324
  max-width: 300px;
325
  min-width: 130px;
 
 
326
  }
327
-
328
  body .ui-tooltip {
329
  border-width: 1px;
330
  }
331
-
332
  .ui-tooltip, .arrow:after {
333
- border: 1px solid #d7d7d7;
334
  }
335
-
336
  .ui-tooltip {
337
  padding: 5px 10px;
338
  }
339
-
340
  .arrow {
341
  width: 70px;
342
  height: 16px;
@@ -347,16 +344,13 @@ body .ui-tooltip {
347
  bottom: -16px;
348
  z-index: 99999;
349
  }
350
-
351
  .arrow.top {
352
  top: -16px;
353
  bottom: auto;
354
  }
355
-
356
  .arrow.left {
357
  left: 20%;
358
  }
359
-
360
  .arrow:after {
361
  content: "";
362
  position: absolute;
@@ -371,12 +365,11 @@ body .ui-tooltip {
371
  -o-transform: rotate(45deg);
372
  tranform: rotate(45deg);
373
  }
374
-
375
  .arrow.top:after {
376
  bottom: -20px;
377
  top: auto;
378
  }
379
-
380
  a.removeimage, a.restoreimage {
381
  cursor: pointer;
382
  }
@@ -398,7 +391,120 @@ a.removeimage, a.restoreimage {
398
  .ewww-attachment-detail {
399
  padding: 13px 0px 0px;
400
  }
401
- .ewww-toggle {
402
- color: #0073aa;
403
- cursor:pointer;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
404
  }
221
  .ui-widget-content .ui-state-default,
222
  .ui-widget-header .ui-state-default {
223
  border: 1px solid #d3d3d3;
224
+ background: #e6e6e6 50% 50% repeat-x;
225
  font-weight: normal;
226
  color: #555555;
227
  }
238
  .ui-widget-content .ui-state-focus,
239
  .ui-widget-header .ui-state-focus {
240
  border: 1px solid #999999;
241
+ background: #dadada 50% 50% repeat-x;
242
  font-weight: normal;
243
  color: #212121;
244
  }
253
  .ui-widget-content .ui-state-active,
254
  .ui-widget-header .ui-state-active {
255
  border: 1px solid #aaaaaa;
256
+ background: #ffffff 50% 50% repeat-x;
257
  font-weight: normal;
258
  color: #212121;
259
  }
316
  filter:Alpha(Opacity=35); /* For IE8 - See #6059 */
317
  }
318
  /* jQuery UI Tooltip 1.10.1 */
 
319
  .ui-tooltip {
320
  padding: 8px;
321
  position: absolute;
322
  z-index: 9999;
323
  max-width: 300px;
324
  min-width: 130px;
325
+ border-radius: 8px;
326
+ background: #fff;
327
  }
 
328
  body .ui-tooltip {
329
  border-width: 1px;
330
  }
 
331
  .ui-tooltip, .arrow:after {
332
+ border: 1px solid #272727;
333
  }
 
334
  .ui-tooltip {
335
  padding: 5px 10px;
336
  }
 
337
  .arrow {
338
  width: 70px;
339
  height: 16px;
344
  bottom: -16px;
345
  z-index: 99999;
346
  }
 
347
  .arrow.top {
348
  top: -16px;
349
  bottom: auto;
350
  }
 
351
  .arrow.left {
352
  left: 20%;
353
  }
 
354
  .arrow:after {
355
  content: "";
356
  position: absolute;
365
  -o-transform: rotate(45deg);
366
  tranform: rotate(45deg);
367
  }
 
368
  .arrow.top:after {
369
  bottom: -20px;
370
  top: auto;
371
  }
372
+ /* media library actions and details */
373
  a.removeimage, a.restoreimage {
374
  cursor: pointer;
375
  }
391
  .ewww-attachment-detail {
392
  padding: 13px 0px 0px;
393
  }
394
+ /* bulk and settings ui */
395
+ h2.ewww-hndle {
396
+ font-size: 14px;
397
+ padding: 8px 12px;
398
+ margin: 0;
399
+ line-height: 1.4;
400
+ user-select: none;
401
+ border-bottom: 1px solid #eee;
402
+ touch-action: none;
403
+ cursor: pointer;
404
+ }
405
+ button.ewww-handlediv {
406
+ color: #72777c;
407
+ display: block;
408
+ cursor: pointer;
409
+ float: right;
410
+ width: 36px;
411
+ height: 36px;
412
+ }
413
+ .js .postbox .ewww-handlediv .toggle-indicator:before {
414
+ margin-top: 4px;
415
+ width: 20px;
416
+ border-radius: 50%;
417
+ text-indent: -1px;
418
+ }
419
+ .js .postbox.closed .ewww-handlediv .toggle-indicator:before {
420
+ content: "\f140";
421
+ }
422
+ /* optimization status section */
423
+ #ewww-status .inside {
424
+ margin: 0;
425
+ padding: 0;
426
+ }
427
+ ul.ewww-blocks {
428
+ display: flex;
429
+ list-style: none;
430
+ margin: 0;
431
+ padding: 0;
432
+ }
433
+ ul.ewww-blocks li:first-child {
434
+ border-left: 0;
435
+ }
436
+ .ewww-blocks li {
437
+ border-left: 1px solid #e2e2e2;
438
+ float: left;
439
+ margin: 0px;
440
+ padding: 0px;
441
+ }
442
+ .ewww-blocks li .ewww-status-detail {
443
+ display: block;
444
+ text-align: center;
445
+ margin: 2em;
446
+ }
447
+ .ewww-blocks li #ewww-notices {
448
+ text-align: left;
449
+ }
450
+ .ewww-guage {
451
+ position: relative;
452
+ margin: 0 auto 1rem;
453
+ padding: 0;
454
+ width: 120px;
455
+ height: 120px;
456
+ }
457
+ .ewww-guage svg {
458
+ -webkit-transform: rotate(-90deg);
459
+ transform: rotate(-90deg);
460
+ }
461
+ .ewww-inactive,
462
+ .ewww-active {
463
+ fill: none;
464
+ }
465
+ .ewww-inactive {
466
+ stroke: #e6e6e6;
467
+ }
468
+ #ewww-compress-guage .ewww-active {
469
+ stroke: #3eadc9;
470
+ stroke-linecap: round;
471
+ }
472
+ #ewww-resize-guage .ewww-active {
473
+ stroke: #1d3c71;
474
+ stroke-linecap: round;
475
+ }
476
+ #ewww-savings-guage .ewww-active {
477
+ stroke: #f26b45;
478
+ stroke-linecap: round;
479
+ }
480
+ #ewww-compress-guage .ewww-score {
481
+ color: #3eadc9;
482
+ }
483
+ #ewww-resize-guage .ewww-score {
484
+ color: #1d3c71;
485
+ }
486
+ .ewww-score {
487
+ position: absolute;
488
+ left: 50%;
489
+ top: 50%;
490
+ padding: 0;
491
+ margin: 0;
492
+ transform: translate(-50%, -50%);
493
+ font-size: 1.3rem;
494
+ font-weight: bold;
495
+ line-height: 1.5;
496
+ }
497
+ #ewww-savings-guage .ewww-score {
498
+ font-size: 1rem;
499
+ color: #f26b45;
500
+ white-space: nowrap;
501
+ }
502
+ .ewww-recommend {
503
+ display: none;
504
+ }
505
+ .ui-tooltip ul.ewww-tooltip {
506
+ list-style: disc outside none;
507
+ }
508
+ .ui-tooltip ul.ewww-tooltip li {
509
+ margin-left: 1em;
510
  }
includes/load_webp.js CHANGED
@@ -485,7 +485,7 @@ function ewww_load_images(ewww_webp_supported) {
485
  return ewww_img;
486
  }
487
  if (ewww_webp_supported) {
488
- $('.batch-image img, .image-wrapper a, .ngg-pro-masonry-item a').each(function() {
489
  var ewww_attr = $(this).attr('data-webp');
490
  if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
491
  $(this).attr('data-src', ewww_attr);
@@ -698,3 +698,87 @@ function ewww_load_images(ewww_webp_supported) {
698
  if ( typeof jQuery !== 'undefined' ) {
699
  check_webp_feature('alpha', ewww_load_images);
700
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
485
  return ewww_img;
486
  }
487
  if (ewww_webp_supported) {
488
+ $('.batch-image img, .image-wrapper a, .ngg-pro-masonry-item a, .ngg-galleria-offscreen-seo-wrapper a').each(function() {
489
  var ewww_attr = $(this).attr('data-webp');
490
  if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
491
  $(this).attr('data-src', ewww_attr);
698
  if ( typeof jQuery !== 'undefined' ) {
699
  check_webp_feature('alpha', ewww_load_images);
700
  }
701
+ var ewww_ngg_galleries_timer = 0;
702
+ var ewww_ngg_galleries = setInterval(function() {
703
+ if ( typeof galleries !== 'undefined' ) {
704
+ if ( typeof jQuery !== 'undefined' ) {
705
+ check_webp_feature('alpha', ewww_ngg_plus_parse_galleries);
706
+ clearInterval(ewww_ngg_galleries);
707
+ }
708
+ }
709
+ ewww_ngg_galleries_timer += 25;
710
+ if (ewww_ngg_galleries_timer > 1000) {
711
+ clearInterval(ewww_ngg_galleries);
712
+ }
713
+ }, 25);
714
+ function ewww_ngg_plus_parse_galleries(ewww_webp_supported) {
715
+ if (ewww_webp_supported) {
716
+ (function($) {
717
+ $.each(galleries, function(galleryIndex, gallery) {
718
+ galleries[galleryIndex].images_list = ewww_ngg_plus_parse_image_list(gallery.images_list);
719
+ });
720
+ })(jQuery);
721
+ }
722
+ }
723
+ check_webp_feature('alpha', ewww_ngg_plus_load_galleries);
724
+ function ewww_ngg_plus_load_galleries(ewww_webp_supported) {
725
+ if (ewww_webp_supported) {
726
+ (function($) {
727
+ $(window).on('ngg.galleria.themeadded', function(event, themename) {
728
+ console.log(themename);
729
+ window.ngg_galleria._create_backup = window.ngg_galleria.create;
730
+ window.ngg_galleria.create = function(gallery_parent, themename) {
731
+ var gallery_id = $(gallery_parent).data('id');
732
+ console.log(gallery_id);
733
+ galleries['gallery_' + gallery_id].images_list = ewww_ngg_plus_parse_image_list(galleries['gallery_' + gallery_id].images_list);
734
+ return window.ngg_galleria._create_backup(gallery_parent, themename);
735
+ };
736
+ });
737
+ $(window).on('override_nplModal_methods', function(e, methods) {
738
+ methods._set_events_backup = methods.set_events;
739
+ methods.set_events = function() {
740
+ $('#npl_content').bind('npl_images_ready', function(event, gallery_id) {
741
+ var cache = methods.fetch_images.gallery_image_cache[gallery_id];
742
+ cache = ewww_ngg_plus_parse_image_list(cache);
743
+ });
744
+ return methods._set_events_backup();
745
+ }
746
+ });
747
+ })(jQuery);
748
+ }
749
+ }
750
+ function ewww_ngg_plus_parse_image_list(images_list) {
751
+ (function($) {
752
+ $.each(images_list, function(nggIndex, nggImage) {
753
+ if (typeof nggImage['image-webp'] !== typeof undefined) {
754
+ images_list[nggIndex]['image'] = nggImage['image-webp'];
755
+ delete images_list[nggIndex]['image-webp'];
756
+ }
757
+ if (typeof nggImage['thumb-webp'] !== typeof undefined) {
758
+ images_list[nggIndex]['thumb'] = nggImage['thumb-webp'];
759
+ delete images_list[nggIndex]['thumb-webp'];
760
+ }
761
+ if (typeof nggImage['full_image_webp'] !== typeof undefined) {
762
+ images_list[nggIndex]['full_image'] = nggImage['full_image_webp'];
763
+ delete images_list[nggIndex]['full_image_webp'];
764
+ }
765
+ if (typeof nggImage['srcsets'] !== typeof undefined) {
766
+ $.each(nggImage['srcsets'], function(nggSrcsetIndex, nggSrcset) {
767
+ if (typeof nggImage['srcsets'][nggSrcsetIndex + '-webp'] !== typeof undefined) {
768
+ images_list[nggIndex]['srcsets'][nggSrcsetIndex] = nggImage['srcsets'][nggSrcsetIndex + '-webp'];
769
+ delete images_list[nggIndex]['srcsets'][nggSrcsetIndex + '-webp'];
770
+ }
771
+ });
772
+ }
773
+ if (typeof nggImage['full_srcsets'] !== typeof undefined) {
774
+ $.each(nggImage['full_srcsets'], function(nggFSrcsetIndex, nggFSrcset) {
775
+ if (typeof nggImage['full_srcsets'][nggFSrcsetIndex + '-webp'] !== typeof undefined) {
776
+ images_list[nggIndex]['full_srcsets'][nggFSrcsetIndex] = nggImage['full_srcsets'][nggFSrcsetIndex + '-webp'];
777
+ delete images_list[nggIndex]['full_srcsets'][nggFSrcsetIndex + '-webp'];
778
+ }
779
+ });
780
+ }
781
+ });
782
+ })(jQuery);
783
+ return images_list;
784
+ }
includes/load_webp.min.js CHANGED
@@ -1 +1 @@
1
- function check_webp_feature(t,e){var a={alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"},i=!1,r=new Image;r.onload=function(){var t=r.width>0&&r.height>0;i=!0,e(t)},r.onerror=function(){i=!1,e(!1)},r.src="data:image/webp;base64,"+a[t]}function ewww_load_images(t){jQuery(document).arrive(".ewww_webp",function(){ewww_load_images(t)}),function(e){function a(t,a){for(var r=["align","alt","border","crossorigin","height","hspace","ismap","longdesc","usemap","vspace","width","accesskey","class","contenteditable","contextmenu","dir","draggable","dropzone","hidden","id","lang","spellcheck","style","tabindex","title","translate","sizes","data-caption","data-attachment-id","data-permalink","data-orig-size","data-comments-opened","data-image-meta","data-image-title","data-image-description","data-event-trigger","data-highlight-color","data-highlight-opacity","data-highlight-border-color","data-highlight-border-width","data-highlight-border-opacity","data-no-lazy","data-lazy","data-large_image_width","data-large_image_height"],n=0,o=r.length;n<o;n++){var s=e(t).attr(i+r[n]);void 0!==s&&!1!==s&&e(a).attr(r[n],s)}return a}var i="data-";t&&(e(".batch-image img, .image-wrapper a, .ngg-pro-masonry-item a").each(function(){var t=e(this).attr("data-webp");void 0!==t&&!1!==t&&e(this).attr("data-src",t),void 0!==(t=e(this).attr("data-webp-thumbnail"))&&!1!==t&&e(this).attr("data-thumbnail",t)}),e(".image-wrapper a, .ngg-pro-masonry-item a").each(function(){var t=e(this).attr("data-webp");void 0!==t&&!1!==t&&e(this).attr("href",t)}),e(".rev_slider ul li").each(function(){var t=e(this).attr("data-webp-thumb");void 0!==t&&!1!==t&&e(this).attr("data-thumb",t);for(var a=1;a<11;)void 0!==(t=e(this).attr("data-webp-param"+a))&&!1!==t&&e(this).attr("data-param"+a,t),a++}),e(".rev_slider img").each(function(){var t=e(this).attr("data-webp-lazyload");void 0!==t&&!1!==t&&e(this).attr("data-lazyload",t)}),e("div.woocommerce-product-gallery__image").each(function(){var t=e(this).attr("data-webp-thumb");void 0!==t&&!1!==t&&e(this).attr("data-thumb",t)})),e("img.ewww_webp_lazy_retina").each(function(){if(t)void 0!==(a=e(this).attr("data-srcset-webp"))&&!1!==a&&e(this).attr("data-srcset",a);else{var a=e(this).attr("data-srcset-img");void 0!==a&&!1!==a&&e(this).attr("data-srcset",a)}e(this).removeClass("ewww_webp_lazy_retina")}),e("video").each(function(){if(t)void 0!==(a=e(this).attr("data-poster-webp"))&&!1!==a&&e(this).attr("poster",a);else{var a=e(this).attr("data-poster-image");void 0!==a&&!1!==a&&e(this).attr("poster",a)}}),e("img.ewww_webp_lazy_load").each(function(){if(t)e(this).attr("data-lazy-src",e(this).attr("data-lazy-webp-src")),void 0!==(a=e(this).attr("data-srcset-webp"))&&!1!==a&&e(this).attr("srcset",a),void 0!==(a=e(this).attr("data-lazy-srcset-webp"))&&!1!==a&&e(this).attr("data-lazy-srcset",a);else{e(this).attr("data-lazy-src",e(this).attr("data-lazy-img-src"));var a=e(this).attr("data-srcset");void 0!==a&&!1!==a&&e(this).attr("srcset",a),void 0!==(a=e(this).attr("data-lazy-srcset-img"))&&!1!==a&&e(ewww_img).attr("data-lazy-srcset",a)}e(this).removeClass("ewww_webp_lazy_load")}),e(".ewww_webp_lazy_hueman").each(function(){var i=document.createElement("img");if(e(i).attr("src",e(this).attr("data-src")),t)e(i).attr("data-src",e(this).attr("data-webp-src")),void 0!==(r=e(this).attr("data-srcset-webp"))&&!1!==r&&e(i).attr("data-srcset",r);else{e(i).attr("data-src",e(this).attr("data-img"));var r=e(this).attr("data-srcset-img");void 0!==r&&!1!==r&&e(i).attr("data-srcset",r)}i=a(this,i),e(this).after(i),e(this).removeClass("ewww_webp_lazy_hueman")}),e(".ewww_webp").each(function(){var i=document.createElement("img");if(t)e(i).attr("src",e(this).attr("data-webp")),void 0!==(r=e(this).attr("data-srcset-webp"))&&!1!==r&&e(i).attr("srcset",r),void 0!==(r=e(this).attr("data-webp-orig-file"))&&!1!==r?e(i).attr("data-orig-file",r):void 0!==(r=e(this).attr("data-orig-file"))&&!1!==r&&e(i).attr("data-orig-file",r),void 0!==(r=e(this).attr("data-webp-medium-file"))&&!1!==r?e(i).attr("data-medium-file",r):void 0!==(r=e(this).attr("data-medium-file"))&&!1!==r&&e(i).attr("data-medium-file",r),void 0!==(r=e(this).attr("data-webp-large-file"))&&!1!==r?e(i).attr("data-large-file",r):void 0!==(r=e(this).attr("data-large-file"))&&!1!==r&&e(i).attr("data-large-file",r),void 0!==(r=e(this).attr("data-webp-large_image"))&&!1!==r?e(i).attr("data-large_image",r):void 0!==(r=e(this).attr("data-large_image"))&&!1!==r&&e(i).attr("data-large_image",r),void 0!==(r=e(this).attr("data-webp-src"))&&!1!==r?e(i).attr("data-src",r):void 0!==(r=e(this).attr("data-src"))&&!1!==r&&e(i).attr("data-src",r);else{e(i).attr("src",e(this).attr("data-img"));var r=e(this).attr("data-srcset-img");void 0!==r&&!1!==r&&e(i).attr("srcset",r),void 0!==(r=e(this).attr("data-orig-file"))&&!1!==r&&e(i).attr("data-orig-file",r),void 0!==(r=e(this).attr("data-medium-file"))&&!1!==r&&e(i).attr("data-medium-file",r),void 0!==(r=e(this).attr("data-large-file"))&&!1!==r&&e(i).attr("data-large-file",r),void 0!==(r=e(this).attr("data-large_image"))&&!1!==r&&e(i).attr("data-large_image",r),void 0!==(r=e(this).attr("data-src"))&&!1!==r&&e(i).attr("data-src",r)}i=a(this,i),e(this).after(i),e(this).removeClass("ewww_webp")})}(jQuery),jQuery.fn.isotope&&jQuery.fn.imagesLoaded&&(jQuery(".fusion-posts-container-infinite").imagesLoaded(function(){jQuery(".fusion-posts-container-infinite").hasClass("isotope")&&jQuery(".fusion-posts-container-infinite").isotope()}),jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").imagesLoaded(function(){jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").isotope()}))}var Arrive=function(t,e,a){"use strict";function i(t,e,a){o.addMethod(e,a,t.unbindEvent),o.addMethod(e,a,t.unbindEventWithSelectorOrCallback),o.addMethod(e,a,t.unbindEventWithSelectorAndCallback)}function r(t){t.arrive=l.bindEvent,i(l,t,"unbindArrive"),t.leave=c.bindEvent,i(c,t,"unbindLeave")}if(t.MutationObserver&&"undefined"!=typeof HTMLElement){var n=0,o=function(){var e=HTMLElement.prototype.matches||HTMLElement.prototype.webkitMatchesSelector||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelector;return{matchesSelector:function(t,a){return t instanceof HTMLElement&&e.call(t,a)},addMethod:function(t,e,a){var i=t[e];t[e]=function(){return a.length==arguments.length?a.apply(this,arguments):"function"==typeof i?i.apply(this,arguments):void 0}},callCallbacks:function(t){for(var e,a=0;e=t[a];a++)e.callback.call(e.elem)},checkChildNodesRecursively:function(t,e,a,i){for(var r,n=0;r=t[n];n++)a(r,e,i)&&i.push({callback:e.callback,elem:r}),r.childNodes.length>0&&o.checkChildNodesRecursively(r.childNodes,e,a,i)},mergeArrays:function(t,e){var a,i={};for(a in t)i[a]=t[a];for(a in e)i[a]=e[a];return i},toElementsArray:function(e){return void 0===e||"number"==typeof e.length&&e!==t||(e=[e]),e}}}(),s=function(){var t=function(){this._eventsBucket=[],this._beforeAdding=null,this._beforeRemoving=null};return t.prototype.addEvent=function(t,e,a,i){var r={target:t,selector:e,options:a,callback:i,firedElems:[]};return this._beforeAdding&&this._beforeAdding(r),this._eventsBucket.push(r),r},t.prototype.removeEvent=function(t){for(var e,a=this._eventsBucket.length-1;e=this._eventsBucket[a];a--)t(e)&&(this._beforeRemoving&&this._beforeRemoving(e),this._eventsBucket.splice(a,1))},t.prototype.beforeAdding=function(t){this._beforeAdding=t},t.prototype.beforeRemoving=function(t){this._beforeRemoving=t},t}(),d=function(e,i){var r=new s,n=this,d={fireOnAttributesModification:!1};return r.beforeAdding(function(a){var r,o=a.target;a.selector,a.callback;o!==t.document&&o!==t||(o=document.getElementsByTagName("html")[0]),r=new MutationObserver(function(t){i.call(this,t,a)});var s=e(a.options);r.observe(o,s),a.observer=r,a.me=n}),r.beforeRemoving(function(t){t.observer.disconnect()}),this.bindEvent=function(t,e,a){e=o.mergeArrays(d,e);for(var i=o.toElementsArray(this),n=0;n<i.length;n++)r.addEvent(i[n],t,e,a)},this.unbindEvent=function(){var t=o.toElementsArray(this);r.removeEvent(function(e){for(var i=0;i<t.length;i++)if(this===a||e.target===t[i])return!0;return!1})},this.unbindEventWithSelectorOrCallback=function(t){var e,i=o.toElementsArray(this),n=t;e="function"==typeof t?function(t){for(var e=0;e<i.length;e++)if((this===a||t.target===i[e])&&t.callback===n)return!0;return!1}:function(e){for(var r=0;r<i.length;r++)if((this===a||e.target===i[r])&&e.selector===t)return!0;return!1},r.removeEvent(e)},this.unbindEventWithSelectorAndCallback=function(t,e){var i=o.toElementsArray(this);r.removeEvent(function(r){for(var n=0;n<i.length;n++)if((this===a||r.target===i[n])&&r.selector===t&&r.callback===e)return!0;return!1})},this},l=new function(){function t(t,e,i){if(o.matchesSelector(t,e.selector)&&(t._id===a&&(t._id=n++),-1==e.firedElems.indexOf(t._id))){if(e.options.onceOnly){if(0!==e.firedElems.length)return;e.me.unbindEventWithSelectorAndCallback.call(e.target,e.selector,e.callback)}e.firedElems.push(t._id),i.push({callback:e.callback,elem:t})}}var e={fireOnAttributesModification:!1,onceOnly:!1,existing:!1},i=(l=new d(function(t){var e={attributes:!1,childList:!0,subtree:!0};return t.fireOnAttributesModification&&(e.attributes=!0),e},function(e,a){e.forEach(function(e){var i=e.addedNodes,r=e.target,n=[];null!==i&&i.length>0?o.checkChildNodesRecursively(i,a,t,n):"attributes"===e.type&&t(r,a,n)&&n.push({callback:a.callback,elem:node}),o.callCallbacks(n)})})).bindEvent;return l.bindEvent=function(t,a,r){void 0===r?(r=a,a=e):a=o.mergeArrays(e,a);var n=o.toElementsArray(this);if(a.existing){for(var s=[],d=0;d<n.length;d++)for(var l=n[d].querySelectorAll(t),c=0;c<l.length;c++)s.push({callback:r,elem:l[c]});if(a.onceOnly&&s.length)return r.call(s[0].elem);setTimeout(o.callCallbacks,1,s)}i.call(this,t,a,r)},l},c=new function(){function t(t,e){return o.matchesSelector(t,e.selector)}var e={},a=(c=new d(function(t){return{childList:!0,subtree:!0}},function(e,a){e.forEach(function(e){var i=e.removedNodes,r=(e.target,[]);null!==i&&i.length>0&&o.checkChildNodesRecursively(i,a,t,r),o.callCallbacks(r)})})).bindEvent;return c.bindEvent=function(t,i,r){void 0===r?(r=i,i=e):i=o.mergeArrays(e,i),a.call(this,t,i,r)},c};e&&r(e.fn),r(HTMLElement.prototype),r(NodeList.prototype),r(HTMLCollection.prototype),r(HTMLDocument.prototype),r(Window.prototype);var h={};return i(l,h,"unbindAllArrive"),i(c,h,"unbindAllLeave"),h}}(window,"undefined"==typeof jQuery?null:jQuery,void 0);"undefined"!=typeof jQuery&&check_webp_feature("alpha",ewww_load_images);
1
+ var Arrive=function(d,t,c){"use strict";if(d.MutationObserver&&"undefined"!=typeof HTMLElement){var a,e,i=0,u=(a=HTMLElement.prototype.matches||HTMLElement.prototype.webkitMatchesSelector||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelector,{matchesSelector:function(t,e){return t instanceof HTMLElement&&a.call(t,e)},addMethod:function(t,e,a){var i=t[e];t[e]=function(){return a.length==arguments.length?a.apply(this,arguments):"function"==typeof i?i.apply(this,arguments):void 0}},callCallbacks:function(t){for(var e,a=0;e=t[a];a++)e.callback.call(e.elem)},checkChildNodesRecursively:function(t,e,a,i){for(var r,n=0;r=t[n];n++)a(r,e,i)&&i.push({callback:e.callback,elem:r}),0<r.childNodes.length&&u.checkChildNodesRecursively(r.childNodes,e,a,i)},mergeArrays:function(t,e){var a,i={};for(a in t)i[a]=t[a];for(a in e)i[a]=e[a];return i},toElementsArray:function(t){return void 0===t||"number"==typeof t.length&&t!==d||(t=[t]),t}}),h=((e=function(){this._eventsBucket=[],this._beforeAdding=null,this._beforeRemoving=null}).prototype.addEvent=function(t,e,a,i){var r={target:t,selector:e,options:a,callback:i,firedElems:[]};return this._beforeAdding&&this._beforeAdding(r),this._eventsBucket.push(r),r},e.prototype.removeEvent=function(t){for(var e,a=this._eventsBucket.length-1;e=this._eventsBucket[a];a--)t(e)&&(this._beforeRemoving&&this._beforeRemoving(e),this._eventsBucket.splice(a,1))},e.prototype.beforeAdding=function(t){this._beforeAdding=t},e.prototype.beforeRemoving=function(t){this._beforeRemoving=t},e),s=function(r,n){var s=new h,o=this,l={fireOnAttributesModification:!1};return s.beforeAdding(function(e){var t,a=e.target;e.selector,e.callback;a!==d.document&&a!==d||(a=document.getElementsByTagName("html")[0]),t=new MutationObserver(function(t){n.call(this,t,e)});var i=r(e.options);t.observe(a,i),e.observer=t,e.me=o}),s.beforeRemoving(function(t){t.observer.disconnect()}),this.bindEvent=function(t,e,a){e=u.mergeArrays(l,e);for(var i=u.toElementsArray(this),r=0;r<i.length;r++)s.addEvent(i[r],t,e,a)},this.unbindEvent=function(){var a=u.toElementsArray(this);s.removeEvent(function(t){for(var e=0;e<a.length;e++)if(this===c||t.target===a[e])return!0;return!1})},this.unbindEventWithSelectorOrCallback=function(a){var t,i=u.toElementsArray(this),r=a;t="function"==typeof a?function(t){for(var e=0;e<i.length;e++)if((this===c||t.target===i[e])&&t.callback===r)return!0;return!1}:function(t){for(var e=0;e<i.length;e++)if((this===c||t.target===i[e])&&t.selector===a)return!0;return!1},s.removeEvent(t)},this.unbindEventWithSelectorAndCallback=function(a,i){var r=u.toElementsArray(this);s.removeEvent(function(t){for(var e=0;e<r.length;e++)if((this===c||t.target===r[e])&&t.selector===a&&t.callback===i)return!0;return!1})},this},r=new function(){var l={fireOnAttributesModification:!1,onceOnly:!1,existing:!1};function n(t,e,a){if(u.matchesSelector(t,e.selector)&&(t._id===c&&(t._id=i++),-1==e.firedElems.indexOf(t._id))){if(e.options.onceOnly){if(0!==e.firedElems.length)return;e.me.unbindEventWithSelectorAndCallback.call(e.target,e.selector,e.callback)}e.firedElems.push(t._id),a.push({callback:e.callback,elem:t})}}var d=(r=new s(function(t){var e={attributes:!1,childList:!0,subtree:!0};return t.fireOnAttributesModification&&(e.attributes=!0),e},function(t,r){t.forEach(function(t){var e=t.addedNodes,a=t.target,i=[];null!==e&&0<e.length?u.checkChildNodesRecursively(e,r,n,i):"attributes"===t.type&&n(a,r,i)&&i.push({callback:r.callback,elem:node}),u.callCallbacks(i)})})).bindEvent;return r.bindEvent=function(t,e,a){void 0===a?(a=e,e=l):e=u.mergeArrays(l,e);var i=u.toElementsArray(this);if(e.existing){for(var r=[],n=0;n<i.length;n++)for(var s=i[n].querySelectorAll(t),o=0;o<s.length;o++)r.push({callback:a,elem:s[o]});if(e.onceOnly&&r.length)return a.call(r[0].elem);setTimeout(u.callCallbacks,1,r)}d.call(this,t,e,a)},r},o=new function(){var i={};function r(t,e){return u.matchesSelector(t,e.selector)}var n=(o=new s(function(t){return{childList:!0,subtree:!0}},function(t,i){t.forEach(function(t){var e=t.removedNodes,a=(t.target,[]);null!==e&&0<e.length&&u.checkChildNodesRecursively(e,i,r,a),u.callCallbacks(a)})})).bindEvent;return o.bindEvent=function(t,e,a){void 0===a?(a=e,e=i):e=u.mergeArrays(i,e),n.call(this,t,e,a)},o};t&&g(t.fn),g(HTMLElement.prototype),g(NodeList.prototype),g(HTMLCollection.prototype),g(HTMLDocument.prototype),g(Window.prototype);var n={};return l(r,n,"unbindAllArrive"),l(o,n,"unbindAllLeave"),n}function l(t,e,a){u.addMethod(e,a,t.unbindEvent),u.addMethod(e,a,t.unbindEventWithSelectorOrCallback),u.addMethod(e,a,t.unbindEventWithSelectorAndCallback)}function g(t){t.arrive=r.bindEvent,l(r,t,"unbindArrive"),t.leave=o.bindEvent,l(o,t,"unbindLeave")}}(window,"undefined"==typeof jQuery?null:jQuery,void 0);function check_webp_feature(t,e){var a=new Image;a.onload=function(){var t=0<a.width&&0<a.height;!0,e(t)},a.onerror=function(){e(!1)},a.src="data:image/webp;base64,"+{alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"}[t]}function ewww_load_images(i){jQuery(document).arrive(".ewww_webp",function(){ewww_load_images(i)}),function(s){function a(t,e){for(var a=["align","alt","border","crossorigin","height","hspace","ismap","longdesc","usemap","vspace","width","accesskey","class","contenteditable","contextmenu","dir","draggable","dropzone","hidden","id","lang","spellcheck","style","tabindex","title","translate","sizes","data-caption","data-attachment-id","data-permalink","data-orig-size","data-comments-opened","data-image-meta","data-image-title","data-image-description","data-event-trigger","data-highlight-color","data-highlight-opacity","data-highlight-border-color","data-highlight-border-width","data-highlight-border-opacity","data-no-lazy","data-lazy","data-large_image_width","data-large_image_height"],i=0,r=a.length;i<r;i++){var n=s(t).attr("data-"+a[i]);void 0!==n&&!1!==n&&s(e).attr(a[i],n)}return e}i&&(s(".batch-image img, .image-wrapper a, .ngg-pro-masonry-item a, .ngg-galleria-offscreen-seo-wrapper a").each(function(){var t;void 0!==(t=s(this).attr("data-webp"))&&!1!==t&&s(this).attr("data-src",t),void 0!==(t=s(this).attr("data-webp-thumbnail"))&&!1!==t&&s(this).attr("data-thumbnail",t)}),s(".image-wrapper a, .ngg-pro-masonry-item a").each(function(){var t=s(this).attr("data-webp");void 0!==t&&!1!==t&&s(this).attr("href",t)}),s(".rev_slider ul li").each(function(){void 0!==(e=s(this).attr("data-webp-thumb"))&&!1!==e&&s(this).attr("data-thumb",e);for(var t=1;t<11;){var e;void 0!==(e=s(this).attr("data-webp-param"+t))&&!1!==e&&s(this).attr("data-param"+t,e),t++}}),s(".rev_slider img").each(function(){var t=s(this).attr("data-webp-lazyload");void 0!==t&&!1!==t&&s(this).attr("data-lazyload",t)}),s("div.woocommerce-product-gallery__image").each(function(){var t=s(this).attr("data-webp-thumb");void 0!==t&&!1!==t&&s(this).attr("data-thumb",t)})),s("img.ewww_webp_lazy_retina").each(function(){var t;i?void 0!==(t=s(this).attr("data-srcset-webp"))&&!1!==t&&s(this).attr("data-srcset",t):void 0!==(t=s(this).attr("data-srcset-img"))&&!1!==t&&s(this).attr("data-srcset",t);s(this).removeClass("ewww_webp_lazy_retina")}),s("video").each(function(){var t;i?void 0!==(t=s(this).attr("data-poster-webp"))&&!1!==t&&s(this).attr("poster",t):void 0!==(t=s(this).attr("data-poster-image"))&&!1!==t&&s(this).attr("poster",t)}),s("img.ewww_webp_lazy_load").each(function(){var t;i?(s(this).attr("data-lazy-src",s(this).attr("data-lazy-webp-src")),void 0!==(t=s(this).attr("data-srcset-webp"))&&!1!==t&&s(this).attr("srcset",t),void 0!==(t=s(this).attr("data-lazy-srcset-webp"))&&!1!==t&&s(this).attr("data-lazy-srcset",t)):(s(this).attr("data-lazy-src",s(this).attr("data-lazy-img-src")),void 0!==(t=s(this).attr("data-srcset"))&&!1!==t&&s(this).attr("srcset",t),void 0!==(t=s(this).attr("data-lazy-srcset-img"))&&!1!==t&&s(ewww_img).attr("data-lazy-srcset",t));s(this).removeClass("ewww_webp_lazy_load")}),s(".ewww_webp_lazy_hueman").each(function(){var t,e=document.createElement("img");(s(e).attr("src",s(this).attr("data-src")),i)?(s(e).attr("data-src",s(this).attr("data-webp-src")),void 0!==(t=s(this).attr("data-srcset-webp"))&&!1!==t&&s(e).attr("data-srcset",t)):(s(e).attr("data-src",s(this).attr("data-img")),void 0!==(t=s(this).attr("data-srcset-img"))&&!1!==t&&s(e).attr("data-srcset",t));e=a(this,e),s(this).after(e),s(this).removeClass("ewww_webp_lazy_hueman")}),s(".ewww_webp").each(function(){var t=document.createElement("img");if(i){if(s(t).attr("src",s(this).attr("data-webp")),void 0!==(e=s(this).attr("data-srcset-webp"))&&!1!==e&&s(t).attr("srcset",e),void 0!==(e=s(this).attr("data-webp-orig-file"))&&!1!==e)s(t).attr("data-orig-file",e);else void 0!==(e=s(this).attr("data-orig-file"))&&!1!==e&&s(t).attr("data-orig-file",e);if(void 0!==(e=s(this).attr("data-webp-medium-file"))&&!1!==e)s(t).attr("data-medium-file",e);else void 0!==(e=s(this).attr("data-medium-file"))&&!1!==e&&s(t).attr("data-medium-file",e);if(void 0!==(e=s(this).attr("data-webp-large-file"))&&!1!==e)s(t).attr("data-large-file",e);else void 0!==(e=s(this).attr("data-large-file"))&&!1!==e&&s(t).attr("data-large-file",e);if(void 0!==(e=s(this).attr("data-webp-large_image"))&&!1!==e)s(t).attr("data-large_image",e);else void 0!==(e=s(this).attr("data-large_image"))&&!1!==e&&s(t).attr("data-large_image",e);if(void 0!==(e=s(this).attr("data-webp-src"))&&!1!==e)s(t).attr("data-src",e);else void 0!==(e=s(this).attr("data-src"))&&!1!==e&&s(t).attr("data-src",e)}else{var e;s(t).attr("src",s(this).attr("data-img")),void 0!==(e=s(this).attr("data-srcset-img"))&&!1!==e&&s(t).attr("srcset",e),void 0!==(e=s(this).attr("data-orig-file"))&&!1!==e&&s(t).attr("data-orig-file",e),void 0!==(e=s(this).attr("data-medium-file"))&&!1!==e&&s(t).attr("data-medium-file",e),void 0!==(e=s(this).attr("data-large-file"))&&!1!==e&&s(t).attr("data-large-file",e),void 0!==(e=s(this).attr("data-large_image"))&&!1!==e&&s(t).attr("data-large_image",e),void 0!==(e=s(this).attr("data-src"))&&!1!==e&&s(t).attr("data-src",e)}t=a(this,t),s(this).after(t),s(this).removeClass("ewww_webp")})}(jQuery),jQuery.fn.isotope&&jQuery.fn.imagesLoaded&&(jQuery(".fusion-posts-container-infinite").imagesLoaded(function(){jQuery(".fusion-posts-container-infinite").hasClass("isotope")&&jQuery(".fusion-posts-container-infinite").isotope()}),jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").imagesLoaded(function(){jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").isotope()}))}"undefined"!=typeof jQuery&&check_webp_feature("alpha",ewww_load_images);var ewww_ngg_galleries_timer=0,ewww_ngg_galleries=setInterval(function(){"undefined"!=typeof galleries&&"undefined"!=typeof jQuery&&(check_webp_feature("alpha",ewww_ngg_plus_parse_galleries),clearInterval(ewww_ngg_galleries)),1e3<(ewww_ngg_galleries_timer+=25)&&clearInterval(ewww_ngg_galleries)},25);function ewww_ngg_plus_parse_galleries(t){t&&jQuery.each(galleries,function(t,e){galleries[t].images_list=ewww_ngg_plus_parse_image_list(e.images_list)})}function ewww_ngg_plus_load_galleries(t){var r;t&&((r=jQuery)(window).on("ngg.galleria.themeadded",function(t,e){console.log(e),window.ngg_galleria._create_backup=window.ngg_galleria.create,window.ngg_galleria.create=function(t,e){var a=r(t).data("id");return console.log(a),galleries["gallery_"+a].images_list=ewww_ngg_plus_parse_image_list(galleries["gallery_"+a].images_list),window.ngg_galleria._create_backup(t,e)}}),r(window).on("override_nplModal_methods",function(t,i){i._set_events_backup=i.set_events,i.set_events=function(){return r("#npl_content").bind("npl_images_ready",function(t,e){var a=i.fetch_images.gallery_image_cache[e];a=ewww_ngg_plus_parse_image_list(a)}),i._set_events_backup()}}))}function ewww_ngg_plus_parse_image_list(r){var t;return(t=jQuery).each(r,function(a,i){void 0!==i["image-webp"]&&(r[a].image=i["image-webp"],delete r[a]["image-webp"]),void 0!==i["thumb-webp"]&&(r[a].thumb=i["thumb-webp"],delete r[a]["thumb-webp"]),void 0!==i.full_image_webp&&(r[a].full_image=i.full_image_webp,delete r[a].full_image_webp),void 0!==i.srcsets&&t.each(i.srcsets,function(t,e){void 0!==i.srcsets[t+"-webp"]&&(r[a].srcsets[t]=i.srcsets[t+"-webp"],delete r[a].srcsets[t+"-webp"])}),void 0!==i.full_srcsets&&t.each(i.full_srcsets,function(t,e){void 0!==i.full_srcsets[t+"-webp"]&&(r[a].full_srcsets[t]=i.full_srcsets[t+"-webp"],delete r[a].full_srcsets[t+"-webp"])})}),r}check_webp_feature("alpha",ewww_ngg_plus_load_galleries);
includes/media.js CHANGED
@@ -1,4 +1,4 @@
1
- jQuery(document).on( 'click', '.ewww-manual-optimize', function() {
2
  var post_id = jQuery(this).data('id');
3
  var ewww_nonce = jQuery(this).data('nonce');
4
  var ewww_manual_optimize_data = {
@@ -18,7 +18,7 @@ jQuery(document).on( 'click', '.ewww-manual-optimize', function() {
18
  });
19
  return false;
20
  });
21
- jQuery(document).on( 'click', '.ewww-manual-convert', function() {
22
  var post_id = jQuery(this).data('id');
23
  var ewww_nonce = jQuery(this).data('nonce');
24
  var ewww_manual_optimize_data = {
@@ -43,7 +43,7 @@ jQuery(document).on( 'click', '.ewww-manual-convert', function() {
43
  });
44
  return false;
45
  });
46
- jQuery(document).on( 'click', '.ewww-manual-restore', function() {
47
  var post_id = jQuery(this).data('id');
48
  var ewww_nonce = jQuery(this).data('nonce');
49
  var ewww_manual_optimize_data = {
@@ -66,7 +66,7 @@ jQuery(document).on( 'click', '.ewww-manual-restore', function() {
66
  });
67
  return false;
68
  });
69
- jQuery(document).on( 'click', '.ewww-manual-cloud-restore', function() {
70
  var post_id = jQuery(this).data('id');
71
  var ewww_nonce = jQuery(this).data('nonce');
72
  var ewww_manual_optimize_data = {
@@ -82,10 +82,20 @@ jQuery(document).on( 'click', '.ewww-manual-cloud-restore', function() {
82
  } else if (ewww_manual_response.success) {
83
  jQuery('#ewww-media-status-' + post_id ).html( ewww_manual_response.success );
84
  }
85
- /* if (ewww_manual_response.basename) {
86
- var attachment_span = jQuery('#post-' + post_id + ' .column-title .filename .screen-reader-text').html();
87
- jQuery('#post-' + post_id + ' .column-title .filename').html('<span class="screen-reader-text">' + attachment_span + '</span>' + ewww_manual_response.basename);
88
- }*/
89
  });
90
  return false;
91
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).on('click', '.ewww-manual-optimize', function() {
2
  var post_id = jQuery(this).data('id');
3
  var ewww_nonce = jQuery(this).data('nonce');
4
  var ewww_manual_optimize_data = {
18
  });
19
  return false;
20
  });
21
+ jQuery(document).on('click', '.ewww-manual-convert', function() {
22
  var post_id = jQuery(this).data('id');
23
  var ewww_nonce = jQuery(this).data('nonce');
24
  var ewww_manual_optimize_data = {
43
  });
44
  return false;
45
  });
46
+ jQuery(document).on('click', '.ewww-manual-restore', function() {
47
  var post_id = jQuery(this).data('id');
48
  var ewww_nonce = jQuery(this).data('nonce');
49
  var ewww_manual_optimize_data = {
66
  });
67
  return false;
68
  });
69
+ jQuery(document).on('click', '.ewww-manual-cloud-restore', function() {
70
  var post_id = jQuery(this).data('id');
71
  var ewww_nonce = jQuery(this).data('nonce');
72
  var ewww_manual_optimize_data = {
82
  } else if (ewww_manual_response.success) {
83
  jQuery('#ewww-media-status-' + post_id ).html( ewww_manual_response.success );
84
  }
 
 
 
 
85
  });
86
  return false;
87
  });
88
+ jQuery(document).on('click', '.ewww-show-debug-meta', function() {
89
+ var post_id = jQuery(this).data('id');
90
+ jQuery('#ewww-debug-meta-' + post_id).toggle();
91
+ });
92
+ jQuery(document).on('click', '#ewww-image-optimizer-media-listmode .notice-dismiss', function() {
93
+ var ewww_dismiss_media_data = {
94
+ action: 'ewww_dismiss_media_notice',
95
+ };
96
+ jQuery.post(ajaxurl, ewww_dismiss_media_data, function(response) {
97
+ if (response) {
98
+ console.log(response);
99
+ }
100
+ });
101
+ });
includes/nextgen.js CHANGED
@@ -18,54 +18,6 @@ jQuery(document).on( 'click', '.ewww-manual-optimize', function() {
18
  });
19
  return false;
20
  });
21
- /*jQuery(document).on( 'click', '.ewww-manual-convert', function() {
22
- var post_id = jQuery(this).data('id');
23
- var ewww_nonce = jQuery(this).data('nonce');
24
- var ewww_manual_optimize_data = {
25
- action: 'ewww_manual_optimize',
26
- ewww_manual_nonce: ewww_nonce,
27
- ewww_force: 1,
28
- ewww_convert: 1,
29
- ewww_attachment_ID: post_id,
30
- };
31
- jQuery('#ewww-media-status-' + post_id ).html( ewww_vars.optimizing );
32
- jQuery.post(ajaxurl, ewww_manual_optimize_data, function(response) {
33
- var ewww_manual_response = jQuery.parseJSON(response);
34
- if (ewww_manual_response.error) {
35
- jQuery('#ewww-media-status-' + post_id ).html( ewww_manual_response.error );
36
- } else if (ewww_manual_response.success) {
37
- jQuery('#ewww-media-status-' + post_id ).html( ewww_manual_response.success );
38
- }
39
- if (ewww_manual_response.basename) {
40
- var attachment_span = jQuery('#post-' + post_id + ' .column-title .filename .screen-reader-text').html();
41
- jQuery('#post-' + post_id + ' .column-title .filename').html('<span class="screen-reader-text">' + attachment_span + '</span>' + ewww_manual_response.basename);
42
- }
43
- });
44
- return false;
45
- });
46
- jQuery(document).on( 'click', '.ewww-manual-restore', function() {
47
- var post_id = jQuery(this).data('id');
48
- var ewww_nonce = jQuery(this).data('nonce');
49
- var ewww_manual_optimize_data = {
50
- action: 'ewww_manual_restore',
51
- ewww_manual_nonce: ewww_nonce,
52
- ewww_attachment_ID: post_id,
53
- };
54
- jQuery('#ewww-media-status-' + post_id ).html( ewww_vars.restoring );
55
- jQuery.post(ajaxurl, ewww_manual_optimize_data, function(response) {
56
- var ewww_manual_response = jQuery.parseJSON(response);
57
- if (ewww_manual_response.error) {
58
- jQuery('#ewww-media-status-' + post_id ).html( ewww_manual_response.error );
59
- } else if (ewww_manual_response.success) {
60
- jQuery('#ewww-media-status-' + post_id ).html( ewww_manual_response.success );
61
- }
62
- if (ewww_manual_response.basename) {
63
- var attachment_span = jQuery('#post-' + post_id + ' .column-title .filename .screen-reader-text').html();
64
- jQuery('#post-' + post_id + ' .column-title .filename').html('<span class="screen-reader-text">' + attachment_span + '</span>' + ewww_manual_response.basename);
65
- }
66
- });
67
- return false;
68
- });*/
69
  jQuery(document).on( 'click', '.ewww-manual-cloud-restore', function() {
70
  var post_id = jQuery(this).data('id');
71
  var ewww_nonce = jQuery(this).data('nonce');
@@ -85,3 +37,7 @@ jQuery(document).on( 'click', '.ewww-manual-cloud-restore', function() {
85
  });
86
  return false;
87
  });
 
 
 
 
18
  });
19
  return false;
20
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  jQuery(document).on( 'click', '.ewww-manual-cloud-restore', function() {
22
  var post_id = jQuery(this).data('id');
23
  var ewww_nonce = jQuery(this).data('nonce');
37
  });
38
  return false;
39
  });
40
+ jQuery(document).on('click', '.ewww-show-debug-meta', function() {
41
+ var post_id = jQuery(this).data('id');
42
+ jQuery('#ewww-debug-meta-' + post_id).toggle();
43
+ });
phpcs.ruleset.xml CHANGED
@@ -15,10 +15,10 @@
15
  <rule ref="Generic.PHP.NoSilencedErrors">
16
  <exclude name="Generic.PHP.NoSilencedErrors.Discouraged" />
17
  </rule>
18
-
19
  <rule ref="WordPress.NamingConventions.ValidVariableName">
20
  <properties>
21
- <property name="customPropertiesWhitelist" type="array" value="formatOutput,parentNode,nextSibling,documentElement,imagePath,webimagePath,thumbPath,fileName,Version,Name" />
22
  </properties>
23
  <properties>
24
  <property name="customVariablesWhitelist" type="array" value="formatOutput,parentNode,nextSibling,documentElement" />
15
  <rule ref="Generic.PHP.NoSilencedErrors">
16
  <exclude name="Generic.PHP.NoSilencedErrors.Discouraged" />
17
  </rule>
18
+
19
  <rule ref="WordPress.NamingConventions.ValidVariableName">
20
  <properties>
21
+ <property name="customPropertiesWhitelist" type="array" value="formatOutput,imgQuality,parentNode,nextSibling,documentElement,imagePath,webimagePath,thumbPath,fileName,Version,Name" />
22
  </properties>
23
  <properties>
24
  <property name="customVariablesWhitelist" type="array" value="formatOutput,parentNode,nextSibling,documentElement" />
readme.txt CHANGED
@@ -1,11 +1,11 @@
1
  === EWWW Image Optimizer ===
2
  Contributors: nosilver4u
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MKMQKCBFFG3WW
4
- Tags: image, compress, optimize, optimization, lossless, lossy, seo, tinyjpg, tinypng, webp, wp-cli
5
  Requires at least: 4.6
6
  Tested up to: 4.9
7
  Requires PHP: 5.4
8
- Stable tag: 4.2.3
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.
@@ -34,11 +34,11 @@ If you need a version of this plugin for API use only, see [EWWW Image Optimizer
34
 
35
  = Automatic Resizing =
36
 
37
- With ExactDN support, images will be automatically resized to fit the page and device size. ExactDN also enables basic retina support and automatic lossless compression.
38
 
39
  = Support =
40
 
41
- If you need assistance using the plugin, please visit our [Support Page](https://ewww.io/contact-us/). The forums are community supported only.
42
  The EWWW Image Optimizer is developed at https://github.com/nosilver4u/ewww-image-optimizer
43
 
44
  = Bulk Optimize =
@@ -59,7 +59,7 @@ All images created by the built-in WP_Image_Editor class will be automatically o
59
 
60
  = WebP Images =
61
 
62
- Can generate WebP versions of your images, and enables you to serve even smaller images to supported browsers. Several methods are available for serving WebP images, including Apache-compatible rewrite rules and our Alternative WebP Rewriting option compatible with caches and CDNs. Also works with the WebP option in the Cache Enabler plugin from KeyCDN.
63
 
64
  = WP-CLI =
65
 
@@ -104,14 +104,12 @@ To receive updates when new strings are available for translation, you can signu
104
 
105
  1. Upload the "ewww-image-optimizer" plugin to your /wp-content/plugins/ directory.
106
  1. Activate the plugin through the 'Plugins' menu in WordPress.
107
- 1. Ensure jpegtran, optipng, pngout and gifsicle are installed on your Linux server (basic installation instructions are below if they are not). You will receive a warning when you activate the plugin if they are not present. This message will go away once you have them installed.
108
  1. The plugin will attempt to install jpegtran, optipng, and gifsicle automatically for you. This requires that the wp-content folder is writable by the user running the web server.
109
- 1. If the automatic install did not work, find the appropriate binaries for your system in the ewww-image-optimizer plugin folder, copy them to wp-content/ewww/ and remove the OS "tag" (like -linux or -fbsd). No renaming is necessary on Windows, just copy the .exe files to the wp-content/ewww folder. IMPORTANT: Do not symlink or modify the binaries in any way, or they will not pass the security checks. If you transfer files via FTP, be sure to transfer in binary mode, not ascii or text.
110
  1. If the binaries don't run locally, you can sign up for the EWWW IO cloud service to run them via our optimization servers: https://ewww.io/plans/
111
  1. *Recommended* Visit the settings page to enable/disable specific tools and turn on advanced optimization features.
112
  1. Done!
113
 
114
- If these steps do not work, additional documentation is available at https://docs.ewww.io. If you need further assistance using the plugin, please visit our [Support Page](https://ewww.io/contact-us/). The forums are community supported only.
115
 
116
  = Webhosts =
117
 
@@ -141,8 +139,7 @@ The lossy JPG optimization using the API will determine the ideal quality settin
141
 
142
  = The bulk optimizer doesn't seem to be working, what can I do? =
143
 
144
- If it doesn't seem to work at all, check for javascript problems using the developer console in Firefox or Chrome. If it is not working just on some images, you may need to increase the setting max_execution_time in your php.ini file. There are also other timeouts with Apache, and possibly other limitations of your webhost. If you've tried everything else, the last thing to look for is large PNG files. In my tests on a shared hosting setup, "large" is anything over 300 KB. You can first try decreasing the PNG optimization level in the settings. If that doesn't work, perhaps you ought to convert that PNG to JPG or set a max PNG optimization size. Screenshots are often done as PNG files, but that is a poor choice for anything with photographic elements.
145
- [youtube https://www.youtube.com/watch?v=vAC1SVlh7o0]
146
 
147
  = What are the supported operating systems? =
148
 
@@ -154,7 +151,7 @@ Lossless optimization is done with the command *jpegtran -copy all -optimize -pr
154
 
155
  = How are PNGs optimized? =
156
 
157
- There are three parts (and all are optional). First, using the command *pngquant original-file*, then using the commands *pngout-static -s2 original-file* and *optipng -o2 original-file*. You can adjust the optimization levels for both tools on the settings page. Optipng is an automated derivative of pngcrush, which is another widely used png optimization utility. EWWW I.O. Cloud uses TinyPNG for 10% better lossy compression than standalone pngquant.
158
 
159
  = How are GIFs optimized? =
160
 
@@ -177,6 +174,34 @@ http://developer.yahoo.com/performance/rules.html#opt_images
177
  * Feature requests can be submitted via https://ewww.io/contact-us/ and commented on here: https://trello.com/b/Fp81dWof/ewww-image-optimizer
178
  * 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/
179
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
  = 4.2.3 =
181
  * added: skip resizing for images with noresize in the filename
182
  * added: notice about plugins that remove query strings when ExactDN is active
1
  === EWWW Image Optimizer ===
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.4
8
+ Stable tag: 4.3.0
9
  License: GPLv3
10
 
11
  Speed up your website and improve your visitors' experience by automatically compressing and resizing images and PDFs. Boost SEO and improve sales.
34
 
35
  = Automatic Resizing =
36
 
37
+ With ExactDN support, images will be automatically resized to fit the page and device size. ExactDN also enables basic retina support and automatic compression.
38
 
39
  = Support =
40
 
41
+ If you need assistance using the plugin, please visit our [Support Page](https://ewww.io/contact-us/).
42
  The EWWW Image Optimizer is developed at https://github.com/nosilver4u/ewww-image-optimizer
43
 
44
  = Bulk Optimize =
59
 
60
  = WebP Images =
61
 
62
+ One-click WebP with ExactDN and Alternative WebP Rewriting. Otherwise, can generate WebP versions of your images, and enables you to serve even smaller images to supported browsers. Several methods are available for serving WebP images, including Apache-compatible rewrite rules and our Alternative WebP Rewriting option compatible with caches and CDNs. Also works with the WebP option in the Cache Enabler plugin from KeyCDN.
63
 
64
  = WP-CLI =
65
 
104
 
105
  1. Upload the "ewww-image-optimizer" plugin to your /wp-content/plugins/ directory.
106
  1. Activate the plugin through the 'Plugins' menu in WordPress.
 
107
  1. The plugin will attempt to install jpegtran, optipng, and gifsicle automatically for you. This requires that the wp-content folder is writable by the user running the web server.
 
108
  1. If the binaries don't run locally, you can sign up for the EWWW IO cloud service to run them via our optimization servers: https://ewww.io/plans/
109
  1. *Recommended* Visit the settings page to enable/disable specific tools and turn on advanced optimization features.
110
  1. Done!
111
 
112
+ If these steps do not work, additional documentation is available at https://docs.ewww.io/article/6-the-plugin-says-i-m-missing-something. If you need further assistance using the plugin, please visit our [Support Page](https://ewww.io/contact-us/).
113
 
114
  = Webhosts =
115
 
139
 
140
  = The bulk optimizer doesn't seem to be working, what can I do? =
141
 
142
+ See https://docs.ewww.io/article/39-bulk-optimizer-failure for full troubleshooting instructions.
 
143
 
144
  = What are the supported operating systems? =
145
 
151
 
152
  = How are PNGs optimized? =
153
 
154
+ There are three parts (and all are optional). First, using the command *pngquant original-file*, then using the commands *pngout-static -s2 original-file* and *optipng -o2 original-file*. You can adjust the optimization levels for both tools using the [Overrides](https://docs.ewww.io/article/40-override-options). Optipng is an automated derivative of pngcrush, which is another widely used png optimization utility.
155
 
156
  = How are GIFs optimized? =
157
 
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.3.0 =
178
+ * added: Alt WebP enables instant conversion with ExactDN, no need for bulk optimize
179
+ * added: links within settings and other notices for contextual help
180
+ * added: auto-convert large PNG images to JPG during upload, define EWWW_IMAGE_OPTIMIZER_DISABLE_AUTOCONVERT to skip
181
+ * added: use file modification time to add query strings on JS/CSS files for cache invalidation on ExactDN
182
+ * added: use EXACTDN_EXCLUDE in wp-config.php to bypass ExactDN for JS, CSS, etc.
183
+ * added: NextGEN image urls properly rewritten for ExactDN
184
+ * added: NextGEN dynamic thumbs included during manual/bulk optimization
185
+ * added: auto-installer for Cloud plugin when running EWWW IO on a "banned" webhost
186
+ * added: suggested privacy policy text for users of the API and ExactDN
187
+ * added: detect wordpress.com sites and disable exec function and binaries
188
+ * changed: resizing uses the primary media dimensions unless the "other" dimensions are configured
189
+ * changed: Resize Other Images removed from GUI, configure via Overrides tab
190
+ * changed: filter NextGEN quality to prevent oversized thumbs
191
+ * changed: allow crop via filter even when one dimension is the same as the original
192
+ * changed: auto-rotate function disabled with EWWW_IMAGE_OPTIMIZER_DISABLE_AUTOROTATE
193
+ * changed: one-click copy for debug info, and debug collapsed by default in media library and bulk results
194
+ * changed: bulk operations for batches of NextGEN images now use the bulk optimizer page instead of loading inline
195
+ * fixed: thumbs not generated during WP/LR Sync
196
+ * fixed: uploading images in the Gutenberg editor uses the wrong resize dimensions
197
+ * fixed: unique filename function producing names with a hyphen and no digits
198
+ * fixed: encoded ampersands within the path portion of a url prevent ExactDN parsing
199
+ * fixed: entering a decimal for bulk delay does nothing
200
+ * fixed: if urls on a localized WPML domain are using the default domain, ExactDN ignores them
201
+ * fixed: toggle for plugin status and bulk status generate admin-ajax.php 403 errors
202
+ * fixed: PNGOUT installer confirmation notice was missing
203
+ * deprecated: PHP 5.4 support will be removed in the next major release (version 4.4)
204
+
205
  = 4.2.3 =
206
  * added: skip resizing for images with noresize in the filename
207
  * added: notice about plugins that remove query strings when ExactDN is active
unique.php CHANGED
@@ -49,11 +49,26 @@ function ewww_image_optimizer_exec_init() {
49
  define( 'EWWW_IMAGE_OPTIMIZER_NOEXEC', true );
50
  }
51
  }
 
52
  // If cloud is fully enabled, we're going to skip all the checks related to the bundled tools.
53
  if ( EWWW_IMAGE_OPTIMIZER_CLOUD ) {
54
  ewwwio_debug_message( 'cloud options enabled, shutting off binaries' );
55
  ewww_image_optimizer_disable_tools();
56
  // Check if this is an unsupported OS (not Linux or Mac OSX or FreeBSD or Windows or SunOS).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  } elseif ( 'Linux' != PHP_OS && 'Darwin' != PHP_OS && 'FreeBSD' != PHP_OS && 'WINNT' != PHP_OS && 'SunOS' != PHP_OS ) {
58
  // Call the function to display a notice.
59
  add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_os' );
@@ -86,7 +101,7 @@ function ewww_image_optimizer_tool_init() {
86
  // Check for optimization utilities and register a notice if something is missing.
87
  add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_utils' );
88
  add_action( 'admin_notices', 'ewww_image_optimizer_notice_utils' );
89
- if ( EWWW_IMAGE_OPTIMIZER_CLOUD ) {
90
  ewwwio_debug_message( 'cloud options enabled, shutting off binaries' );
91
  ewww_image_optimizer_disable_tools();
92
  }
@@ -107,6 +122,26 @@ function ewww_image_optimizer_set_defaults() {
107
  add_site_option( 'ewww_image_optimizer_pdf_level', '0' );
108
  }
109
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  /**
111
  * Tells the user they are on an unsupported operating system.
112
  */
@@ -1562,6 +1597,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1562
  // Tell the user optimization was skipped.
1563
  return array( false, __( 'Optimization skipped', 'ewww-image-optimizer' ), $converted, $file );
1564
  }
 
1565
  global $s3_uploads_image;
1566
  if ( empty( $s3_uploads_image ) ) {
1567
  $s3_uploads_image = false;
@@ -1632,6 +1668,9 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1632
  }
1633
  return array( false, __( 'Unsupported file type', 'ewww-image-optimizer' ) . ": $type", $converted, $original );
1634
  }
 
 
 
1635
  if ( ! EWWW_IMAGE_OPTIMIZER_CLOUD ) {
1636
  ewww_image_optimizer_define_noexec();
1637
  if ( EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
@@ -1746,6 +1785,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1746
  return array( $file, $results_msg, $converted, $original );
1747
  }
1748
  }
 
1749
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) > 10 ) {
1750
  list( $file, $converted, $result, $new_size, $backup_hash ) = ewww_image_optimizer_cloud_optimizer( $file, $type, $convert, $pngfile, 'image/png', $skip_lossy );
1751
  if ( $converted ) {
@@ -2010,6 +2050,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2010
  return array( $file, $results_msg, $converted, $original );
2011
  }
2012
  }
 
2013
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) >= 20 && ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
2014
  list( $file, $converted, $result, $new_size, $backup_hash ) = ewww_image_optimizer_cloud_optimizer(
2015
  $file,
@@ -2300,6 +2341,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2300
  return array( $file, $results_msg, $converted, $original );
2301
  }
2302
  }
 
2303
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' ) == 10 ) {
2304
  list( $file, $converted, $result, $new_size, $backup_hash ) = ewww_image_optimizer_cloud_optimizer( $file, $type, $convert, $pngfile, 'image/png', $skip_lossy );
2305
  if ( $converted ) {
@@ -2441,6 +2483,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2441
  return array( $file, $results_msg, false, $original );
2442
  }
2443
  }
 
2444
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ) > 0 ) {
2445
  list( $file, $converted, $result, $new_size, $backup_hash ) = ewww_image_optimizer_cloud_optimizer( $file, $type );
2446
  }
@@ -2571,11 +2614,8 @@ function ewww_image_optimizer_install_pngout_wrapper() {
2571
  * @return string The url from whence we came (settings page), with success or error parameters added.
2572
  */
2573
  function ewww_image_optimizer_install_pngout() {
2574
- if ( PHP_OS != 'WINNT' ) {
2575
- $tar = ewww_image_optimizer_find_nix_binary( 'tar', 't' );
2576
- }
2577
- if ( empty( $tar ) && PHP_OS != 'WINNT' ) {
2578
- $pngout_error = __( 'tar command not found', 'ewww-image-optimizer' );
2579
  }
2580
  if ( PHP_OS == 'Linux' ) {
2581
  $os_string = 'linux';
@@ -2587,52 +2627,87 @@ function ewww_image_optimizer_install_pngout() {
2587
  $tool_path = trailingslashit( EWWW_IMAGE_OPTIMIZER_TOOL_PATH );
2588
  if ( empty( $pngout_error ) ) {
2589
  if ( PHP_OS == 'Linux' || PHP_OS == 'FreeBSD' ) {
2590
- $download_result = ewww_image_optimizer_escapeshellarg( download_url( 'http://static.jonof.id.au/dl/kenutils/pngout-' . $latest . '-' . $os_string . '-static.tar.gz' ) );
2591
  if ( is_wp_error( $download_result ) ) {
2592
  $pngout_error = $download_result->get_error_message();
2593
  } else {
2594
- $arch_type = 'i686';
2595
- if ( ewww_image_optimizer_function_exists( 'php_uname' ) ) {
2596
- $arch_type = php_uname( 'm' );
2597
- }
2598
- exec( "$tar xzf $download_result -C " . ewww_image_optimizer_escapeshellarg( EWWW_IMAGE_OPTIMIZER_BINARY_PATH ) . ' pngout-' . $latest . '-' . $os_string . '-static/' . $arch_type . '/pngout-static' );
2599
- if ( file_exists( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-' . $os_string . '-static/' . $arch_type . '/pngout-static' ) ) {
2600
- if ( ! rename( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-' . $os_string . '-static/' . $arch_type . '/pngout-static', $tool_path . 'pngout-static' ) ) {
2601
- if ( empty( $pngout_error ) ) {
2602
- $pngout_error = __( 'could not move pngout', 'ewww-image-optimizer' );
2603
- }
2604
  }
2605
- if ( ! chmod( $tool_path . 'pngout-static', 0755 ) ) {
2606
- if ( empty( $pngout_error ) ) {
2607
- $pngout_error = __( 'could not set permissions', 'ewww-image-optimizer' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2608
  }
 
 
 
 
 
 
 
 
2609
  }
2610
- $pngout_version = ewww_image_optimizer_tool_found( ewww_image_optimizer_escapeshellarg( $tool_path ) . 'pngout-static', 'p' );
2611
- } else {
2612
- $pngout_error = __( 'extraction of files failed', 'ewww-image-optimizer' );
2613
  }
2614
  }
2615
  }
2616
  if ( PHP_OS == 'Darwin' ) {
2617
- $download_result = ewww_image_optimizer_escapeshellarg( download_url( 'http://static.jonof.id.au/dl/kenutils/pngout-' . $latest . '-darwin.tar.gz' ) );
 
2618
  if ( is_wp_error( $download_result ) ) {
2619
  $pngout_error = $download_result->get_error_message();
2620
  } else {
2621
- exec( "$tar xzf $download_result -C " . ewww_image_optimizer_escapeshellarg( EWWW_IMAGE_OPTIMIZER_BINARY_PATH ) . ' pngout-' . $latest . '-darwin/pngout' );
2622
- if ( file_exists( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-darwin/pngout' ) ) {
2623
- if ( ! rename( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-darwin/pngout', $tool_path . 'pngout-static' ) ) {
2624
- if ( empty( $pngout_error ) ) {
2625
- $pngout_error = __( 'could not move pngout', 'ewww-image-optimizer' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2626
  }
2627
- }
2628
- if ( ! chmod( $tool_path . 'pngout-static', 0755 ) ) {
2629
- if ( empty( $pngout_error ) ) {
2630
- $pngout_error = __( 'could not set permissions', 'ewww-image-optimizer' );
2631
  }
 
 
 
2632
  }
2633
- $pngout_version = ewww_image_optimizer_tool_found( ewww_image_optimizer_escapeshellarg( $tool_path ) . 'pngout-static', 'p' );
2634
- } else {
2635
- $pngout_error = __( 'extraction of files failed', 'ewww-image-optimizer' );
2636
  }
2637
  }
2638
  }
@@ -2650,6 +2725,9 @@ function ewww_image_optimizer_install_pngout() {
2650
  $pngout_version = ewww_image_optimizer_tool_found( '"' . $tool_path . 'pngout.exe"', 'p' );
2651
  }
2652
  }
 
 
 
2653
  if ( ! empty( $pngout_version ) ) {
2654
  $sendback = add_query_arg( 'ewww_pngout', 'success', remove_query_arg( array( 'ewww_pngout', 'ewww_error' ), wp_get_referer() ) );
2655
  }
@@ -2665,6 +2743,16 @@ function ewww_image_optimizer_install_pngout() {
2665
  return $sendback;
2666
  }
2667
 
 
 
 
 
 
 
 
 
 
 
2668
  /**
2669
  * Removes any binaries that have been installed in the wp-content/ewww/ folder.
2670
  */
49
  define( 'EWWW_IMAGE_OPTIMIZER_NOEXEC', true );
50
  }
51
  }
52
+ global $exactdn;
53
  // If cloud is fully enabled, we're going to skip all the checks related to the bundled tools.
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' );
101
  // Check for optimization utilities and register a notice if something is missing.
102
  add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_utils' );
103
  add_action( 'admin_notices', 'ewww_image_optimizer_notice_utils' );
104
+ if ( defined( 'EWWW_IMAGE_OPTIMIZER_CLOUD' ) && EWWW_IMAGE_OPTIMIZER_CLOUD ) {
105
  ewwwio_debug_message( 'cloud options enabled, shutting off binaries' );
106
  ewww_image_optimizer_disable_tools();
107
  }
122
  add_site_option( 'ewww_image_optimizer_pdf_level', '0' );
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' );
132
+ }
133
+ if ( is_multisite() && is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) ) {
134
+ $options_page = 'network/settings.php';
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
+ }
144
+
145
  /**
146
  * Tells the user they are on an unsupported operating system.
147
  */
1597
  // Tell the user optimization was skipped.
1598
  return array( false, __( 'Optimization skipped', 'ewww-image-optimizer' ), $converted, $file );
1599
  }
1600
+ global $ewww_image;
1601
  global $s3_uploads_image;
1602
  if ( empty( $s3_uploads_image ) ) {
1603
  $s3_uploads_image = false;
1668
  }
1669
  return array( false, __( 'Unsupported file type', 'ewww-image-optimizer' ) . ": $type", $converted, $original );
1670
  }
1671
+ if ( ! is_object( $ewww_image ) || ! $ewww_image instanceof EWWW_Image || $ewww_image->file != $file ) {
1672
+ $ewww_image = new EWWW_Image( 0, '', $file );
1673
+ }
1674
  if ( ! EWWW_IMAGE_OPTIMIZER_CLOUD ) {
1675
  ewww_image_optimizer_define_noexec();
1676
  if ( EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
1785
  return array( $file, $results_msg, $converted, $original );
1786
  }
1787
  }
1788
+ $ewww_image->level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' );
1789
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) > 10 ) {
1790
  list( $file, $converted, $result, $new_size, $backup_hash ) = ewww_image_optimizer_cloud_optimizer( $file, $type, $convert, $pngfile, 'image/png', $skip_lossy );
1791
  if ( $converted ) {
2050
  return array( $file, $results_msg, $converted, $original );
2051
  }
2052
  }
2053
+ $ewww_image->level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' );
2054
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) >= 20 && ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
2055
  list( $file, $converted, $result, $new_size, $backup_hash ) = ewww_image_optimizer_cloud_optimizer(
2056
  $file,
2341
  return array( $file, $results_msg, $converted, $original );
2342
  }
2343
  }
2344
+ $ewww_image->level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' );
2345
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' ) == 10 ) {
2346
  list( $file, $converted, $result, $new_size, $backup_hash ) = ewww_image_optimizer_cloud_optimizer( $file, $type, $convert, $pngfile, 'image/png', $skip_lossy );
2347
  if ( $converted ) {
2483
  return array( $file, $results_msg, false, $original );
2484
  }
2485
  }
2486
+ $ewww_image->level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' );
2487
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ) > 0 ) {
2488
  list( $file, $converted, $result, $new_size, $backup_hash ) = ewww_image_optimizer_cloud_optimizer( $file, $type );
2489
  }
2614
  * @return string The url from whence we came (settings page), with success or error parameters added.
2615
  */
2616
  function ewww_image_optimizer_install_pngout() {
2617
+ if ( ! extension_loaded( 'zlib' ) || ! class_exists( 'PharData' ) ) {
2618
+ $pngout_error = __( 'zlib or phar extension missing from PHP', 'ewww-image-optimizer' );
 
 
 
2619
  }
2620
  if ( PHP_OS == 'Linux' ) {
2621
  $os_string = 'linux';
2627
  $tool_path = trailingslashit( EWWW_IMAGE_OPTIMIZER_TOOL_PATH );
2628
  if ( empty( $pngout_error ) ) {
2629
  if ( PHP_OS == 'Linux' || PHP_OS == 'FreeBSD' ) {
2630
+ $download_result = download_url( 'http://static.jonof.id.au/dl/kenutils/pngout-' . $latest . '-' . $os_string . '-static.tar.gz' );
2631
  if ( is_wp_error( $download_result ) ) {
2632
  $pngout_error = $download_result->get_error_message();
2633
  } else {
2634
+ if ( ! ewwwio_check_memory_available( filesize( $download_result ) + 1000 ) ) {
2635
+ $pngout_error = __( 'insufficient memory available for installation', 'ewww-image-optimizer' );
2636
+ } else {
2637
+ $arch_type = 'i686';
2638
+ if ( ewww_image_optimizer_function_exists( 'php_uname' ) ) {
2639
+ $arch_type = php_uname( 'm' );
 
 
 
 
2640
  }
2641
+
2642
+ $tmpname = current( explode( '.', $download_result ) );
2643
+ $tmpname .= '-' . uniqid() . '.tar.gz';
2644
+ rename( $download_result, $tmpname );
2645
+ $download_result = $tmpname;
2646
+
2647
+ $pngout_gzipped = new PharData( $download_result );
2648
+ $pngout_tarball = $pngout_gzipped->decompress();
2649
+ $download_result = $pngout_tarball->getPath();
2650
+ $pngout_tarball->extractTo(
2651
+ EWWW_IMAGE_OPTIMIZER_BINARY_PATH,
2652
+ 'pngout-' . $latest . '-' . $os_string . '-static/' . $arch_type . '/pngout-static',
2653
+ true
2654
+ );
2655
+
2656
+ if ( is_file( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-' . $os_string . '-static/' . $arch_type . '/pngout-static' ) ) {
2657
+ if ( ! rename( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-' . $os_string . '-static/' . $arch_type . '/pngout-static', $tool_path . 'pngout-static' ) ) {
2658
+ if ( empty( $pngout_error ) ) {
2659
+ $pngout_error = __( 'could not move pngout', 'ewww-image-optimizer' );
2660
+ }
2661
  }
2662
+ if ( ! chmod( $tool_path . 'pngout-static', 0755 ) ) {
2663
+ if ( empty( $pngout_error ) ) {
2664
+ $pngout_error = __( 'could not set permissions', 'ewww-image-optimizer' );
2665
+ }
2666
+ }
2667
+ $pngout_version = ewww_image_optimizer_tool_found( ewww_image_optimizer_escapeshellarg( $tool_path ) . 'pngout-static', 'p' );
2668
+ } else {
2669
+ $pngout_error = __( 'extraction of files failed', 'ewww-image-optimizer' );
2670
  }
 
 
 
2671
  }
2672
  }
2673
  }
2674
  if ( PHP_OS == 'Darwin' ) {
2675
+ $latest = '20150920';
2676
+ $download_result = download_url( 'http://static.jonof.id.au/dl/kenutils/pngout-' . $latest . '-darwin.tar.gz' );
2677
  if ( is_wp_error( $download_result ) ) {
2678
  $pngout_error = $download_result->get_error_message();
2679
  } else {
2680
+ if ( ! ewwwio_check_memory_available( filesize( $download_result ) + 1000 ) ) {
2681
+ $pngout_error = __( 'insufficient memory available for installation', 'ewww-image-optimizer' );
2682
+ } else {
2683
+ $tmpname = current( explode( '.', $download_result ) );
2684
+ $tmpname .= '-' . uniqid() . '.tar.gz';
2685
+ rename( $download_result, $tmpname );
2686
+ $download_result = $tmpname;
2687
+
2688
+ $pngout_gzipped = new PharData( $download_result );
2689
+ $pngout_tarball = $pngout_gzipped->decompress();
2690
+ $download_result = $pngout_tarball->getPath();
2691
+ $pngout_tarball->extractTo(
2692
+ EWWW_IMAGE_OPTIMIZER_BINARY_PATH,
2693
+ 'pngout-' . $latest . '-darwin/pngout',
2694
+ true
2695
+ );
2696
+ if ( is_file( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-darwin/pngout' ) ) {
2697
+ if ( ! rename( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-darwin/pngout', $tool_path . 'pngout-static' ) ) {
2698
+ if ( empty( $pngout_error ) ) {
2699
+ $pngout_error = __( 'could not move pngout', 'ewww-image-optimizer' );
2700
+ }
2701
  }
2702
+ if ( ! chmod( $tool_path . 'pngout-static', 0755 ) ) {
2703
+ if ( empty( $pngout_error ) ) {
2704
+ $pngout_error = __( 'could not set permissions', 'ewww-image-optimizer' );
2705
+ }
2706
  }
2707
+ $pngout_version = ewww_image_optimizer_tool_found( ewww_image_optimizer_escapeshellarg( $tool_path ) . 'pngout-static', 'p' );
2708
+ } else {
2709
+ $pngout_error = __( 'extraction of files failed', 'ewww-image-optimizer' );
2710
  }
 
 
 
2711
  }
2712
  }
2713
  }
2725
  $pngout_version = ewww_image_optimizer_tool_found( '"' . $tool_path . 'pngout.exe"', 'p' );
2726
  }
2727
  }
2728
+ if ( is_string( $download_result ) && is_writable( $download_result ) ) {
2729
+ unlink( $download_result );
2730
+ }
2731
  if ( ! empty( $pngout_version ) ) {
2732
  $sendback = add_query_arg( 'ewww_pngout', 'success', remove_query_arg( array( 'ewww_pngout', 'ewww_error' ), wp_get_referer() ) );
2733
  }
2743
  return $sendback;
2744
  }
2745
 
2746
+ /**
2747
+ * Downloads a file to the EWWW IO folder.
2748
+ *
2749
+ * @param string $url The remote url to fetch.
2750
+ * @return string|WP_Error The location of the downloaded file, or a WP_Error object on failure.
2751
+ */
2752
+ function ewwwio_download_url( $url ) {
2753
+ return $location;
2754
+ }
2755
+
2756
  /**
2757
  * Removes any binaries that have been installed in the wp-content/ewww/ folder.
2758
  */