EWWW Image Optimizer - Version 4.4.0

Version Description

  • added: preserve animations in GIF images during resize operations
  • added: ExactDN will fill in srcset/sizes attributes for all images based on detected width for better mobile support
  • added: configuration options in the settings page for several "hidden" ExactDN options
  • changed: Alt WebP still depends on jQuery, but jQuery can be loaded in async or defer mode
  • changed: Remove Metadata option has been renamed, if you previously had it configured as an override (JPEGTRAN_COPY), please use the new name: EWWW_IMAGE_OPTIMIZER_METADATA_REMOVE
  • changed: ExactDN uses premium compression by default
  • fixed: regression with ExactDN and max-width style attributes
  • fixed: WP esc_url mangles ExactDN urls
  • fixed: WebP images missing from S3 when using WP Offload S3
  • fixed: PDF uploads with S3 Uploads plugin
  • deprecated: PHP 5.5 support will be removed in the next major release (version 4.5)
  • removed: PHP 5.4 no longer supported
Download this release

Release Info

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

Code changes from version 4.3.2 to 4.4.0

.travis.yml CHANGED
@@ -12,7 +12,6 @@ branches:
12
  - master
13
 
14
  php:
15
- - 5.4
16
  - 5.5
17
  - 5.6
18
  - 7.0
@@ -25,7 +24,7 @@ env:
25
 
26
  matrix:
27
  include:
28
- - php: 5.4
29
  env: WP_VERSION=latest WP_MULTISITE=1
30
  - php: 7.1
31
  env: WP_VERSION=latest WP_MULTISITE=1
12
  - master
13
 
14
  php:
 
15
  - 5.5
16
  - 5.6
17
  - 7.0
24
 
25
  matrix:
26
  include:
27
+ - php: 5.5
28
  env: WP_VERSION=latest WP_MULTISITE=1
29
  - php: 7.1
30
  env: WP_VERSION=latest WP_MULTISITE=1
aux-optimize.php CHANGED
@@ -307,7 +307,8 @@ function ewww_image_optimizer_aux_images_table_count_pending_media() {
307
  function ewww_image_optimizer_delete_pending() {
308
  global $wpdb;
309
  $wpdb->query( "DELETE from $wpdb->ewwwio_images WHERE pending=1 AND (image_size IS NULL OR image_size = 0)" );
310
- $wpdb->update( $wpdb->ewwwio_images,
 
311
  array(
312
  'pending' => 0,
313
  ),
@@ -391,18 +392,26 @@ function ewww_image_optimizer_image_scan( $dir, $started = 0 ) {
391
  set_transient( 'ewww_image_optimizer_aux_iterator', $file_counter - 20, 300 ); // Keep track of where we left off, minus 20 to be safe.
392
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
393
  ewwwio_ob_clean();
394
- die( ewwwio_json_encode( array(
395
- 'remaining' => '<p>' . esc_html__( 'Stage 2, please wait.', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' /></p>",
396
- 'notice' => '',
397
- ) ) );
 
 
 
 
398
  }
399
  // TODO: can we tailor this for scheduled opt also?
400
  if ( ! empty( $_REQUEST['ewww_scan'] ) && 0 === $file_counter % 100 && ! ewwwio_check_memory_available( 2097000 ) ) {
401
  if ( $file_counter < 100 ) {
402
  ewwwio_ob_clean();
403
- die( ewwwio_json_encode( array(
404
- 'error' => esc_html__( 'Stage 2 unable to complete due to memory restrictions. Please increase the memory_limit setting for PHP and try again.', 'ewww-image-optimizer' ),
405
- ) ) );
 
 
 
 
406
  }
407
  if ( ! empty( $reset_images ) ) {
408
  array_walk( $reset_images, 'intval' );
@@ -414,10 +423,14 @@ function ewww_image_optimizer_image_scan( $dir, $started = 0 ) {
414
  set_transient( 'ewww_image_optimizer_aux_iterator', $file_counter - 20, 300 ); // Keep track of where we left off, minus 20 to be safe.
415
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
416
  ewwwio_ob_clean();
417
- die( ewwwio_json_encode( array(
418
- 'remaining' => '<p>' . esc_html__( 'Stage 2, please wait.', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' /></p>",
419
- 'notice' => '',
420
- ) ) );
 
 
 
 
421
  }
422
  $file_counter++;
423
  if ( $file->isFile() ) {
@@ -526,7 +539,8 @@ function ewww_image_optimizer_aux_images_convert() {
526
  $image_md5 = md5_file( $record['path'] );
527
  if ( $image_md5 === $record['image_md5'] ) {
528
  $filesize = filesize( $record['path'] );
529
- $wpdb->update( $wpdb->ewwwio_images,
 
530
  array(
531
  'image_md5' => null,
532
  'image_size' => $filesize,
@@ -536,7 +550,8 @@ function ewww_image_optimizer_aux_images_convert() {
536
  )
537
  );
538
  } else {
539
- $wpdb->delete( $wpdb->ewwwio_images,
 
540
  array(
541
  'id' => $record['id'],
542
  )
@@ -710,10 +725,14 @@ function ewww_image_optimizer_aux_images_script( $hook = '' ) {
710
  $ready_msg .= ' <a href="https://docs.ewww.io/article/20-why-do-i-have-so-many-images-on-my-site" target="_blank" data-beacon-article="58598744c697912ffd6c3eb4">' . esc_html__( 'Why are there so many images?', 'ewww-image-optimizer' ) . '</a>';
711
  }
712
  ewwwio_ob_clean();
713
- die( ewwwio_json_encode( array(
714
- 'ready' => $image_count,
715
- 'message' => $ready_msg,
716
- ) ) );
 
 
 
 
717
  }
718
  ewwwio_memory( __FUNCTION__ );
719
  return $image_count;
307
  function ewww_image_optimizer_delete_pending() {
308
  global $wpdb;
309
  $wpdb->query( "DELETE from $wpdb->ewwwio_images WHERE pending=1 AND (image_size IS NULL OR image_size = 0)" );
310
+ $wpdb->update(
311
+ $wpdb->ewwwio_images,
312
  array(
313
  'pending' => 0,
314
  ),
392
  set_transient( 'ewww_image_optimizer_aux_iterator', $file_counter - 20, 300 ); // Keep track of where we left off, minus 20 to be safe.
393
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
394
  ewwwio_ob_clean();
395
+ die(
396
+ ewwwio_json_encode(
397
+ array(
398
+ 'remaining' => '<p>' . esc_html__( 'Stage 2, please wait.', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' /></p>",
399
+ 'notice' => '',
400
+ )
401
+ )
402
+ );
403
  }
404
  // TODO: can we tailor this for scheduled opt also?
405
  if ( ! empty( $_REQUEST['ewww_scan'] ) && 0 === $file_counter % 100 && ! ewwwio_check_memory_available( 2097000 ) ) {
406
  if ( $file_counter < 100 ) {
407
  ewwwio_ob_clean();
408
+ die(
409
+ ewwwio_json_encode(
410
+ array(
411
+ 'error' => esc_html__( 'Stage 2 unable to complete due to memory restrictions. Please increase the memory_limit setting for PHP and try again.', 'ewww-image-optimizer' ),
412
+ )
413
+ )
414
+ );
415
  }
416
  if ( ! empty( $reset_images ) ) {
417
  array_walk( $reset_images, 'intval' );
423
  set_transient( 'ewww_image_optimizer_aux_iterator', $file_counter - 20, 300 ); // Keep track of where we left off, minus 20 to be safe.
424
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
425
  ewwwio_ob_clean();
426
+ die(
427
+ ewwwio_json_encode(
428
+ array(
429
+ 'remaining' => '<p>' . esc_html__( 'Stage 2, please wait.', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' /></p>",
430
+ 'notice' => '',
431
+ )
432
+ )
433
+ );
434
  }
435
  $file_counter++;
436
  if ( $file->isFile() ) {
539
  $image_md5 = md5_file( $record['path'] );
540
  if ( $image_md5 === $record['image_md5'] ) {
541
  $filesize = filesize( $record['path'] );
542
+ $wpdb->update(
543
+ $wpdb->ewwwio_images,
544
  array(
545
  'image_md5' => null,
546
  'image_size' => $filesize,
550
  )
551
  );
552
  } else {
553
+ $wpdb->delete(
554
+ $wpdb->ewwwio_images,
555
  array(
556
  'id' => $record['id'],
557
  )
725
  $ready_msg .= ' <a href="https://docs.ewww.io/article/20-why-do-i-have-so-many-images-on-my-site" target="_blank" data-beacon-article="58598744c697912ffd6c3eb4">' . esc_html__( 'Why are there so many images?', 'ewww-image-optimizer' ) . '</a>';
726
  }
727
  ewwwio_ob_clean();
728
+ die(
729
+ ewwwio_json_encode(
730
+ array(
731
+ 'ready' => $image_count,
732
+ 'message' => $ready_msg,
733
+ )
734
+ )
735
+ );
736
  }
737
  ewwwio_memory( __FUNCTION__ );
738
  return $image_count;
bulk.php CHANGED
@@ -456,28 +456,32 @@ function ewww_image_optimizer_bulk_script( $hook ) {
456
  $attachment_count = count( $attachments );
457
  // Submit a couple variables for our javascript to work with.
458
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
459
- wp_localize_script('ewwwbulkscript', 'ewww_vars', array(
460
- '_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-bulk' ),
461
- 'attachments' => ewww_image_optimizer_aux_images_table_count_pending(),
462
- 'image_count' => $image_count,
463
- /* translators: %d: number of images */
464
- 'count_string' => sprintf( esc_html__( '%d images', 'ewww-image-optimizer' ), $image_count ),
465
- 'scan_fail' => esc_html__( 'Operation timed out, you may need to increase the max_execution_time or memory_limit for PHP', 'ewww-image-optimizer' ),
466
- 'scan_incomplete' => esc_html__( 'Scan did not complete, will try again', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' />",
467
- 'operation_stopped' => esc_html__( 'Optimization stopped, reload page to resume.', 'ewww-image-optimizer' ),
468
- 'operation_interrupted' => esc_html__( 'Operation Interrupted', 'ewww-image-optimizer' ),
469
- 'temporary_failure' => esc_html__( 'Temporary failure, attempts remaining:', 'ewww-image-optimizer' ),
470
- 'invalid_response' => esc_html__( 'Received an invalid response from your website, please check for errors in the Developer Tools console of your browser.', 'ewww-image-optimizer' ),
471
- 'bad_attachment' => esc_html__( 'Previous failure due to broken/missing metadata, skipped resizes for attachment:', 'ewww-image-optimizer' ),
472
- 'remove_failed' => esc_html__( 'Could not remove image from table.', 'ewww-image-optimizer' ),
473
- /* translators: used for Bulk Optimize progress bar, like so: Optimized 32/346 */
474
- 'optimized' => esc_html__( 'Optimized', 'ewww-image-optimizer' ),
475
- 'last_image_header' => esc_html__( 'Last Image Optimized', 'ewww-image-optimizer' ),
476
- 'time_remaining' => esc_html__( 'remaining', 'ewww-image-optimizer' ),
477
- 'original_restored' => esc_html__( 'Original Restored', 'ewww-image-optimizer' ),
478
- 'restoring' => '<p>' . esc_html__( 'Restoring', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' /></p>",
479
- 'bulk_fail_more' => '<a href="https://docs.ewww.io/article/39-bulk-optimizer-failure" target="_blank" data-beacon-article="596f84f72c7d3a73488b3ca7">' . esc_html__( 'more...', 'ewww-image-optimizer' ) . '</a>',
480
- ) );
 
 
 
 
481
  // Load the stylesheet for the jquery progressbar.
482
  wp_enqueue_style( 'jquery-ui-progressbar', plugins_url( '/includes/jquery-ui-1.10.1.custom.css', __FILE__ ) );
483
  ewwwio_memory( __FUNCTION__ );
@@ -628,17 +632,13 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
628
  ewwwio_debug_message( 'bailing no cli' );
629
  ewww_image_optimizer_debug_log();
630
  ewwwio_ob_clean();
631
- die( ewwwio_json_encode( array(
632
- 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
633
- ) ) );
634
  }
635
  if ( ! empty( $_REQUEST['ewww_scan'] ) && ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) ) {
636
  ewwwio_debug_message( 'bailing no nonce' );
637
  ewww_image_optimizer_debug_log();
638
  ewwwio_ob_clean();
639
- die( ewwwio_json_encode( array(
640
- 'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ),
641
- ) ) );
642
  }
643
  global $wpdb;
644
  if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
@@ -737,9 +737,7 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
737
  } else {
738
  ewwwio_debug_message( 'no array found' );
739
  ewwwio_ob_clean();
740
- die( ewwwio_json_encode( array(
741
- 'error' => esc_html__( 'List of attachment IDs not found.', 'ewww-image-optimizer' ),
742
- ) ) );
743
  }
744
 
745
  $failsafe_selected_ids = $selected_ids;
@@ -896,7 +894,8 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
896
  $optimized_list[ $ims_path ] = $optimized_list[ $ims_temp_path ];
897
  ewwwio_debug_message( "updating record {$optimized_list[ $ims_temp_path ]['id']} with $ims_path" );
898
  // Update our records so that we have the correct path going forward.
899
- $ewwwdb->update( $ewwwdb->ewwwio_images,
 
900
  array(
901
  'path' => ewww_image_optimizer_relative_path_remove( $ims_path ),
902
  'updated' => $optimized_list[ $ims_temp_path ]['updated'],
@@ -1200,19 +1199,27 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
1200
  $notice = ( 'low_memory' == get_transient( 'ewww_image_optimizer_low_memory_mode' ) ? esc_html__( "Increasing PHP's memory_limit setting will allow for faster scanning with fewer database queries. Please allow up to 10 minutes for changes to memory limit to be detected.", 'ewww-image-optimizer' ) : '' );
1201
  if ( count( $attachment_ids ) ) {
1202
  ewwwio_ob_clean();
1203
- die( ewwwio_json_encode( array(
1204
- /* translators: %d: number of images */
1205
- 'remaining' => sprintf( esc_html__( 'Stage 1, %d images left to scan.', 'ewww-image-optimizer' ), count( $attachment_ids ) ) . "&nbsp;<img src='$loading_image' />",
1206
- 'notice' => $notice,
1207
- 'bad_attachment' => $bad_attachment,
1208
- ) ) );
 
 
 
 
1209
  } else {
1210
  ewwwio_ob_clean();
1211
- die( ewwwio_json_encode( array(
1212
- 'remaining' => esc_html__( 'Stage 2, please wait.', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' />",
1213
- 'notice' => $notice,
1214
- 'bad_attachment' => $bad_attachment,
1215
- ) ) );
 
 
 
 
1216
  }
1217
  }
1218
 
@@ -1242,9 +1249,7 @@ function ewww_image_optimizer_bulk_initialize() {
1242
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
1243
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
1244
  ewwwio_ob_clean();
1245
- die( ewwwio_json_encode( array(
1246
- 'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ),
1247
- ) ) );
1248
  }
1249
  session_write_close();
1250
  $output = array();
@@ -1265,16 +1270,24 @@ function ewww_image_optimizer_bulk_initialize() {
1265
  ) {
1266
  if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
1267
  ewwwio_ob_clean();
1268
- die( ewwwio_json_encode( array(
1269
- 'error' => esc_html__( 'Error retrieving list of images', 'ewww-image-optimizer' ),
1270
- 'data' => print_r( $attachments, true ),
1271
- ) ) );
 
 
 
 
1272
  } else {
1273
  ewwwio_ob_clean();
1274
- die( ewwwio_json_encode( array(
1275
- 'error' => esc_html__( 'Error retrieving list of images', 'ewww-image-optimizer' ),
1276
- 'data' => 'print_r disabled',
1277
- ) ) );
 
 
 
 
1278
  }
1279
  }
1280
  }
@@ -1477,9 +1490,7 @@ function ewww_image_optimizer_bulk_loop( $hook = '', $delay = 0 ) {
1477
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
1478
  if ( 'ewww-image-optimizer-cli' !== $hook && ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) ) {
1479
  ewwwio_ob_clean();
1480
- die( ewwwio_json_encode( array(
1481
- 'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ),
1482
- ) ) );
1483
  }
1484
  session_write_close();
1485
  // Retrieve the time when the optimizer starts.
@@ -1512,10 +1523,14 @@ function ewww_image_optimizer_bulk_loop( $hook = '', $delay = 0 ) {
1512
  $image = new EWWW_Image( $attachment, 'media' );
1513
  if ( ! $image->file ) {
1514
  ewwwio_ob_clean();
1515
- die( ewwwio_json_encode( array(
1516
- 'done' => 1,
1517
- 'completed' => 0,
1518
- ) ) );
 
 
 
 
1519
  }
1520
 
1521
  $output['results'] = '';
456
  $attachment_count = count( $attachments );
457
  // Submit a couple variables for our javascript to work with.
458
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
459
+ wp_localize_script(
460
+ 'ewwwbulkscript',
461
+ 'ewww_vars',
462
+ array(
463
+ '_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-bulk' ),
464
+ 'attachments' => ewww_image_optimizer_aux_images_table_count_pending(),
465
+ 'image_count' => $image_count,
466
+ /* translators: %d: number of images */
467
+ 'count_string' => sprintf( esc_html__( '%d images', 'ewww-image-optimizer' ), $image_count ),
468
+ 'scan_fail' => esc_html__( 'Operation timed out, you may need to increase the max_execution_time or memory_limit for PHP', 'ewww-image-optimizer' ),
469
+ 'scan_incomplete' => esc_html__( 'Scan did not complete, will try again', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' />",
470
+ 'operation_stopped' => esc_html__( 'Optimization stopped, reload page to resume.', 'ewww-image-optimizer' ),
471
+ 'operation_interrupted' => esc_html__( 'Operation Interrupted', 'ewww-image-optimizer' ),
472
+ 'temporary_failure' => esc_html__( 'Temporary failure, attempts remaining:', 'ewww-image-optimizer' ),
473
+ 'invalid_response' => esc_html__( 'Received an invalid response from your website, please check for errors in the Developer Tools console of your browser.', 'ewww-image-optimizer' ),
474
+ 'bad_attachment' => esc_html__( 'Previous failure due to broken/missing metadata, skipped resizes for attachment:', 'ewww-image-optimizer' ),
475
+ 'remove_failed' => esc_html__( 'Could not remove image from table.', 'ewww-image-optimizer' ),
476
+ /* translators: used for Bulk Optimize progress bar, like so: Optimized 32/346 */
477
+ 'optimized' => esc_html__( 'Optimized', 'ewww-image-optimizer' ),
478
+ 'last_image_header' => esc_html__( 'Last Image Optimized', 'ewww-image-optimizer' ),
479
+ 'time_remaining' => esc_html__( 'remaining', 'ewww-image-optimizer' ),
480
+ 'original_restored' => esc_html__( 'Original Restored', 'ewww-image-optimizer' ),
481
+ 'restoring' => '<p>' . esc_html__( 'Restoring', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' /></p>",
482
+ 'bulk_fail_more' => '<a href="https://docs.ewww.io/article/39-bulk-optimizer-failure" target="_blank" data-beacon-article="596f84f72c7d3a73488b3ca7">' . esc_html__( 'more...', 'ewww-image-optimizer' ) . '</a>',
483
+ )
484
+ );
485
  // Load the stylesheet for the jquery progressbar.
486
  wp_enqueue_style( 'jquery-ui-progressbar', plugins_url( '/includes/jquery-ui-1.10.1.custom.css', __FILE__ ) );
487
  ewwwio_memory( __FUNCTION__ );
632
  ewwwio_debug_message( 'bailing no cli' );
633
  ewww_image_optimizer_debug_log();
634
  ewwwio_ob_clean();
635
+ die( ewwwio_json_encode( array( 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ) ) ) );
 
 
636
  }
637
  if ( ! empty( $_REQUEST['ewww_scan'] ) && ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) ) {
638
  ewwwio_debug_message( 'bailing no nonce' );
639
  ewww_image_optimizer_debug_log();
640
  ewwwio_ob_clean();
641
+ die( ewwwio_json_encode( array( 'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) ) ) );
 
 
642
  }
643
  global $wpdb;
644
  if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
737
  } else {
738
  ewwwio_debug_message( 'no array found' );
739
  ewwwio_ob_clean();
740
+ die( ewwwio_json_encode( array( 'error' => esc_html__( 'List of attachment IDs not found.', 'ewww-image-optimizer' ) ) ) );
 
 
741
  }
742
 
743
  $failsafe_selected_ids = $selected_ids;
894
  $optimized_list[ $ims_path ] = $optimized_list[ $ims_temp_path ];
895
  ewwwio_debug_message( "updating record {$optimized_list[ $ims_temp_path ]['id']} with $ims_path" );
896
  // Update our records so that we have the correct path going forward.
897
+ $ewwwdb->update(
898
+ $ewwwdb->ewwwio_images,
899
  array(
900
  'path' => ewww_image_optimizer_relative_path_remove( $ims_path ),
901
  'updated' => $optimized_list[ $ims_temp_path ]['updated'],
1199
  $notice = ( 'low_memory' == get_transient( 'ewww_image_optimizer_low_memory_mode' ) ? esc_html__( "Increasing PHP's memory_limit setting will allow for faster scanning with fewer database queries. Please allow up to 10 minutes for changes to memory limit to be detected.", 'ewww-image-optimizer' ) : '' );
1200
  if ( count( $attachment_ids ) ) {
1201
  ewwwio_ob_clean();
1202
+ die(
1203
+ ewwwio_json_encode(
1204
+ array(
1205
+ /* translators: %d: number of images */
1206
+ 'remaining' => sprintf( esc_html__( 'Stage 1, %d images left to scan.', 'ewww-image-optimizer' ), count( $attachment_ids ) ) . "&nbsp;<img src='$loading_image' />",
1207
+ 'notice' => $notice,
1208
+ 'bad_attachment' => $bad_attachment,
1209
+ )
1210
+ )
1211
+ );
1212
  } else {
1213
  ewwwio_ob_clean();
1214
+ die(
1215
+ ewwwio_json_encode(
1216
+ array(
1217
+ 'remaining' => esc_html__( 'Stage 2, please wait.', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' />",
1218
+ 'notice' => $notice,
1219
+ 'bad_attachment' => $bad_attachment,
1220
+ )
1221
+ )
1222
+ );
1223
  }
1224
  }
1225
 
1249
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
1250
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
1251
  ewwwio_ob_clean();
1252
+ die( ewwwio_json_encode( array( 'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) ) ) );
 
 
1253
  }
1254
  session_write_close();
1255
  $output = array();
1270
  ) {
1271
  if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
1272
  ewwwio_ob_clean();
1273
+ die(
1274
+ ewwwio_json_encode(
1275
+ array(
1276
+ 'error' => esc_html__( 'Error retrieving list of images', 'ewww-image-optimizer' ),
1277
+ 'data' => print_r( $attachments, true ),
1278
+ )
1279
+ )
1280
+ );
1281
  } else {
1282
  ewwwio_ob_clean();
1283
+ die(
1284
+ ewwwio_json_encode(
1285
+ array(
1286
+ 'error' => esc_html__( 'Error retrieving list of images', 'ewww-image-optimizer' ),
1287
+ 'data' => 'print_r disabled',
1288
+ )
1289
+ )
1290
+ );
1291
  }
1292
  }
1293
  }
1490
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
1491
  if ( 'ewww-image-optimizer-cli' !== $hook && ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) ) {
1492
  ewwwio_ob_clean();
1493
+ die( ewwwio_json_encode( array( 'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) ) ) );
 
 
1494
  }
1495
  session_write_close();
1496
  // Retrieve the time when the optimizer starts.
1523
  $image = new EWWW_Image( $attachment, 'media' );
1524
  if ( ! $image->file ) {
1525
  ewwwio_ob_clean();
1526
+ die(
1527
+ ewwwio_json_encode(
1528
+ array(
1529
+ 'done' => 1,
1530
+ 'completed' => 0,
1531
+ )
1532
+ )
1533
+ );
1534
  }
1535
 
1536
  $output['results'] = '';
changelog.txt CHANGED
@@ -1,3 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  = 4.3.2 =
2
  * changed: prevent dynamic JS/CSS urls within wp-admin/ from being rewritten by ExactDN
3
  * fixed: auto-convert PNG to JPG was running on images with transparency
1
+ = 4.4.0 =
2
+ * added: preserve animations in GIF images during resize operations
3
+ * added: ExactDN will fill in srcset/sizes attributes for all images based on detected width for better mobile support
4
+ * added: configuration options in the settings page for several "hidden" ExactDN options
5
+ * changed: Alt WebP still depends on jQuery, but jQuery can be loaded in async or defer mode
6
+ * changed: Remove Metadata option has been renamed, if you previously had it configured as an override (JPEGTRAN_COPY), please use the new name: EWWW_IMAGE_OPTIMIZER_METADATA_REMOVE
7
+ * changed: ExactDN uses premium compression by default
8
+ * fixed: regression with ExactDN and max-width style attributes
9
+ * fixed: WP esc_url mangles ExactDN urls
10
+ * fixed: WebP images missing from S3 when using WP Offload S3
11
+ * fixed: PDF uploads with S3 Uploads plugin
12
+ * deprecated: PHP 5.5 support will be removed in the next major release (version 4.5)
13
+ * removed: PHP 5.4 no longer supported
14
+
15
  = 4.3.2 =
16
  * changed: prevent dynamic JS/CSS urls within wp-admin/ from being rewritten by ExactDN
17
  * fixed: auto-convert PNG to JPG was running on images with transparency
classes/class-ewww-flag.php CHANGED
@@ -246,17 +246,21 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
246
  // Add the styling for the progressbar.
247
  wp_enqueue_style( 'jquery-ui-progressbar', plugins_url( '/includes/jquery-ui-1.10.1.custom.css', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ) );
248
  // Prepare a few variables to be used by the javascript code.
249
- wp_localize_script( 'ewwwbulkscript', 'ewww_vars', array(
250
- '_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-bulk' ),
251
- 'gallery' => 'flag',
252
- 'attachments' => count( $ids ),
253
- 'scan_fail' => esc_html__( 'Operation timed out, you may need to increase the max_execution_time for PHP', 'ewww-image-optimizer' ),
254
- 'operation_stopped' => esc_html__( 'Optimization stopped, reload page to resume.', 'ewww-image-optimizer' ),
255
- 'operation_interrupted' => esc_html__( 'Operation Interrupted', 'ewww-image-optimizer' ),
256
- 'temporary_failure' => esc_html__( 'Temporary failure, seconds left to retry:', 'ewww-image-optimizer' ),
257
- 'remove_failed' => esc_html__( 'Could not remove image from table.', 'ewww-image-optimizer' ),
258
- 'optimized' => esc_html__( 'Optimized', 'ewww-image-optimizer' ),
259
- ) );
 
 
 
 
260
  }
261
 
262
  /**
@@ -275,9 +279,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
275
  $ewwwio_flag_background = new EWWWIO_Flag_Background_Process();
276
  }
277
  ewwwio_debug_message( "optimization (flagallery) queued for $image_id" );
278
- $ewwwio_flag_background->push_to_queue( array(
279
- 'id' => $image_id,
280
- ) );
281
  $ewwwio_flag_background->save()->dispatch();
282
  set_transient( 'ewwwio-background-in-progress-flag-' . $image_id, true, 24 * HOUR_IN_SECONDS );
283
  ewww_image_optimizer_debug_log();
@@ -349,7 +351,9 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
349
  * Remove the image editor filter during upload, and add a new filter that will restore it later.
350
  */
351
  function ewww_remove_image_editor() {
352
- remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
 
 
353
  add_action( 'flag_image_optimized', 'ewww_image_optimizer_restore_editor_hooks' );
354
  }
355
 
@@ -365,9 +369,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
365
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
366
  }
367
  ewwwio_ob_clean();
368
- wp_die( ewwwio_json_encode( array(
369
- 'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
370
- ) ) );
371
  }
372
  // Make sure we have an attachment ID.
373
  if ( empty( $_REQUEST['ewww_attachment_ID'] ) ) {
@@ -375,9 +377,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
375
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
376
  }
377
  ewwwio_ob_clean();
378
- wp_die( ewwwio_json_encode( array(
379
- 'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ),
380
- ) ) );
381
  }
382
  $id = intval( $_REQUEST['ewww_attachment_ID'] );
383
  if ( empty( $_REQUEST['ewww_manual_nonce'] ) || ! wp_verify_nonce( $_REQUEST['ewww_manual_nonce'], "ewww-manual-$id" ) ) {
@@ -385,9 +385,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
385
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
386
  }
387
  ewwwio_ob_clean();
388
- wp_die( ewwwio_json_encode( array(
389
- 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
390
- ) ) );
391
  }
392
  global $ewww_image;
393
  if ( ! class_exists( 'flagMeta' ) ) {
@@ -425,9 +423,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
425
  }
426
  $success = $this->ewww_manage_image_custom_column( $id );
427
  ewwwio_ob_clean();
428
- wp_die( ewwwio_json_encode( array(
429
- 'success' => $success,
430
- ) ) );
431
  }
432
 
433
  /**
@@ -442,9 +438,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
442
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
443
  }
444
  ewwwio_ob_clean();
445
- wp_die( ewwwio_json_encode( array(
446
- 'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
447
- ) ) );
448
  }
449
  // Make sure function wasn't called without an attachment to work with.
450
  if ( false === isset( $_REQUEST['ewww_attachment_ID'] ) ) {
@@ -452,9 +446,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
452
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
453
  }
454
  ewwwio_ob_clean();
455
- wp_die( ewwwio_json_encode( array(
456
- 'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ),
457
- ) ) );
458
  }
459
  // Store the attachment $id.
460
  $id = intval( $_REQUEST['ewww_attachment_ID'] );
@@ -463,9 +455,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
463
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
464
  }
465
  ewwwio_ob_clean();
466
- wp_die( ewwwio_json_encode( array(
467
- 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
468
- ) ) );
469
  }
470
  if ( ! class_exists( 'flagMeta' ) ) {
471
  require_once( FLAG_ABSPATH . 'lib/meta.php' );
@@ -473,9 +463,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
473
  ewww_image_optimizer_cloud_restore_from_meta_data( $id, 'flag' );
474
  $success = $this->ewww_manage_image_custom_column( $id );
475
  ewwwio_ob_clean();
476
- wp_die( ewwwio_json_encode( array(
477
- 'success' => $success,
478
- ) ) );
479
  }
480
 
481
  /**
@@ -753,13 +741,15 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
753
  list( $detail_output, $converted, $backup_available ) = ewww_image_optimizer_custom_column_results( $id, $optimized_images );
754
  $output .= $detail_output;
755
  if ( current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
756
- $output .= sprintf( '<a class="ewww-manual-optimize" data-id="%1$d" data-nonce="%2$s" href="admin.php?action=ewww_flag_manual&amp;ewww_manual_nonce=%2$s&amp;ewww_force=1&amp;ewww_attachment_ID=%1$d">%3$s</a>',
 
757
  $id,
758
  $ewww_manual_nonce,
759
  esc_html__( 'Re-optimize', 'ewww-image-optimizer' )
760
  );
761
  if ( $backup_available ) {
762
- $output .= sprintf( '<br><a class="ewww-manual-cloud-restore" data-id="%1$d" data-nonce="%2$s" href="admin.php?action=ewww_flag_cloud_restore&amp;ewww_manual_nonce=%2$s&amp;ewww_attachment_ID=%1$d">%3$s</a>',
 
763
  $id,
764
  $ewww_manual_nonce,
765
  esc_html__( 'Restore original', 'ewww-image-optimizer' )
@@ -771,7 +761,8 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
771
  // Otherwise, tell the user that they can optimize the image now.
772
  } else {
773
  if ( current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
774
- $output .= sprintf( '<a class="ewww-manual-optimize" data-id="%1$d" data-nonce="%2$s" href="admin.php?action=ewww_flag_manual&amp;ewww_manual_nonce=%2$s&amp;ewww_attachment_ID=%1$d">%3$s</a>',
 
775
  $id,
776
  $ewww_manual_nonce,
777
  esc_html__( 'Optimize now!', 'ewww-image-optimizer' )
246
  // Add the styling for the progressbar.
247
  wp_enqueue_style( 'jquery-ui-progressbar', plugins_url( '/includes/jquery-ui-1.10.1.custom.css', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ) );
248
  // Prepare a few variables to be used by the javascript code.
249
+ wp_localize_script(
250
+ 'ewwwbulkscript',
251
+ 'ewww_vars',
252
+ array(
253
+ '_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-bulk' ),
254
+ 'gallery' => 'flag',
255
+ 'attachments' => count( $ids ),
256
+ 'scan_fail' => esc_html__( 'Operation timed out, you may need to increase the max_execution_time for PHP', 'ewww-image-optimizer' ),
257
+ 'operation_stopped' => esc_html__( 'Optimization stopped, reload page to resume.', 'ewww-image-optimizer' ),
258
+ 'operation_interrupted' => esc_html__( 'Operation Interrupted', 'ewww-image-optimizer' ),
259
+ 'temporary_failure' => esc_html__( 'Temporary failure, seconds left to retry:', 'ewww-image-optimizer' ),
260
+ 'remove_failed' => esc_html__( 'Could not remove image from table.', 'ewww-image-optimizer' ),
261
+ 'optimized' => esc_html__( 'Optimized', 'ewww-image-optimizer' ),
262
+ )
263
+ );
264
  }
265
 
266
  /**
279
  $ewwwio_flag_background = new EWWWIO_Flag_Background_Process();
280
  }
281
  ewwwio_debug_message( "optimization (flagallery) queued for $image_id" );
282
+ $ewwwio_flag_background->push_to_queue( array( 'id' => $image_id ) );
 
 
283
  $ewwwio_flag_background->save()->dispatch();
284
  set_transient( 'ewwwio-background-in-progress-flag-' . $image_id, true, 24 * HOUR_IN_SECONDS );
285
  ewww_image_optimizer_debug_log();
351
  * Remove the image editor filter during upload, and add a new filter that will restore it later.
352
  */
353
  function ewww_remove_image_editor() {
354
+ global $ewww_preempt_editor;
355
+ $ewww_preempt_editor = true;
356
+ /* remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 ); */
357
  add_action( 'flag_image_optimized', 'ewww_image_optimizer_restore_editor_hooks' );
358
  }
359
 
369
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
370
  }
371
  ewwwio_ob_clean();
372
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) ) ) );
 
 
373
  }
374
  // Make sure we have an attachment ID.
375
  if ( empty( $_REQUEST['ewww_attachment_ID'] ) ) {
377
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
378
  }
379
  ewwwio_ob_clean();
380
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) ) ) );
 
 
381
  }
382
  $id = intval( $_REQUEST['ewww_attachment_ID'] );
383
  if ( empty( $_REQUEST['ewww_manual_nonce'] ) || ! wp_verify_nonce( $_REQUEST['ewww_manual_nonce'], "ewww-manual-$id" ) ) {
385
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
386
  }
387
  ewwwio_ob_clean();
388
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ) ) ) );
 
 
389
  }
390
  global $ewww_image;
391
  if ( ! class_exists( 'flagMeta' ) ) {
423
  }
424
  $success = $this->ewww_manage_image_custom_column( $id );
425
  ewwwio_ob_clean();
426
+ wp_die( ewwwio_json_encode( array( 'success' => $success ) ) );
 
 
427
  }
428
 
429
  /**
438
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
439
  }
440
  ewwwio_ob_clean();
441
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) ) ) );
 
 
442
  }
443
  // Make sure function wasn't called without an attachment to work with.
444
  if ( false === isset( $_REQUEST['ewww_attachment_ID'] ) ) {
446
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
447
  }
448
  ewwwio_ob_clean();
449
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) ) ) );
 
 
450
  }
451
  // Store the attachment $id.
452
  $id = intval( $_REQUEST['ewww_attachment_ID'] );
455
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
456
  }
457
  ewwwio_ob_clean();
458
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ) ) ) );
 
 
459
  }
460
  if ( ! class_exists( 'flagMeta' ) ) {
461
  require_once( FLAG_ABSPATH . 'lib/meta.php' );
463
  ewww_image_optimizer_cloud_restore_from_meta_data( $id, 'flag' );
464
  $success = $this->ewww_manage_image_custom_column( $id );
465
  ewwwio_ob_clean();
466
+ wp_die( ewwwio_json_encode( array( 'success' => $success ) ) );
 
 
467
  }
468
 
469
  /**
741
  list( $detail_output, $converted, $backup_available ) = ewww_image_optimizer_custom_column_results( $id, $optimized_images );
742
  $output .= $detail_output;
743
  if ( current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
744
+ $output .= sprintf(
745
+ '<a class="ewww-manual-optimize" data-id="%1$d" data-nonce="%2$s" href="admin.php?action=ewww_flag_manual&amp;ewww_manual_nonce=%2$s&amp;ewww_force=1&amp;ewww_attachment_ID=%1$d">%3$s</a>',
746
  $id,
747
  $ewww_manual_nonce,
748
  esc_html__( 'Re-optimize', 'ewww-image-optimizer' )
749
  );
750
  if ( $backup_available ) {
751
+ $output .= sprintf(
752
+ '<br><a class="ewww-manual-cloud-restore" data-id="%1$d" data-nonce="%2$s" href="admin.php?action=ewww_flag_cloud_restore&amp;ewww_manual_nonce=%2$s&amp;ewww_attachment_ID=%1$d">%3$s</a>',
753
  $id,
754
  $ewww_manual_nonce,
755
  esc_html__( 'Restore original', 'ewww-image-optimizer' )
761
  // Otherwise, tell the user that they can optimize the image now.
762
  } else {
763
  if ( current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
764
+ $output .= sprintf(
765
+ '<a class="ewww-manual-optimize" data-id="%1$d" data-nonce="%2$s" href="admin.php?action=ewww_flag_manual&amp;ewww_manual_nonce=%2$s&amp;ewww_attachment_ID=%1$d">%3$s</a>',
766
  $id,
767
  $ewww_manual_nonce,
768
  esc_html__( 'Optimize now!', 'ewww-image-optimizer' )
classes/class-ewww-image.php CHANGED
@@ -214,10 +214,12 @@ class EWWW_Image {
214
  $mime = 'image/gif';
215
  }
216
  // Update the attachment post with the new mimetype and id.
217
- wp_update_post( array(
218
- 'ID' => $this->attachment_id,
219
- 'post_mime_type' => $mime,
220
- ) );
 
 
221
  }
222
 
223
  /**
@@ -834,19 +836,23 @@ class EWWW_Image {
834
  if ( ! empty( $image_record ) && is_array( $image_record ) && ! empty( $image_record['id'] ) ) {
835
  $id = $image_record['id'];
836
  } else { // Insert a new record.
837
- $ewwwdb->insert( $ewwwdb->ewwwio_images, array(
838
- 'path' => ewww_image_optimizer_relative_path_remove( $new_path ),
839
- 'converted' => ewww_image_optimizer_relative_path_remove( $path ),
840
- 'orig_size' => filesize( $new_path ),
841
- 'attachment_id' => $this->attachment_id,
842
- 'results' => __( 'No savings', 'ewww-image-optimizer' ),
843
- 'updated' => date( 'Y-m-d H:i:s' ),
844
- 'updates' => 0,
845
- ) );
 
 
 
846
  return;
847
  }
848
  }
849
- $ewwwdb->update( $ewwwdb->ewwwio_images,
 
850
  array(
851
  'path' => ewww_image_optimizer_relative_path_remove( $new_path ),
852
  'converted' => ewww_image_optimizer_relative_path_remove( $path ),
@@ -889,7 +895,8 @@ class EWWW_Image {
889
  return false;
890
  }
891
  }
892
- $ewwwdb->update( $ewwwdb->ewwwio_images,
 
893
  array(
894
  'path' => ewww_image_optimizer_relative_path_remove( $new_path ),
895
  'converted' => '',
214
  $mime = 'image/gif';
215
  }
216
  // Update the attachment post with the new mimetype and id.
217
+ wp_update_post(
218
+ array(
219
+ 'ID' => $this->attachment_id,
220
+ 'post_mime_type' => $mime,
221
+ )
222
+ );
223
  }
224
 
225
  /**
836
  if ( ! empty( $image_record ) && is_array( $image_record ) && ! empty( $image_record['id'] ) ) {
837
  $id = $image_record['id'];
838
  } else { // Insert a new record.
839
+ $ewwwdb->insert(
840
+ $ewwwdb->ewwwio_images,
841
+ array(
842
+ 'path' => ewww_image_optimizer_relative_path_remove( $new_path ),
843
+ 'converted' => ewww_image_optimizer_relative_path_remove( $path ),
844
+ 'orig_size' => filesize( $new_path ),
845
+ 'attachment_id' => $this->attachment_id,
846
+ 'results' => __( 'No savings', 'ewww-image-optimizer' ),
847
+ 'updated' => date( 'Y-m-d H:i:s' ),
848
+ 'updates' => 0,
849
+ )
850
+ );
851
  return;
852
  }
853
  }
854
+ $ewwwdb->update(
855
+ $ewwwdb->ewwwio_images,
856
  array(
857
  'path' => ewww_image_optimizer_relative_path_remove( $new_path ),
858
  'converted' => ewww_image_optimizer_relative_path_remove( $path ),
895
  return false;
896
  }
897
  }
898
+ $ewwwdb->update(
899
+ $ewwwdb->ewwwio_images,
900
  array(
901
  'path' => ewww_image_optimizer_relative_path_remove( $new_path ),
902
  'converted' => '',
classes/class-ewww-nextcellent.php CHANGED
@@ -65,9 +65,7 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
65
  $ewwwio_ngg_background = new EWWWIO_Ngg_Background_Process();
66
  }
67
  foreach ( $images as $id ) {
68
- $ewwwio_ngg_background->push_to_queue( array(
69
- 'id' => $id,
70
- ) );
71
  set_transient( 'ewwwio-background-in-progress-ngg-' . $id, true, 24 * HOUR_IN_SECONDS );
72
  ewwwio_debug_message( "optimization (nextcellent) queued for $id" );
73
  }
@@ -94,9 +92,7 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
94
  $fres = ewww_image_optimizer( $file_path, 2, false, false, true );
95
  // Update the metadata for the optimized image.
96
  global $nggdb;
97
- $nggdb->update_image_meta( $id, array(
98
- 'ewww_image_optimizer' => $fres[1],
99
- ) );
100
  }
101
 
102
  /**
@@ -123,9 +119,7 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
123
  // Run the optimizer on the current image.
124
  $res = ewww_image_optimizer( ABSPATH . $file_path, 2, false, false, true );
125
  // Update the metadata for the optimized image.
126
- nggdb::update_image_meta( $image['id'], array(
127
- 'ewww_image_optimizer' => $res[1],
128
- ) );
129
  }
130
  }
131
 
@@ -166,9 +160,7 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
166
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
167
  }
168
  ewwwio_ob_clean();
169
- wp_die( ewwwio_json_encode( array(
170
- 'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
171
- ) ) );
172
  }
173
  // Make sure function wasn't called without an attachment to work with.
174
  if ( empty( $_REQUEST['ewww_attachment_ID'] ) ) {
@@ -176,9 +168,7 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
176
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
177
  }
178
  ewwwio_ob_clean();
179
- wp_die( ewwwio_json_encode( array(
180
- 'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ),
181
- ) ) );
182
  }
183
  // Store the attachment $id.
184
  $id = intval( $_REQUEST['ewww_attachment_ID'] );
@@ -187,9 +177,7 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
187
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
188
  }
189
  ewwwio_ob_clean();
190
- wp_die( ewwwio_json_encode( array(
191
- 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
192
- ) ) );
193
  }
194
  $this->ewww_ngg_optimize( $id );
195
  $success = $this->ewww_manage_image_custom_column( 'ewww_image_optimizer', $id, true );
@@ -202,9 +190,7 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
202
  die;
203
  }
204
  ewwwio_ob_clean();
205
- wp_die( ewwwio_json_encode( array(
206
- 'success' => $success,
207
- ) ) );
208
  }
209
 
210
  /**
@@ -218,9 +204,7 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
218
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
219
  }
220
  ewwwio_ob_clean();
221
- wp_die( ewwwio_json_encode( array(
222
- 'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
223
- ) ) );
224
  }
225
  // Make sure function wasn't called without an attachment to work with.
226
  if ( false === isset( $_REQUEST['ewww_attachment_ID'] ) ) {
@@ -228,9 +212,7 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
228
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
229
  }
230
  ewwwio_ob_clean();
231
- wp_die( ewwwio_json_encode( array(
232
- 'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ),
233
- ) ) );
234
  }
235
  // Sanitize the attachment $id.
236
  $id = intval( $_REQUEST['ewww_attachment_ID'] );
@@ -239,16 +221,12 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
239
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
240
  }
241
  ewwwio_ob_clean();
242
- wp_die( ewwwio_json_encode( array(
243
- 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
244
- ) ) );
245
  }
246
  ewww_image_optimizer_cloud_restore_from_meta_data( $id, 'nextcell' );
247
  $success = $this->ewww_manage_image_custom_column( 'ewww_image_optimizer', $id, true );
248
  ewwwio_ob_clean();
249
- wp_die( ewwwio_json_encode( array(
250
- 'success' => $success,
251
- ) ) );
252
  }
253
 
254
  /**
@@ -279,9 +257,7 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
279
  $fres = ewww_image_optimizer( $file_path, 2, false, false, true );
280
  // Update the metadata for the optimized image.
281
  global $nggdb;
282
- $nggdb->update_image_meta( $id, array(
283
- 'ewww_image_optimizer' => $fres[1],
284
- ) );
285
  // Get the filepath of the thumbnail image.
286
  $thumb_path = $meta->image->thumbPath;
287
  $ewww_image = new EWWW_Image( $id, 'nextcell', $thumb_path );
@@ -377,13 +353,15 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
377
  list( $detail_output, $converted, $backup_available ) = ewww_image_optimizer_custom_column_results( $id, $optimized_images );
378
  $output .= $detail_output;
379
  if ( current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
380
- $output .= sprintf( '<a class="ewww-manual-optimize" data-id="%1$d" data-nonce="%2$s" href="admin.php?action=ewww_ngg_manual&amp;ewww_manual_nonce=%2$s&amp;ewww_force=1&amp;ewww_attachment_ID=%1$d">%3$s</a>',
 
381
  $id,
382
  $ewww_manual_nonce,
383
  esc_html__( 'Re-optimize', 'ewww-image-optimizer' )
384
  );
385
  if ( $backup_available ) {
386
- $output .= sprintf( '<br><a class="ewww-manual-cloud-restore" data-id="%1$d" data-nonce="%2$s" href="admin.php?action=ewww_ngg_cloud_restore&amp;ewww_manual_nonce=%2$s&amp;ewww_attachment_ID=%1$d">%3$s</a>',
 
387
  $id,
388
  $ewww_manual_nonce,
389
  esc_html__( 'Restore original', 'ewww-image-optimizer' )
@@ -395,7 +373,8 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
395
  // Otherwise, give the image size, and a link to optimize right now.
396
  } else {
397
  if ( current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
398
- $output .= sprintf( '<a class="ewww-manual-optimize" data-id="%1$d" data-nonce="%2$s" href="admin.php?action=ewww_ngg_manual&amp;ewww_manual_nonce=%2$s&amp;ewww_attachment_ID=%1$d">%3$s</a>',
 
399
  $id,
400
  $ewww_manual_nonce,
401
  esc_html__( 'Optimize now!', 'ewww-image-optimizer' )
@@ -586,17 +565,21 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
586
  wp_enqueue_style( 'ngg-jqueryui' );
587
  wp_add_inline_style( 'ngg-jqueryui', '.ui-widget-header { background-color: ' . ewww_image_optimizer_admin_background() . '; }' );
588
  // Include all the vars we need for javascript.
589
- wp_localize_script( 'ewwwbulkscript', 'ewww_vars', array(
590
- '_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-bulk' ),
591
- 'gallery' => 'nextgen',
592
- 'attachments' => count( $images ),
593
- 'scan_fail' => esc_html__( 'Operation timed out, you may need to increase the max_execution_time for PHP', 'ewww-image-optimizer' ),
594
- 'operation_stopped' => esc_html__( 'Optimization stopped, reload page to resume.', 'ewww-image-optimizer' ),
595
- 'operation_interrupted' => esc_html__( 'Operation Interrupted', 'ewww-image-optimizer' ),
596
- 'temporary_failure' => esc_html__( 'Temporary failure, seconds left to retry:', 'ewww-image-optimizer' ),
597
- 'remove_failed' => esc_html__( 'Could not remove image from table.', 'ewww-image-optimizer' ),
598
- 'optimized' => esc_html__( 'Optimized', 'ewww-image-optimizer' ),
599
- ) );
 
 
 
 
600
  }
601
 
602
  /**
65
  $ewwwio_ngg_background = new EWWWIO_Ngg_Background_Process();
66
  }
67
  foreach ( $images as $id ) {
68
+ $ewwwio_ngg_background->push_to_queue( array( 'id' => $id ) );
 
 
69
  set_transient( 'ewwwio-background-in-progress-ngg-' . $id, true, 24 * HOUR_IN_SECONDS );
70
  ewwwio_debug_message( "optimization (nextcellent) queued for $id" );
71
  }
92
  $fres = ewww_image_optimizer( $file_path, 2, false, false, true );
93
  // Update the metadata for the optimized image.
94
  global $nggdb;
95
+ $nggdb->update_image_meta( $id, array( 'ewww_image_optimizer' => $fres[1] ) );
 
 
96
  }
97
 
98
  /**
119
  // Run the optimizer on the current image.
120
  $res = ewww_image_optimizer( ABSPATH . $file_path, 2, false, false, true );
121
  // Update the metadata for the optimized image.
122
+ nggdb::update_image_meta( $image['id'], array( 'ewww_image_optimizer' => $res[1] ) );
 
 
123
  }
124
  }
125
 
160
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
161
  }
162
  ewwwio_ob_clean();
163
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) ) ) );
 
 
164
  }
165
  // Make sure function wasn't called without an attachment to work with.
166
  if ( empty( $_REQUEST['ewww_attachment_ID'] ) ) {
168
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
169
  }
170
  ewwwio_ob_clean();
171
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) ) ) );
 
 
172
  }
173
  // Store the attachment $id.
174
  $id = intval( $_REQUEST['ewww_attachment_ID'] );
177
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
178
  }
179
  ewwwio_ob_clean();
180
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ) ) ) );
 
 
181
  }
182
  $this->ewww_ngg_optimize( $id );
183
  $success = $this->ewww_manage_image_custom_column( 'ewww_image_optimizer', $id, true );
190
  die;
191
  }
192
  ewwwio_ob_clean();
193
+ wp_die( ewwwio_json_encode( array( 'success' => $success ) ) );
 
 
194
  }
195
 
196
  /**
204
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
205
  }
206
  ewwwio_ob_clean();
207
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) ) ) );
 
 
208
  }
209
  // Make sure function wasn't called without an attachment to work with.
210
  if ( false === isset( $_REQUEST['ewww_attachment_ID'] ) ) {
212
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
213
  }
214
  ewwwio_ob_clean();
215
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) ) ) );
 
 
216
  }
217
  // Sanitize the attachment $id.
218
  $id = intval( $_REQUEST['ewww_attachment_ID'] );
221
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
222
  }
223
  ewwwio_ob_clean();
224
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ) ) ) );
 
 
225
  }
226
  ewww_image_optimizer_cloud_restore_from_meta_data( $id, 'nextcell' );
227
  $success = $this->ewww_manage_image_custom_column( 'ewww_image_optimizer', $id, true );
228
  ewwwio_ob_clean();
229
+ wp_die( ewwwio_json_encode( array( 'success' => $success ) ) );
 
 
230
  }
231
 
232
  /**
257
  $fres = ewww_image_optimizer( $file_path, 2, false, false, true );
258
  // Update the metadata for the optimized image.
259
  global $nggdb;
260
+ $nggdb->update_image_meta( $id, array( 'ewww_image_optimizer' => $fres[1] ) );
 
 
261
  // Get the filepath of the thumbnail image.
262
  $thumb_path = $meta->image->thumbPath;
263
  $ewww_image = new EWWW_Image( $id, 'nextcell', $thumb_path );
353
  list( $detail_output, $converted, $backup_available ) = ewww_image_optimizer_custom_column_results( $id, $optimized_images );
354
  $output .= $detail_output;
355
  if ( current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
356
+ $output .= sprintf(
357
+ '<a class="ewww-manual-optimize" data-id="%1$d" data-nonce="%2$s" href="admin.php?action=ewww_ngg_manual&amp;ewww_manual_nonce=%2$s&amp;ewww_force=1&amp;ewww_attachment_ID=%1$d">%3$s</a>',
358
  $id,
359
  $ewww_manual_nonce,
360
  esc_html__( 'Re-optimize', 'ewww-image-optimizer' )
361
  );
362
  if ( $backup_available ) {
363
+ $output .= sprintf(
364
+ '<br><a class="ewww-manual-cloud-restore" data-id="%1$d" data-nonce="%2$s" href="admin.php?action=ewww_ngg_cloud_restore&amp;ewww_manual_nonce=%2$s&amp;ewww_attachment_ID=%1$d">%3$s</a>',
365
  $id,
366
  $ewww_manual_nonce,
367
  esc_html__( 'Restore original', 'ewww-image-optimizer' )
373
  // Otherwise, give the image size, and a link to optimize right now.
374
  } else {
375
  if ( current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
376
+ $output .= sprintf(
377
+ '<a class="ewww-manual-optimize" data-id="%1$d" data-nonce="%2$s" href="admin.php?action=ewww_ngg_manual&amp;ewww_manual_nonce=%2$s&amp;ewww_attachment_ID=%1$d">%3$s</a>',
378
  $id,
379
  $ewww_manual_nonce,
380
  esc_html__( 'Optimize now!', 'ewww-image-optimizer' )
565
  wp_enqueue_style( 'ngg-jqueryui' );
566
  wp_add_inline_style( 'ngg-jqueryui', '.ui-widget-header { background-color: ' . ewww_image_optimizer_admin_background() . '; }' );
567
  // Include all the vars we need for javascript.
568
+ wp_localize_script(
569
+ 'ewwwbulkscript',
570
+ 'ewww_vars',
571
+ array(
572
+ '_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-bulk' ),
573
+ 'gallery' => 'nextgen',
574
+ 'attachments' => count( $images ),
575
+ 'scan_fail' => esc_html__( 'Operation timed out, you may need to increase the max_execution_time for PHP', 'ewww-image-optimizer' ),
576
+ 'operation_stopped' => esc_html__( 'Optimization stopped, reload page to resume.', 'ewww-image-optimizer' ),
577
+ 'operation_interrupted' => esc_html__( 'Operation Interrupted', 'ewww-image-optimizer' ),
578
+ 'temporary_failure' => esc_html__( 'Temporary failure, seconds left to retry:', 'ewww-image-optimizer' ),
579
+ 'remove_failed' => esc_html__( 'Could not remove image from table.', 'ewww-image-optimizer' ),
580
+ 'optimized' => esc_html__( 'Optimized', 'ewww-image-optimizer' ),
581
+ )
582
+ );
583
  }
584
 
585
  /**
classes/class-ewww-nextgen.php CHANGED
@@ -151,9 +151,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
151
  $ewwwio_ngg2_background = new EWWWIO_Ngg2_Background_Process();
152
  }
153
  ewwwio_debug_message( "backgrounding optimization for $image_id" );
154
- $ewwwio_ngg2_background->push_to_queue( array(
155
- 'id' => $image_id,
156
- ) );
157
  $ewwwio_ngg2_background->save()->dispatch();
158
  set_transient( 'ewwwio-background-in-progress-ngg-' . $image_id, true, 24 * HOUR_IN_SECONDS );
159
  ewww_image_optimizer_debug_log();
@@ -255,9 +253,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
255
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
256
  }
257
  ewwwio_ob_clean();
258
- wp_die( ewwwio_json_encode( array(
259
- 'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
260
- ) ) );
261
  }
262
  // Make sure function wasn't called without an attachment to work with.
263
  if ( false === isset( $_REQUEST['ewww_attachment_ID'] ) ) {
@@ -265,9 +261,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
265
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
266
  }
267
  ewwwio_ob_clean();
268
- wp_die( ewwwio_json_encode( array(
269
- 'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ),
270
- ) ) );
271
  }
272
  // Sanitize the attachment $id.
273
  $id = intval( $_REQUEST['ewww_attachment_ID'] );
@@ -276,9 +270,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
276
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
277
  }
278
  ewwwio_ob_clean();
279
- wp_die( ewwwio_json_encode( array(
280
- 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
281
- ) ) );
282
  }
283
  // Creating the 'registry' object for working with nextgen.
284
  $registry = C_Component_Registry::get_instance();
@@ -290,9 +282,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
290
  $success = $this->ewww_manage_image_custom_column( '', $image );
291
  if ( get_transient( 'ewww_image_optimizer_cloud_status' ) == 'exceeded' || ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_exceeded' ) > time() ) {
292
  ewwwio_ob_clean();
293
- wp_die( ewwwio_json_encode( array(
294
- 'error' => esc_html__( 'License exceeded', 'ewww-image-optimizer' ),
295
- ) ) );
296
  }
297
  if ( ! wp_doing_ajax() ) {
298
  // Get the referring page, and send the user back there.
@@ -302,9 +292,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
302
  die;
303
  }
304
  ewwwio_ob_clean();
305
- wp_die( ewwwio_json_encode( array(
306
- 'success' => $success,
307
- ) ) );
308
  }
309
 
310
  /**
@@ -318,9 +306,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
318
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
319
  }
320
  ewwwio_ob_clean();
321
- wp_die( ewwwio_json_encode( array(
322
- 'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
323
- ) ) );
324
  }
325
  // Make sure function wasn't called without an attachment to work with.
326
  if ( false === isset( $_REQUEST['ewww_attachment_ID'] ) ) {
@@ -328,9 +314,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
328
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
329
  }
330
  ewwwio_ob_clean();
331
- wp_die( ewwwio_json_encode( array(
332
- 'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ),
333
- ) ) );
334
  }
335
  // Sanitize the attachment $id.
336
  $id = intval( $_REQUEST['ewww_attachment_ID'] );
@@ -339,9 +323,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
339
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
340
  }
341
  ewwwio_ob_clean();
342
- wp_die( ewwwio_json_encode( array(
343
- 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
344
- ) ) );
345
  }
346
  // Creating the 'registry' object for working with nextgen.
347
  $registry = C_Component_Registry::get_instance();
@@ -352,9 +334,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
352
  ewww_image_optimizer_cloud_restore_from_meta_data( $image->pid, 'nextgen' );
353
  $success = $this->ewww_manage_image_custom_column( '', $image );
354
  ewwwio_ob_clean();
355
- wp_die( ewwwio_json_encode( array(
356
- 'success' => $success,
357
- ) ) );
358
  }
359
 
360
  /**
@@ -564,20 +544,23 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
564
  }
565
  $ewww_manual_nonce = wp_create_nonce( 'ewww-manual-' . $id );
566
  if ( $optimized ) {
567
- $link = sprintf( '<a class="ewww-manual-optimize" data-id="%1$d" data-nonce="%2$s" href="admin.php?action=ewww_ngg_manual&amp;ewww_manual_nonce=%2$s&amp;ewww_force=1&amp;ewww_attachment_ID=%1$d">%3$s</a>',
 
568
  $id,
569
  $ewww_manual_nonce,
570
  esc_html__( 'Re-optimize', 'ewww-image-optimizer' )
571
  );
572
  if ( $restorable ) {
573
- $link .= sprintf( '<br><a class="ewww-manual-cloud-restore" data-id="%1$d" data-nonce="%2$s" href="admin.php?action=ewww_ngg_cloud_restore&amp;ewww_manual_nonce=%2$s&amp;ewww_attachment_ID=%1$d">%3$s</a>',
 
574
  $id,
575
  $ewww_manual_nonce,
576
  esc_html__( 'Restore original', 'ewww-image-optimizer' )
577
  );
578
  }
579
  } else {
580
- $link = sprintf( '<a class="ewww-manual-optimize" data-id="%1$d" data-nonce="%2$s" href="admin.php?action=ewww_ngg_manual&amp;ewww_manual_nonce=%2$s&amp;ewww_attachment_ID=%1$d">%3$s</a>',
 
581
  $id,
582
  $ewww_manual_nonce,
583
  esc_html__( 'Optimize now!', 'ewww-image-optimizer' )
@@ -803,17 +786,21 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
803
  wp_enqueue_style( 'jquery-ui-nextgen' );
804
  wp_add_inline_style( 'jquery-ui-nextgen', '.ui-widget-header { background-color: ' . ewww_image_optimizer_admin_background() . '; }' );
805
  // Include all the vars we need for javascript.
806
- wp_localize_script( 'ewwwbulkscript', 'ewww_vars', array(
807
- '_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-bulk' ),
808
- 'gallery' => 'nextgen',
809
- 'attachments' => count( $images ),
810
- 'scan_fail' => esc_html__( 'Operation timed out, you may need to increase the max_execution_time for PHP', 'ewww-image-optimizer' ),
811
- 'operation_stopped' => esc_html__( 'Optimization stopped, reload page to resume.', 'ewww-image-optimizer' ),
812
- 'operation_interrupted' => esc_html__( 'Operation Interrupted', 'ewww-image-optimizer' ),
813
- 'temporary_failure' => esc_html__( 'Temporary failure, seconds left to retry:', 'ewww-image-optimizer' ),
814
- 'remove_failed' => esc_html__( 'Could not remove image from table.', 'ewww-image-optimizer' ),
815
- 'optimized' => esc_html__( 'Optimized', 'ewww-image-optimizer' ),
816
- ) );
 
 
 
 
817
  }
818
 
819
  /**
@@ -1011,16 +998,18 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
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
  }
151
  $ewwwio_ngg2_background = new EWWWIO_Ngg2_Background_Process();
152
  }
153
  ewwwio_debug_message( "backgrounding optimization for $image_id" );
154
+ $ewwwio_ngg2_background->push_to_queue( array( 'id' => $image_id ) );
 
 
155
  $ewwwio_ngg2_background->save()->dispatch();
156
  set_transient( 'ewwwio-background-in-progress-ngg-' . $image_id, true, 24 * HOUR_IN_SECONDS );
157
  ewww_image_optimizer_debug_log();
253
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
254
  }
255
  ewwwio_ob_clean();
256
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) ) ) );
 
 
257
  }
258
  // Make sure function wasn't called without an attachment to work with.
259
  if ( false === isset( $_REQUEST['ewww_attachment_ID'] ) ) {
261
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
262
  }
263
  ewwwio_ob_clean();
264
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) ) ) );
 
 
265
  }
266
  // Sanitize the attachment $id.
267
  $id = intval( $_REQUEST['ewww_attachment_ID'] );
270
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
271
  }
272
  ewwwio_ob_clean();
273
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ) ) ) );
 
 
274
  }
275
  // Creating the 'registry' object for working with nextgen.
276
  $registry = C_Component_Registry::get_instance();
282
  $success = $this->ewww_manage_image_custom_column( '', $image );
283
  if ( get_transient( 'ewww_image_optimizer_cloud_status' ) == 'exceeded' || ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_exceeded' ) > time() ) {
284
  ewwwio_ob_clean();
285
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'License exceeded', 'ewww-image-optimizer' ) ) ) );
 
 
286
  }
287
  if ( ! wp_doing_ajax() ) {
288
  // Get the referring page, and send the user back there.
292
  die;
293
  }
294
  ewwwio_ob_clean();
295
+ wp_die( ewwwio_json_encode( array( 'success' => $success ) ) );
 
 
296
  }
297
 
298
  /**
306
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
307
  }
308
  ewwwio_ob_clean();
309
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) ) ) );
 
 
310
  }
311
  // Make sure function wasn't called without an attachment to work with.
312
  if ( false === isset( $_REQUEST['ewww_attachment_ID'] ) ) {
314
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
315
  }
316
  ewwwio_ob_clean();
317
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) ) ) );
 
 
318
  }
319
  // Sanitize the attachment $id.
320
  $id = intval( $_REQUEST['ewww_attachment_ID'] );
323
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
324
  }
325
  ewwwio_ob_clean();
326
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ) ) ) );
 
 
327
  }
328
  // Creating the 'registry' object for working with nextgen.
329
  $registry = C_Component_Registry::get_instance();
334
  ewww_image_optimizer_cloud_restore_from_meta_data( $image->pid, 'nextgen' );
335
  $success = $this->ewww_manage_image_custom_column( '', $image );
336
  ewwwio_ob_clean();
337
+ wp_die( ewwwio_json_encode( array( 'success' => $success ) ) );
 
 
338
  }
339
 
340
  /**
544
  }
545
  $ewww_manual_nonce = wp_create_nonce( 'ewww-manual-' . $id );
546
  if ( $optimized ) {
547
+ $link = sprintf(
548
+ '<a class="ewww-manual-optimize" data-id="%1$d" data-nonce="%2$s" href="admin.php?action=ewww_ngg_manual&amp;ewww_manual_nonce=%2$s&amp;ewww_force=1&amp;ewww_attachment_ID=%1$d">%3$s</a>',
549
  $id,
550
  $ewww_manual_nonce,
551
  esc_html__( 'Re-optimize', 'ewww-image-optimizer' )
552
  );
553
  if ( $restorable ) {
554
+ $link .= sprintf(
555
+ '<br><a class="ewww-manual-cloud-restore" data-id="%1$d" data-nonce="%2$s" href="admin.php?action=ewww_ngg_cloud_restore&amp;ewww_manual_nonce=%2$s&amp;ewww_attachment_ID=%1$d">%3$s</a>',
556
  $id,
557
  $ewww_manual_nonce,
558
  esc_html__( 'Restore original', 'ewww-image-optimizer' )
559
  );
560
  }
561
  } else {
562
+ $link = sprintf(
563
+ '<a class="ewww-manual-optimize" data-id="%1$d" data-nonce="%2$s" href="admin.php?action=ewww_ngg_manual&amp;ewww_manual_nonce=%2$s&amp;ewww_attachment_ID=%1$d">%3$s</a>',
564
  $id,
565
  $ewww_manual_nonce,
566
  esc_html__( 'Optimize now!', 'ewww-image-optimizer' )
786
  wp_enqueue_style( 'jquery-ui-nextgen' );
787
  wp_add_inline_style( 'jquery-ui-nextgen', '.ui-widget-header { background-color: ' . ewww_image_optimizer_admin_background() . '; }' );
788
  // Include all the vars we need for javascript.
789
+ wp_localize_script(
790
+ 'ewwwbulkscript',
791
+ 'ewww_vars',
792
+ array(
793
+ '_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-bulk' ),
794
+ 'gallery' => 'nextgen',
795
+ 'attachments' => count( $images ),
796
+ 'scan_fail' => esc_html__( 'Operation timed out, you may need to increase the max_execution_time for PHP', 'ewww-image-optimizer' ),
797
+ 'operation_stopped' => esc_html__( 'Optimization stopped, reload page to resume.', 'ewww-image-optimizer' ),
798
+ 'operation_interrupted' => esc_html__( 'Operation Interrupted', 'ewww-image-optimizer' ),
799
+ 'temporary_failure' => esc_html__( 'Temporary failure, seconds left to retry:', 'ewww-image-optimizer' ),
800
+ 'remove_failed' => esc_html__( 'Could not remove image from table.', 'ewww-image-optimizer' ),
801
+ 'optimized' => esc_html__( 'Optimized', 'ewww-image-optimizer' ),
802
+ )
803
+ );
804
  }
805
 
806
  /**
998
  if ( 'manage-galleries' === $_REQUEST['page'] ) {
999
  $type = 'galleries';
1000
  }
1001
+ wp_redirect(
1002
+ add_query_arg(
1003
+ array(
1004
+ 'page' => 'ewww-ngg-bulk',
1005
+ '_wpnonce' => $_REQUEST['_wpnonce'],
1006
+ 'bulk_type' => $type,
1007
+ 'bulkaction' => 'bulk_optimize',
1008
+ 'doaction' => $_REQUEST['doaction'],
1009
+ ),
1010
+ admin_url( 'admin.php' )
1011
+ )
1012
+ );
1013
  ewwwio_memory( __FUNCTION__ );
1014
  exit();
1015
  }
classes/class-ewwwio-alt-webp.php CHANGED
@@ -16,12 +16,12 @@ if ( ! defined( 'ABSPATH' ) ) {
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
  /**
16
  class EWWWIO_Alt_Webp extends EWWWIO_Page_Parser {
17
 
18
  /**
19
+ * The Alt WebP inline script contents. Current length 12941.
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,e){e&&e.options.onceOnly&&1==e.firedElems.length&&(t=[t[0]]);for(var a,i=0;a=t[i];i++)a&&a.callback&&a.callback.call(a.elem,a.elem);e&&e.options.onceOnly&&1==e.firedElems.length&&e.me.unbindEventWithSelectorAndCallback.call(e.target,e.selector,e.callback)},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)t.hasOwnProperty(a)&&(i[a]=t[a]);for(a in e)e.hasOwnProperty(a)&&(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--)if(t(e)){this._beforeRemoving&&this._beforeRemoving(e);var i=this._eventsBucket.splice(a,1);i&&i.length&&(i[0].callback=null)}},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;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){return!(!u.matchesSelector(t,e.selector)||(t._id===c&&(t._id=i++),-1!=e.firedElems.indexOf(t._id))||(e.firedElems.push(t._id),0))}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.push({callback:r.callback,elem:a}),u.callCallbacks(i,r)})})).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,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(){return{childList:!0,subtree:!0}},function(t,i){t.forEach(function(t){var e=t.removedNodes,a=[];null!==e&&0<e.length&&u.checkChildNodesRecursively(e,i,r,a),u.callCallbacks(a,i)})})).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(){ewww_webp_supported=0<a.width&&0<a.height,e(ewww_webp_supported)},a.onerror=function(){e(ewww_webp_supported=!1)},a.src="data:image/webp;base64,"+{alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"}[t]}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()}))}var ewww_webp_supported=!1,ewww_jquery_waiting_timer=0;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}ewww_jquery_waiting=setInterval(function(){if(window.jQuery){check_webp_feature("alpha",ewww_load_images),check_webp_feature("alpha",ewww_ngg_plus_load_galleries),document.arrive(".ewww_webp",function(){ewww_load_images(ewww_webp_supported)});var t=0,e=setInterval(function(){"undefined"!=typeof galleries&&(check_webp_feature("alpha",ewww_ngg_plus_parse_galleries),clearInterval(e)),1e3<(t+=25)&&clearInterval(e)},25);clearInterval(ewww_jquery_waiting)}1e4<(ewww_jquery_waiting_timer+=100)&&clearInterval(ewww_jquery_waiting)},100);';
25
 
26
 
27
  /**
classes/class-ewwwio-background-process.php CHANGED
@@ -215,11 +215,14 @@ if ( ! class_exists( 'EWWWIO_Background_Process' ) ) {
215
 
216
  $key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
217
 
218
- $count = $wpdb->get_var( $wpdb->prepare( "
219
- SELECT COUNT(*)
220
- FROM $wpdb->options
221
- WHERE option_name LIKE %s AND option_value != ''
222
- ", $key ) );
 
 
 
223
 
224
  return ( $count > 0 ) ? false : true;
225
  }
215
 
216
  $key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
217
 
218
+ $count = $wpdb->get_var(
219
+ $wpdb->prepare(
220
+ "SELECT COUNT(*)
221
+ FROM $wpdb->options
222
+ WHERE option_name LIKE %s AND option_value != ''",
223
+ $key
224
+ )
225
+ );
226
 
227
  return ( $count > 0 ) ? false : true;
228
  }
classes/class-ewwwio-cli.php CHANGED
@@ -457,9 +457,7 @@ function ewww_image_optimizer_bulk_next( $delay, $attachments ) {
457
  // Run the optimizer on the current image.
458
  $fres = ewww_image_optimizer( $file_path, 2, false, false, true );
459
  // Update the metadata of the optimized image.
460
- nggdb::update_image_meta( $id, array(
461
- 'ewww_image_optimizer' => $fres[1],
462
- ) );
463
  // Output the results of the optimization.
464
  WP_CLI::line( __( 'Optimized image:', 'ewww-image-optimizer' ) . $meta->image->filename );
465
  /* translators: %s: compression results */
457
  // Run the optimizer on the current image.
458
  $fres = ewww_image_optimizer( $file_path, 2, false, false, true );
459
  // Update the metadata of the optimized image.
460
+ nggdb::update_image_meta( $id, array( 'ewww_image_optimizer' => $fres[1] ) );
 
 
461
  // Output the results of the optimization.
462
  WP_CLI::line( __( 'Optimized image:', 'ewww-image-optimizer' ) . $meta->image->filename );
463
  /* translators: %s: compression results */
classes/class-ewwwio-gd-editor.php CHANGED
@@ -26,7 +26,12 @@ if ( class_exists( 'Bbpp_Animated_Gif' ) ) {
26
  * @return WP_Error| array The full path, base filename, width, height, and mimetype.
27
  */
28
  protected function _save( $image, $filename = null, $mime_type = null ) {
 
29
  global $ewww_defer;
 
 
 
 
30
  list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
31
  if ( ! $filename ) {
32
  $filename = $this->generate_filename( null, null, $extension );
@@ -48,7 +53,7 @@ if ( class_exists( 'Bbpp_Animated_Gif' ) ) {
48
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_CLOUD' ) ) {
49
  ewww_image_optimizer_cloud_init();
50
  }
51
- $saved = parent::_save( $image, $filename, $mimetype );
52
  if ( ! is_wp_error( $saved ) ) {
53
  if ( ! $filename ) {
54
  $filename = $saved['path'];
@@ -145,7 +150,12 @@ if ( class_exists( 'Bbpp_Animated_Gif' ) ) {
145
  * @return WP_Error| array The full path, base filename, width, height, and mimetype.
146
  */
147
  protected function _save( $image, $filename = null, $mime_type = null ) {
 
148
  global $ewww_defer;
 
 
 
 
149
  list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
150
  if ( ! $filename ) {
151
  $filename = $this->generate_filename( null, null, $extension );
@@ -217,7 +227,12 @@ if ( class_exists( 'Bbpp_Animated_Gif' ) ) {
217
  * @return WP_Error| array The full path, base filename, width, height, and mimetype.
218
  */
219
  protected function _save( $image, $filename = null, $mime_type = null ) {
 
220
  global $ewww_defer;
 
 
 
 
221
  list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
222
  if ( ! $filename ) {
223
  $filename = $this->generate_filename( null, null, $extension );
@@ -280,16 +295,313 @@ if ( class_exists( 'Bbpp_Animated_Gif' ) ) {
280
  * @see WP_Image_Editor_GD
281
  */
282
  class EWWWIO_GD_Editor extends WP_Image_Editor_GD {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
283
  /**
284
  * Saves a file from the image editor.
285
  *
 
 
286
  * @param resource $image A GD image object.
287
  * @param string $filename Optional. The name of the file to be saved to.
288
  * @param string $mime_type Optional. The mimetype of the file.
289
- * @return WP_Error| array The full path, base filename, width, height, and mimetype.
290
  */
291
  protected function _save( $image, $filename = null, $mime_type = null ) {
292
  global $ewww_defer;
 
 
 
 
 
 
 
293
  list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
294
  if ( ! $filename ) {
295
  $filename = $this->generate_filename( null, null, $extension );
26
  * @return WP_Error| array The full path, base filename, width, height, and mimetype.
27
  */
28
  protected function _save( $image, $filename = null, $mime_type = null ) {
29
+ ewwwio_debug_message( '<b>wp_image_editor_gd(agr)::' . __FUNCTION__ . '()</b>' );
30
  global $ewww_defer;
31
+ global $ewww_preempt_editor;
32
+ if ( ! empty( $ewww_preempt_editor ) ) {
33
+ return parent::_save( $image, $filename, $mime_type );
34
+ }
35
  list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
36
  if ( ! $filename ) {
37
  $filename = $this->generate_filename( null, null, $extension );
53
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_CLOUD' ) ) {
54
  ewww_image_optimizer_cloud_init();
55
  }
56
+ $saved = parent::_save( $image, $filename, $mime_type );
57
  if ( ! is_wp_error( $saved ) ) {
58
  if ( ! $filename ) {
59
  $filename = $saved['path'];
150
  * @return WP_Error| array The full path, base filename, width, height, and mimetype.
151
  */
152
  protected function _save( $image, $filename = null, $mime_type = null ) {
153
+ ewwwio_debug_message( '<b>wp_image_editor_gd(wpthumb)::' . __FUNCTION__ . '()</b>' );
154
  global $ewww_defer;
155
+ global $ewww_preempt_editor;
156
+ if ( ! empty( $ewww_preempt_editor ) ) {
157
+ return parent::_save( $image, $filename, $mime_type );
158
+ }
159
  list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
160
  if ( ! $filename ) {
161
  $filename = $this->generate_filename( null, null, $extension );
227
  * @return WP_Error| array The full path, base filename, width, height, and mimetype.
228
  */
229
  protected function _save( $image, $filename = null, $mime_type = null ) {
230
+ ewwwio_debug_message( '<b>wp_image_editor_gd(bfi)::' . __FUNCTION__ . '()</b>' );
231
  global $ewww_defer;
232
+ global $ewww_preempt_editor;
233
+ if ( ! empty( $ewww_preempt_editor ) ) {
234
+ return parent::_save( $image, $filename, $mime_type );
235
+ }
236
  list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
237
  if ( ! $filename ) {
238
  $filename = $this->generate_filename( null, null, $extension );
295
  * @see WP_Image_Editor_GD
296
  */
297
  class EWWWIO_GD_Editor extends WP_Image_Editor_GD {
298
+
299
+ /**
300
+ * Resizes current image.
301
+ *
302
+ * Requires width or height, crop is optional. Uses gifsicle to preserve GIF animations.
303
+ * Also use API in future for better quality resizing.
304
+ *
305
+ * @since 4.4.0
306
+ *
307
+ * @param int|null $max_w Image width.
308
+ * @param int|null $max_h Image height.
309
+ * @param bool $crop Optional. Scale by default, crop if true.
310
+ * @return bool|WP_Error
311
+ */
312
+ public function _resize( $max_w, $max_h, $crop = false ) {
313
+ if ( ( ! $max_w || $max_w >= $this->size['width'] ) && ( ! $max_h || $max_h >= $this->size['height'] ) ) {
314
+ return new WP_Error( 'image_resize_error', __( 'Image resize failed.' ) );
315
+ }
316
+ ewwwio_debug_message( '<b>wp_image_editor_gd::' . __FUNCTION__ . '()</b>' );
317
+ if ( defined( 'EWWWIO_EDITOR_AGR' ) && ! EWWWIO_EDITOR_AGR ) {
318
+ ewwwio_debug_message( 'AGR disabled' );
319
+ return parent::_resize( $max_w, $max_h, $crop );
320
+ }
321
+ if ( defined( 'EWWWIO_EDITOR_BETTER_RESIZE' ) && ! EWWW_IO_EDITOR_BETTER_RESIZE ) {
322
+ ewwwio_debug_message( 'API resize disabled' );
323
+ return parent::_resize( $max_w, $max_h, $crop );
324
+ }
325
+ if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_CLOUD' ) ) {
326
+ ewww_image_optimizer_cloud_init();
327
+ }
328
+ $ewww_status = get_transient( 'ewww_image_optimizer_cloud_status' );
329
+ if ( 'image/gif' === $this->mime_type && function_exists( 'ewww_image_optimizer_path_check' ) ) {
330
+ ewww_image_optimizer_path_check( false, false, true, false, false, false );
331
+ }
332
+ if ( 'image/gif' === $this->mime_type && ( ! defined( 'EWWW_IMAGE_OPTIMIZER_GIFSICLE' ) || ! EWWW_IMAGE_OPTIMIZER_GIFSICLE ) ) {
333
+ if ( false === strpos( $ewww_status, 'great' ) ) {
334
+ if ( ! ewww_image_optimizer_cloud_verify() ) {
335
+ ewwwio_debug_message( 'no gifsicle or API to resize an animated GIF' );
336
+ return parent::_resize( $max_w, $max_h, $crop );
337
+ }
338
+ }
339
+ }
340
+ if ( 'image/gif' !== $this->mime_type && false === strpos( $ewww_status, 'great' ) ) {
341
+ if ( ! ewww_image_optimizer_cloud_verify() ) {
342
+ ewwwio_debug_message( 'no API to resize the image' );
343
+ return parent::_resize( $max_w, $max_h, $crop );
344
+ }
345
+ }
346
+ if ( 'image/gif' !== $this->mime_type || ! ewww_image_optimizer_is_animated( $this->file ) ) {
347
+ ewwwio_debug_message( 'not an animated GIF' );
348
+ return parent::_resize( $max_w, $max_h, $crop );
349
+ }
350
+ // TODO: Possibly handle crop, rotate, and flip down the road.
351
+ if ( ! empty( $this->modified ) ) {
352
+ ewwwio_debug_message( 'GIF already altered, leave it alone' );
353
+ return parent::_resize( $max_w, $max_h, $crop );
354
+ }
355
+ if ( ! $this->file || 0 === strpos( $this->file, 's3' ) || 0 === strpos( $this->file, 'http' ) || 0 === strpos( $this->file, 'ftp' ) || ! is_file( $this->file ) ) {
356
+ ewwwio_debug_message( 'could not load original file, or remote path detected' );
357
+ return parent::_resize( $max_w, $max_h, $crop );
358
+ }
359
+ $resize_result = ewww_image_optimizer_better_resize( $this->file, $max_w, $max_h, $crop );
360
+ if ( is_wp_error( $resize_result ) ) {
361
+ return $resize_result;
362
+ }
363
+
364
+ $new_size = getimagesizefromstring( $resize_result );
365
+ if ( empty( $new_size ) ) {
366
+ return new WP_Error( 'image_resize_error', __( 'Image resize failed.' ) );
367
+ }
368
+ $this->update_size( $new_size[0], $new_size[1] );
369
+ ewwwio_memory( __FUNCTION__ );
370
+ return $resize_result;
371
+ }
372
+
373
+ /**
374
+ * Resizes current image.
375
+ * Wraps _resize, since _resize returns a GD Resource.
376
+ *
377
+ * At minimum, either a height or width must be provided.
378
+ * If one of the two is set to null, the resize will
379
+ * maintain aspect ratio according to the provided dimension.
380
+ *
381
+ * @since 4.4.0
382
+ *
383
+ * @param int|null $max_w Image width.
384
+ * @param int|null $max_h Image height.
385
+ * @param bool $crop Optional. Scale by default, crop if true.
386
+ * @return true|WP_Error
387
+ */
388
+ public function resize( $max_w, $max_h, $crop = false ) {
389
+ if ( ( $this->size['width'] == $max_w ) && ( $this->size['height'] == $max_h ) ) {
390
+ return true;
391
+ }
392
+
393
+ $resized = $this->_resize( $max_w, $max_h, $crop );
394
+
395
+ if ( is_resource( $resized ) ) {
396
+ imagedestroy( $this->image );
397
+ $this->image = $resized;
398
+ return true;
399
+ } elseif ( is_string( $resized ) ) {
400
+ $this->ewww_image = $resized;
401
+ imagedestroy( $this->image );
402
+ $this->image = @imagecreatefromstring( $resized );
403
+ return true;
404
+ } elseif ( is_wp_error( $resized ) ) {
405
+ return $resized;
406
+ }
407
+ return new WP_Error( 'image_resize_error', __( 'Image resize failed.' ), $this->file );
408
+ }
409
+
410
+ /**
411
+ * Resize multiple images from a single source.
412
+ *
413
+ * @since 4.4.0
414
+ *
415
+ * @param array $sizes {
416
+ * An array of image size arrays. Default sizes are 'small', 'medium', 'medium_large', 'large'.
417
+ *
418
+ * Either a height or width must be provided.
419
+ * If one of the two is set to null, the resize will
420
+ * maintain aspect ratio according to the provided dimension.
421
+ * Likewise, if crop is false, aspect ratio will also be preserved.
422
+ *
423
+ * @type array $size {
424
+ * Array of height, width values, and whether to crop.
425
+ *
426
+ * @type int $width Image width. Optional if `$height` is specified.
427
+ * @type int $height Image height. Optional if `$width` is specified.
428
+ * @type bool $crop Optional. Whether to crop the image. Default false.
429
+ * }
430
+ * }
431
+ * @return array An array of resized images' metadata by size.
432
+ */
433
+ public function multi_resize( $sizes ) {
434
+ $metadata = array();
435
+ $orig_size = $this->size;
436
+ foreach ( $sizes as $size => $size_data ) {
437
+ if ( ! isset( $size_data['width'] ) && ! isset( $size_data['height'] ) ) {
438
+ continue;
439
+ }
440
+ if ( ! isset( $size_data['width'] ) ) {
441
+ $size_data['width'] = null;
442
+ }
443
+ if ( ! isset( $size_data['height'] ) ) {
444
+ $size_data['height'] = null;
445
+ }
446
+ if ( ! isset( $size_data['crop'] ) ) {
447
+ $size_data['crop'] = false;
448
+ }
449
+
450
+ $image = $this->_resize( $size_data['width'], $size_data['height'], $size_data['crop'] );
451
+ $duplicate = ( ( $orig_size['width'] == $size_data['width'] ) && ( $orig_size['height'] == $size_data['height'] ) );
452
+
453
+ if ( ! is_wp_error( $image ) && ! $duplicate ) {
454
+ if ( is_resource( $image ) ) {
455
+ $resized = $this->_save( $image );
456
+ imagedestroy( $image );
457
+ } elseif ( is_string( $image ) ) {
458
+ $resized = $this->_save_ewwwio_file( $image );
459
+ unset( $image );
460
+ }
461
+ if ( ! is_wp_error( $resized ) && $resized ) {
462
+ unset( $resized['path'] );
463
+ $metadata[ $size ] = $resized;
464
+ }
465
+ }
466
+
467
+ $this->size = $orig_size;
468
+ }
469
+ return $metadata;
470
+ }
471
+
472
+ /**
473
+ * Crops Image.
474
+ *
475
+ * Currently does nothing more than call the parent and let us know the image is modified.
476
+ *
477
+ * @since 4.4.0
478
+ *
479
+ * @param int $src_x The start x position to crop from.
480
+ * @param int $src_y The start y position to crop from.
481
+ * @param int $src_w The width to crop.
482
+ * @param int $src_h The height to crop.
483
+ * @param int $dst_w Optional. The destination width.
484
+ * @param int $dst_h Optional. The destination height.
485
+ * @param bool $src_abs Optional. If the source crop points are absolute.
486
+ * @return bool|WP_Error
487
+ */
488
+ public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ) {
489
+ $this->modified = 'crop';
490
+ return parent::crop( $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs );
491
+ }
492
+
493
+ /**
494
+ * Rotates current image counter-clockwise by $angle.
495
+ *
496
+ * Currently does nothing more than call the parent and let us know the image is modified.
497
+ *
498
+ * @since 4.4.0
499
+ *
500
+ * @param float $angle The number of degrees for rotation.
501
+ * @return true|WP_Error
502
+ */
503
+ public function rotate( $angle ) {
504
+ $this->modified = 'rotate';
505
+ return parent::rotate( $angle );
506
+ }
507
+
508
+ /**
509
+ * Flips current image.
510
+ *
511
+ * Currently does nothing more than call the parent and let us know the image is modified.
512
+ *
513
+ * @since 4.4.0
514
+ *
515
+ * @param bool $horz Flip along Horizontal Axis.
516
+ * @param bool $vert Flip along Vertical Axis.
517
+ * @return true|WP_Error
518
+ */
519
+ public function flip( $horz, $vert ) {
520
+ $this->modified = 'flip';
521
+ return parent::flip( $horz, $vert );
522
+ }
523
+
524
+ /**
525
+ * Saves a file from the EWWW IO API-enabled image editor.
526
+ *
527
+ * @since 4.4.0
528
+ *
529
+ * @param string $image A string containing the image contents.
530
+ * @param string $filename Optional. The name of the file to be saved to.
531
+ * @param string $mime_type Optional. The mimetype of the file.
532
+ * @return WP_Error|array The full path, base filename, and mimetype.
533
+ */
534
+ protected function _save_ewwwio_file( $image, $filename = null, $mime_type = null ) {
535
+ ewwwio_debug_message( '<b>wp_image_editor_gd::' . __FUNCTION__ . '()</b>' );
536
+ list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
537
+ if ( ! $filename ) {
538
+ $filename = $this->generate_filename( null, null, $extension );
539
+ }
540
+ if ( wp_is_stream( $filename ) ) {
541
+ $image = @imagecreatefromstring( $image );
542
+ unset( $this->ewww_image );
543
+ return parent::_save( $image, $filename, $mime_type );
544
+ }
545
+ if ( ! is_string( $image ) ) {
546
+ unset( $this->ewww_image );
547
+ return parent::_save( $image, $filename, $mime_type );
548
+ }
549
+ if ( ( ! defined( 'EWWWIO_EDITOR_OVERWRITE' ) || ! EWWWIO_EDITOR_OVERWRITE ) && is_file( $filename ) && empty( $ewww_preempt_editor ) ) {
550
+ ewwwio_debug_message( "detected existing file: $filename" );
551
+ $current_size = getimagesize( $filename );
552
+ if ( $current_size && $this->size['width'] == $current_size[0] && $this->size['height'] == $current_size[1] ) {
553
+ ewwwio_debug_message( "existing file has same dimensions, not saving $filename" );
554
+ return array(
555
+ 'path' => $filename,
556
+ 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
557
+ 'width' => $this->size['width'],
558
+ 'height' => $this->size['height'],
559
+ 'mime-type' => $mime_type,
560
+ );
561
+ }
562
+ }
563
+ // Write out the image (substitute for $this->make_image()).
564
+ wp_mkdir_p( dirname( $filename ) );
565
+ $result = file_put_contents( $filename, $image );
566
+ if ( $result ) {
567
+ ewwwio_debug_message( "image editor (gd-api-enhanced) saved: $filename" );
568
+ if ( is_writable( $filename ) ) {
569
+ $stat = stat( dirname( $filename ) );
570
+ $perms = $stat['mode'] & 0000666; // Same permissions as parent folder with executable bits stripped.
571
+ chmod( $filename, $perms );
572
+ }
573
+ ewwwio_memory( __FUNCTION__ );
574
+ return array(
575
+ 'path' => $filename,
576
+ 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
577
+ 'width' => $this->size['width'],
578
+ 'height' => $this->size['height'],
579
+ 'mime-type' => $mime_type,
580
+ );
581
+ }
582
+ ewwwio_memory( __FUNCTION__ );
583
+ return new WP_Error( 'image_save_error', __( 'Image Editor Save Failed' ) );
584
+ }
585
+
586
  /**
587
  * Saves a file from the image editor.
588
  *
589
+ * @since 1.7.0
590
+ *
591
  * @param resource $image A GD image object.
592
  * @param string $filename Optional. The name of the file to be saved to.
593
  * @param string $mime_type Optional. The mimetype of the file.
594
+ * @return WP_Error|array The full path, base filename, and mimetype.
595
  */
596
  protected function _save( $image, $filename = null, $mime_type = null ) {
597
  global $ewww_defer;
598
+ global $ewww_preempt_editor;
599
+ if ( ! empty( $this->ewww_image ) && empty( $this->modified ) ) {
600
+ return $this->_save_ewwwio_file( $this->ewww_image, $filename, $mime_type );
601
+ }
602
+ if ( ! empty( $ewww_preempt_editor ) ) {
603
+ return parent::_save( $image, $filename, $mime_type );
604
+ }
605
  list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
606
  if ( ! $filename ) {
607
  $filename = $this->generate_filename( null, null, $extension );
classes/class-ewwwio-gmagick-editor.php CHANGED
@@ -26,6 +26,10 @@ if ( class_exists( 'WP_Image_Editor_Gmagick' ) ) {
26
  */
27
  protected function _save( $image, $filename = null, $mime_type = null ) {
28
  global $ewww_defer;
 
 
 
 
29
  list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
30
  if ( ! $filename ) {
31
  $filename = $this->generate_filename( null, null, $extension );
26
  */
27
  protected function _save( $image, $filename = null, $mime_type = null ) {
28
  global $ewww_defer;
29
+ global $ewww_preempt_editor;
30
+ if ( ! empty( $ewww_preempt_editor ) ) {
31
+ return parent::_save( $image, $filename, $mime_type );
32
+ }
33
  list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
34
  if ( ! $filename ) {
35
  $filename = $this->generate_filename( null, null, $extension );
classes/class-ewwwio-imagick-editor.php CHANGED
@@ -26,6 +26,10 @@ if ( class_exists( 'WP_Thumb_Image_Editor_Imagick' ) ) {
26
  */
27
  protected function _save( $image, $filename = null, $mime_type = null ) {
28
  global $ewww_defer;
 
 
 
 
29
  list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
30
  if ( ! $filename ) {
31
  $filename = $this->generate_filename( null, null, $extension );
@@ -98,6 +102,10 @@ if ( class_exists( 'WP_Thumb_Image_Editor_Imagick' ) ) {
98
  */
99
  protected function _save( $image, $filename = null, $mime_type = null ) {
100
  global $ewww_defer;
 
 
 
 
101
  list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
102
  if ( ! $filename ) {
103
  $filename = $this->generate_filename( null, null, $extension );
@@ -170,6 +178,10 @@ if ( class_exists( 'WP_Thumb_Image_Editor_Imagick' ) ) {
170
  */
171
  protected function _save( $image, $filename = null, $mime_type = null ) {
172
  global $ewww_defer;
 
 
 
 
173
  list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
174
  if ( ! $filename ) {
175
  $filename = $this->generate_filename( null, null, $extension );
@@ -210,11 +222,24 @@ if ( class_exists( 'WP_Thumb_Image_Editor_Imagick' ) ) {
210
  }
211
  } elseif ( class_exists( 'S3_Uploads_Image_Editor_Imagick' ) ) {
212
  /**
213
- * Extension of the WP_Image_Editor_Imagick class to auto-compress edited images.
 
 
 
 
214
  *
215
  * @see WP_Image_Editor_Imagick
216
  */
217
  class EWWWIO_Imagick_Editor extends WP_Image_Editor_Imagick {
 
 
 
 
 
 
 
 
 
218
  /**
219
  * Saves a file from the image editor and sends it to S3 after optimization.
220
  *
@@ -224,6 +249,10 @@ if ( class_exists( 'WP_Thumb_Image_Editor_Imagick' ) ) {
224
  * @return WP_Error| array The full path, base filename, width, height, and mimetype.
225
  */
226
  protected function _save( $image, $filename = null, $mime_type = null ) {
 
 
 
 
227
  list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
228
  if ( ! $filename ) {
229
  $filename = $this->generate_filename( null, null, $extension );
@@ -246,18 +275,18 @@ if ( class_exists( 'WP_Thumb_Image_Editor_Imagick' ) ) {
246
  unset( $s3_uploads_image );
247
  return $saved;
248
  }
249
- if ( file_exists( $saved['path'] ) ) {
250
  $temp_filename = $saved['path'];
251
  ewww_image_optimizer( $temp_filename );
252
  ewwwio_debug_message( "image editor (s3 uploads) saved: $temp_filename" );
253
  $image_size = ewww_image_optimizer_filesize( $temp_filename );
254
  ewwwio_debug_message( "image editor size: $image_size" );
255
  }
256
- $copy_result = copy( $temp_filename, $filename );
257
- if ( file_exists( $saved['path'] ) ) {
258
  unlink( $saved['path'] );
259
  }
260
- if ( file_exists( $temp_filename ) ) {
261
  unlink( $temp_filename );
262
  }
263
  if ( ! $copy_result ) {
@@ -270,6 +299,50 @@ if ( class_exists( 'WP_Thumb_Image_Editor_Imagick' ) ) {
270
  ewwwio_memory( __FUNCTION__ );
271
  return $saved;
272
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
273
  }
274
  } else {
275
  /**
@@ -288,6 +361,10 @@ if ( class_exists( 'WP_Thumb_Image_Editor_Imagick' ) ) {
288
  */
289
  protected function _save( $image, $filename = null, $mime_type = null ) {
290
  global $ewww_defer;
 
 
 
 
291
  list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
292
  if ( ! $filename ) {
293
  $filename = $this->generate_filename( null, null, $extension );
26
  */
27
  protected function _save( $image, $filename = null, $mime_type = null ) {
28
  global $ewww_defer;
29
+ global $ewww_preempt_editor;
30
+ if ( ! empty( $ewww_preempt_editor ) ) {
31
+ return parent::_save( $image, $filename, $mime_type );
32
+ }
33
  list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
34
  if ( ! $filename ) {
35
  $filename = $this->generate_filename( null, null, $extension );
102
  */
103
  protected function _save( $image, $filename = null, $mime_type = null ) {
104
  global $ewww_defer;
105
+ global $ewww_preempt_editor;
106
+ if ( ! empty( $ewww_preempt_editor ) ) {
107
+ return parent::_save( $image, $filename, $mime_type );
108
+ }
109
  list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
110
  if ( ! $filename ) {
111
  $filename = $this->generate_filename( null, null, $extension );
178
  */
179
  protected function _save( $image, $filename = null, $mime_type = null ) {
180
  global $ewww_defer;
181
+ global $ewww_preempt_editor;
182
+ if ( ! empty( $ewww_preempt_editor ) ) {
183
+ return parent::_save( $image, $filename, $mime_type );
184
+ }
185
  list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
186
  if ( ! $filename ) {
187
  $filename = $this->generate_filename( null, null, $extension );
222
  }
223
  } elseif ( class_exists( 'S3_Uploads_Image_Editor_Imagick' ) ) {
224
  /**
225
+ * Extension of the WP_Image_Editor_Imagick class to auto-compress edited S3 images.
226
+ *
227
+ * We extend the WP class directly, because extending the S3 class would be too late to work.
228
+ * So we pretty much have to duplicate the S3 Uploads class with the IO function thrown in
229
+ * the middle: https://github.com/humanmade/S3-Uploads/blob/master/inc/class-s3-uploads-image-editor-imagick.php
230
  *
231
  * @see WP_Image_Editor_Imagick
232
  */
233
  class EWWWIO_Imagick_Editor extends WP_Image_Editor_Imagick {
234
+
235
+ /**
236
+ * A temp file created during pdf_setup().
237
+ *
238
+ * @since 4.4.0
239
+ * @var string $temp_file_to_cleanup
240
+ */
241
+ protected $temp_file_to_cleanup = null;
242
+
243
  /**
244
  * Saves a file from the image editor and sends it to S3 after optimization.
245
  *
249
  * @return WP_Error| array The full path, base filename, width, height, and mimetype.
250
  */
251
  protected function _save( $image, $filename = null, $mime_type = null ) {
252
+ global $ewww_preempt_editor;
253
+ if ( ! empty( $ewww_preempt_editor ) ) {
254
+ return parent::_save( $image, $filename, $mime_type );
255
+ }
256
  list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
257
  if ( ! $filename ) {
258
  $filename = $this->generate_filename( null, null, $extension );
275
  unset( $s3_uploads_image );
276
  return $saved;
277
  }
278
+ if ( is_file( $saved['path'] ) ) {
279
  $temp_filename = $saved['path'];
280
  ewww_image_optimizer( $temp_filename );
281
  ewwwio_debug_message( "image editor (s3 uploads) saved: $temp_filename" );
282
  $image_size = ewww_image_optimizer_filesize( $temp_filename );
283
  ewwwio_debug_message( "image editor size: $image_size" );
284
  }
285
+ $copy_result = copy( $saved['path'], $filename );
286
+ if ( is_file( $saved['path'] ) ) {
287
  unlink( $saved['path'] );
288
  }
289
+ if ( is_file( $temp_filename ) ) {
290
  unlink( $temp_filename );
291
  }
292
  if ( ! $copy_result ) {
299
  ewwwio_memory( __FUNCTION__ );
300
  return $saved;
301
  }
302
+
303
+ /**
304
+ * Custom loader for S3 Uploads.
305
+ *
306
+ * @since 4.4.0
307
+ *
308
+ * @return bool|WP_Error True on success, WP_Error on failure.
309
+ */
310
+ public function load() {
311
+ $result = parent::load();
312
+
313
+ // `load` can call pdf_setup() which has to copy the file to a temp local copy.
314
+ // In this event we want to clean it up once `load` has been completed.
315
+ if ( $this->temp_file_to_cleanup ) {
316
+ unlink( $this->temp_file_to_cleanup );
317
+ $this->temp_file_to_cleanup = null;
318
+ }
319
+ return $result;
320
+ }
321
+
322
+ /**
323
+ * Sets up Imagick for PDF processing.
324
+ * Increases rendering DPI and only loads first page.
325
+ *
326
+ * @since 4.4.0
327
+ *
328
+ * @return string|WP_Error File to load or WP_Error on failure.
329
+ */
330
+ protected function pdf_setup() {
331
+ $temp_filename = tempnam( get_temp_dir(), 's3-uploads' );
332
+ $this->temp_file_to_cleanup = $temp_filename;
333
+ copy( $this->file, $temp_filename );
334
+
335
+ try {
336
+ // By default, PDFs are rendered in a very low resolution.
337
+ // We want the thumbnail to be readable, so increase the rendering DPI.
338
+ $this->image->setResolution( 128, 128 );
339
+
340
+ // Only load the first page.
341
+ return $temp_filename . '[0]';
342
+ } catch ( Exception $e ) {
343
+ return new WP_Error( 'pdf_setup_failed', $e->getMessage(), $this->file );
344
+ }
345
+ }
346
  }
347
  } else {
348
  /**
361
  */
362
  protected function _save( $image, $filename = null, $mime_type = null ) {
363
  global $ewww_defer;
364
+ global $ewww_preempt_editor;
365
+ if ( ! empty( $ewww_preempt_editor ) ) {
366
+ return parent::_save( $image, $filename, $mime_type );
367
+ }
368
  list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
369
  if ( ! $filename ) {
370
  $filename = $this->generate_filename( null, null, $extension );
classes/class-ewwwio-install-cloud.php CHANGED
@@ -139,20 +139,23 @@ class EWWWIO_Install_Cloud {
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 {
139
  if ( ! function_exists( 'plugins_api' ) ) {
140
  require_once( ABSPATH . 'wp-admin/includes/plugin-install.php' );
141
  }
142
+ $response = plugins_api(
143
+ 'plugin_information',
144
+ array(
145
+ 'slug' => $this->plugin_slug,
146
+ 'fields' => array(
147
+ 'sections' => false,
148
+ 'short_description' => false,
149
+ 'downloaded' => false,
150
+ 'rating' => false,
151
+ 'ratings' => false,
152
+ 'tags' => false,
153
+ 'homepage' => false,
154
+ 'donate_link' => false,
155
+ 'added' => false,
156
+ ),
157
+ )
158
+ );
159
  if ( is_wp_error( $response ) ) {
160
  wp_die( esc_html( $response->get_error_message() ) );
161
  } else {
classes/class-ewwwio-tracking.php CHANGED
@@ -109,9 +109,12 @@ class EWWWIO_Tracking {
109
  $data['memory_limit'] = ewwwio_memory_limit();
110
  $data['time_limit'] = (int) ini_get( 'max_execution_time' );
111
  $data['operating_system'] = ewww_image_optimizer_function_exists( 'php_uname' ) ? php_uname( 's' ) : '';
 
 
 
112
 
113
  $data['cloud_api'] = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ? true : false;
114
- $data['keep_metadata'] = ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) ? false : true;
115
  $data['jpg_level'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' );
116
  $data['png_level'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' );
117
  $data['gif_level'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' );
@@ -119,6 +122,17 @@ class EWWWIO_Tracking {
119
  $data['bulk_delay'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_delay' );
120
  $data['backups'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_backup_files' );
121
 
 
 
 
 
 
 
 
 
 
 
 
122
  $data['optipng_level'] = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ? 0 : (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_optipng_level' );
123
  $data['disable_pngout'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_pngout' );
124
  $data['pngout_level'] = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ? 9 : (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_pngout_level' );
@@ -183,11 +197,14 @@ class EWWWIO_Tracking {
183
 
184
  $this->setup_data();
185
  ewwwio_debug_message( 'sending site data' );
186
- $request = wp_remote_post( 'https://stats.exactlywww.com/stats/report.php', array(
187
- 'timeout' => 5,
188
- 'body' => $this->data,
189
- 'user-agent' => 'EWWW/' . EWWW_IMAGE_OPTIMIZER_VERSION . '; ' . get_bloginfo( 'url' ),
190
- ) );
 
 
 
191
 
192
  ewwwio_debug_message( 'finished reporting' );
193
  if ( is_wp_error( $request ) ) {
109
  $data['memory_limit'] = ewwwio_memory_limit();
110
  $data['time_limit'] = (int) ini_get( 'max_execution_time' );
111
  $data['operating_system'] = ewww_image_optimizer_function_exists( 'php_uname' ) ? php_uname( 's' ) : '';
112
+ $data['image_library'] = ewww_image_optimizer_gd_support() ? 'gd' : '';
113
+ $data['image_library'] = ewww_image_optimizer_imagick_support() ? 'imagick' : '';
114
+ $data['image_library'] = ewww_image_optimizer_gmagick_support() ? 'gmagick' : '';
115
 
116
  $data['cloud_api'] = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ? true : false;
117
+ $data['keep_metadata'] = ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) ? false : true;
118
  $data['jpg_level'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' );
119
  $data['png_level'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' );
120
  $data['gif_level'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' );
122
  $data['bulk_delay'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_delay' );
123
  $data['backups'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_backup_files' );
124
 
125
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) && class_exists( 'ExactDN' ) ) {
126
+ global $exactdn;
127
+ if ( $exactdn->get_exactdn_domain() ) {
128
+ $data['exactdn_lossy'] = (int) ewww_image_optimizer_get_option( 'exactdn_lossy' );
129
+ $data['exactdn_all_the_things'] = (bool) ewww_image_optimizer_get_option( 'exactdn_all_the_things' );
130
+ $data['exactdn_resize_existing'] = (bool) ewww_image_optimizer_get_option( 'exactdn_resize_existing' );
131
+ $data['exactdn_prevent_db_queries'] = (bool) ewww_image_optimizer_get_option( 'exactdn_prevent_db_queries' );
132
+ $data['exactdn_prevent_srcset_fill'] = (bool) ewww_image_optimizer_get_option( 'exactdn_prevent_srcset_fill' );
133
+ }
134
+ }
135
+
136
  $data['optipng_level'] = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ? 0 : (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_optipng_level' );
137
  $data['disable_pngout'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_pngout' );
138
  $data['pngout_level'] = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ? 9 : (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_pngout_level' );
197
 
198
  $this->setup_data();
199
  ewwwio_debug_message( 'sending site data' );
200
+ $request = wp_remote_post(
201
+ 'https://stats.exactlywww.com/stats/report.php',
202
+ array(
203
+ 'timeout' => 5,
204
+ 'body' => $this->data,
205
+ 'user-agent' => 'EWWW/' . EWWW_IMAGE_OPTIMIZER_VERSION . '; ' . get_bloginfo( 'url' ),
206
+ )
207
+ );
208
 
209
  ewwwio_debug_message( 'finished reporting' );
210
  if ( is_wp_error( $request ) ) {
classes/class-exactdn.php CHANGED
@@ -255,12 +255,15 @@ class ExactDN extends EWWWIO_Page_Parser {
255
  $url = set_url_scheme( $url, 'https' );
256
  }
257
  add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
258
- $result = wp_remote_post( $url, array(
259
- 'timeout' => 10,
260
- 'body' => array(
261
- 'site_url' => $site_url,
262
- ),
263
- ) );
 
 
 
264
  if ( is_wp_error( $result ) ) {
265
  $error_message = $result->get_error_message();
266
  ewwwio_debug_message( "exactdn activation request failed: $error_message" );
@@ -337,12 +340,15 @@ class ExactDN extends EWWWIO_Page_Parser {
337
  $url = set_url_scheme( $url, 'https' );
338
  }
339
  add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
340
- $result = wp_remote_post( $url, array(
341
- 'timeout' => 10,
342
- 'body' => array(
343
- 'alias' => $domain,
344
- ),
345
- ) );
 
 
 
346
  if ( is_wp_error( $result ) ) {
347
  $error_message = $result->get_error_message();
348
  ewwwio_debug_message( "exactdn verification request failed: $error_message" );
@@ -531,6 +537,49 @@ class ExactDN extends EWWWIO_Page_Parser {
531
  return apply_filters( 'exactdn_content_width', $content_width );
532
  }
533
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
534
  /**
535
  * Starts an output buffer and registers the callback function to do ExactDN url replacement.
536
  */
@@ -587,9 +636,6 @@ class ExactDN extends EWWWIO_Page_Parser {
587
  // Flag if we need to munge a fullsize URL.
588
  $fullsize_url = false;
589
 
590
- // To be stored and used for later srcset generation.
591
- $original_width = 0;
592
-
593
  // Identify image source.
594
  $src = $images['img_url'][ $index ];
595
  $src_orig = $images['img_url'][ $index ];
@@ -631,15 +677,11 @@ class ExactDN extends EWWWIO_Page_Parser {
631
  ewwwio_debug_message( 'url validated' );
632
 
633
  // Find the width and height attributes.
634
- // First, check the image tag.
635
- $width = $this->get_attribute( $images['img_tag'][ $index ], 'width' );
636
- // Then check for an inline max-width directive.
637
- if ( preg_match( '#max-width:\s?(\d+)px#', $images['img_tag'][ $index ], $max_width_string ) ) {
638
- if ( $max_width_string[1] && ( ! $width || $max_width_string[1] < $width ) ) {
639
- $width = $max_width_string[1];
640
- }
641
- }
642
  $height = $this->get_attribute( $images['img_tag'][ $index ], 'height' );
 
 
 
643
 
644
  // Can't pass both a relative width and height, so unset the dimensions in favor of not breaking the horizontal layout.
645
  if ( false !== strpos( $width, '%' ) && false !== strpos( $height, '%' ) ) {
@@ -698,7 +740,6 @@ class ExactDN extends EWWWIO_Page_Parser {
698
  }
699
 
700
  if ( $src_per_wp && $this->validate_image_url( $src_per_wp[0] ) ) {
701
- $original_width = $src_per_wp[1];
702
  ewwwio_debug_message( "detected $width filenamew $filename_width" );
703
  if ( $resize_existing || ( $width && $filename_width != $width ) ) {
704
  ewwwio_debug_message( 'resizing existing or width does not match' );
@@ -826,7 +867,7 @@ class ExactDN extends EWWWIO_Page_Parser {
826
  }
827
 
828
  // Supplant the original source value with our ExactDN URL.
829
- $exactdn_url = esc_url( $exactdn_url );
830
  $new_tag = str_replace( $src_orig, $exactdn_url, $new_tag );
831
 
832
  // If Lazy Load is in use, pass placeholder image through ExactDN.
@@ -834,7 +875,7 @@ class ExactDN extends EWWWIO_Page_Parser {
834
  $placeholder_src = $this->generate_url( $placeholder_src );
835
 
836
  if ( $placeholder_src != $placeholder_src_orig ) {
837
- $new_tag = str_replace( $placeholder_src_orig, esc_url( $placeholder_src ), $new_tag );
838
  }
839
 
840
  unset( $placeholder_src );
@@ -846,22 +887,15 @@ class ExactDN extends EWWWIO_Page_Parser {
846
  } elseif ( ! preg_match( '#data-lazy-(original|src)=#i', $images['img_tag'][ $index ] ) && $this->validate_image_url( $src, true ) ) {
847
  ewwwio_debug_message( 'found a potential exactdn src url to insert into srcset' );
848
  // Find the width attribute.
849
- $width = $this->get_attribute( $tag, 'width' );
850
- // First, check the image tag.
851
  if ( $width ) {
852
- $width = $width_string[1];
853
  ewwwio_debug_message( 'found the width' );
854
  // Insert new image src into the srcset as well, if we have a width.
855
  if (
856
  false !== $width &&
857
  false === strpos( $width, '%' ) &&
858
  false !== strpos( $src, $width ) &&
859
- (
860
- false !== strpos( $src, 'exactdn.com' ) ||
861
- false !== strpos( $src, 'exactdn.net' ) ||
862
- false !== strpos( $src, 'exactcdn.com' ) ||
863
- false !== strpos( $src, 'exactcdn.net' )
864
- )
865
  ) {
866
  $new_tag = $tag;
867
  $exactdn_url = $src;
@@ -879,16 +913,40 @@ class ExactDN extends EWWWIO_Page_Parser {
879
  }
880
  }
881
  } // End if().
882
- if ( ! preg_match( '#data-lazy-(original|src)=#i', $images['img_tag'][ $index ] ) && $this->validate_image_url( $src, true ) ) {
 
 
 
 
883
  if ( ! $this->get_attribute( $images['img_tag'][ $index ], 'srcset' ) && ! $this->get_attribute( $images['img_tag'][ $index ], 'sizes' ) ) {
884
- list( $filename_width, $filename_height ) = $this->get_dimensions_from_filename( $src );
885
- // Alright, we look for $filename_width or $original_width, otherwise try to grok the dimensions if it's a local image.
886
- // Also need to somehow check to be sure we don't end up with anything larger than the width as configured above...
887
- // --perhaps that can be accomplished just by ensuring all srcset images are smaller than $width.
888
- // --probably only way that happens is if the $fullsize_url is used/found.
 
 
 
 
 
 
 
 
 
 
 
 
 
889
  // Then add a srcset and sizes.
890
- if ( $width ) { // We somehow have to get the actual width of the image, this is mandatory for srcset calculation.
891
- } else {
 
 
 
 
 
 
 
892
  }
893
  }
894
  }
@@ -1431,6 +1489,77 @@ class ExactDN extends EWWWIO_Page_Parser {
1431
  return sprintf( '(max-width: %1$dpx) 100vw, %1$dpx', $content_width );
1432
  }
1433
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1434
  /**
1435
  * Check for smart-cropping plugin to adjust cropping parameters.
1436
  * Currently supports Theia Smart Thumbnails using the theiaSmartThumbnails_position meta.
@@ -1545,12 +1674,15 @@ class ExactDN extends EWWWIO_Page_Parser {
1545
  }
1546
 
1547
  // Parse URL and ensure needed keys exist, since the array returned by `parse_url` only includes the URL components it finds.
1548
- $url_info = wp_parse_args( $parsed_url, array(
1549
- 'scheme' => null,
1550
- 'host' => null,
1551
- 'port' => null,
1552
- 'path' => null,
1553
- ) );
 
 
 
1554
 
1555
  // Bail if scheme isn't http or port is set that isn't port 80.
1556
  if (
@@ -1573,19 +1705,7 @@ class ExactDN extends EWWWIO_Page_Parser {
1573
  }
1574
 
1575
  // Bail if the image already went through ExactDN.
1576
- if ( ! $exactdn_is_valid && strpos( $url_info['host'], '.exactdn.com' ) ) {
1577
- ewwwio_debug_message( 'exactdn image' );
1578
- return false;
1579
- }
1580
- if ( ! $exactdn_is_valid && strpos( $url_info['host'], '.exactdn.net' ) ) {
1581
- ewwwio_debug_message( 'exactdn image' );
1582
- return false;
1583
- }
1584
- if ( ! $exactdn_is_valid && strpos( $url_info['host'], '.exactcdn.com' ) ) {
1585
- ewwwio_debug_message( 'exactdn image' );
1586
- return false;
1587
- }
1588
- if ( ! $exactdn_is_valid && strpos( $url_info['host'], '.exactcdn.net' ) ) {
1589
  ewwwio_debug_message( 'exactdn image' );
1590
  return false;
1591
  }
@@ -1919,7 +2039,7 @@ class ExactDN extends EWWWIO_Page_Parser {
1919
  $webp_quality = apply_filters( 'jpeg_quality', $jpg_quality, 'image/webp' );
1920
 
1921
  $more_args = array();
1922
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) ) {
1923
  $more_args['strip'] = 'all';
1924
  }
1925
  if ( ewww_image_optimizer_get_option( 'exactdn_lossy' ) ) {
255
  $url = set_url_scheme( $url, 'https' );
256
  }
257
  add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
258
+ $result = wp_remote_post(
259
+ $url,
260
+ array(
261
+ 'timeout' => 10,
262
+ 'body' => array(
263
+ 'site_url' => $site_url,
264
+ ),
265
+ )
266
+ );
267
  if ( is_wp_error( $result ) ) {
268
  $error_message = $result->get_error_message();
269
  ewwwio_debug_message( "exactdn activation request failed: $error_message" );
340
  $url = set_url_scheme( $url, 'https' );
341
  }
342
  add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
343
+ $result = wp_remote_post(
344
+ $url,
345
+ array(
346
+ 'timeout' => 10,
347
+ 'body' => array(
348
+ 'alias' => $domain,
349
+ ),
350
+ )
351
+ );
352
  if ( is_wp_error( $result ) ) {
353
  $error_message = $result->get_error_message();
354
  ewwwio_debug_message( "exactdn verification request failed: $error_message" );
537
  return apply_filters( 'exactdn_content_width', $content_width );
538
  }
539
 
540
+ /**
541
+ * Get the width from an image element.
542
+ *
543
+ * @param string $img The full image element.
544
+ * @return string The width found or an empty string.
545
+ */
546
+ public function get_img_width( $img ) {
547
+ $width = $this->get_attribute( $img, 'width' );
548
+ // Then check for an inline max-width directive.
549
+ if ( preg_match( '#max-width:\s?(\d+)px#', $img, $max_width_string ) ) {
550
+ if ( $max_width_string[1] && ( ! $width || $max_width_string[1] < $width ) ) {
551
+ $width = $max_width_string[1];
552
+ }
553
+ }
554
+ return $width;
555
+ }
556
+
557
+ /**
558
+ * Get width within an ExactDN url.
559
+ *
560
+ * @param string $url The ExactDN url to parse.
561
+ * @return string The width, if found.
562
+ */
563
+ public function get_exactdn_width_from_url( $url ) {
564
+ $url_args = $this->parse_url( $url, PHP_URL_QUERY );
565
+ if ( ! $url_args ) {
566
+ return '';
567
+ }
568
+ $args = explode( '&', $url_args );
569
+ foreach ( $args as $arg ) {
570
+ if ( preg_match( '#w=(\d+)#', $arg, $width_match ) ) {
571
+ return $width_match[1];
572
+ }
573
+ if ( preg_match( '#resize=(\d+)#', $arg, $width_match ) ) {
574
+ return $width_match[1];
575
+ }
576
+ if ( preg_match( '#fit=(\d+)#', $arg, $width_match ) ) {
577
+ return $width_match[1];
578
+ }
579
+ }
580
+ return '';
581
+ }
582
+
583
  /**
584
  * Starts an output buffer and registers the callback function to do ExactDN url replacement.
585
  */
636
  // Flag if we need to munge a fullsize URL.
637
  $fullsize_url = false;
638
 
 
 
 
639
  // Identify image source.
640
  $src = $images['img_url'][ $index ];
641
  $src_orig = $images['img_url'][ $index ];
677
  ewwwio_debug_message( 'url validated' );
678
 
679
  // Find the width and height attributes.
680
+ $width = $this->get_img_width( $images['img_tag'][ $index ] );
 
 
 
 
 
 
 
681
  $height = $this->get_attribute( $images['img_tag'][ $index ], 'height' );
682
+ // Falsify them if empty.
683
+ $width = $width ? $width : false;
684
+ $height = $height ? $height : false;
685
 
686
  // Can't pass both a relative width and height, so unset the dimensions in favor of not breaking the horizontal layout.
687
  if ( false !== strpos( $width, '%' ) && false !== strpos( $height, '%' ) ) {
740
  }
741
 
742
  if ( $src_per_wp && $this->validate_image_url( $src_per_wp[0] ) ) {
 
743
  ewwwio_debug_message( "detected $width filenamew $filename_width" );
744
  if ( $resize_existing || ( $width && $filename_width != $width ) ) {
745
  ewwwio_debug_message( 'resizing existing or width does not match' );
867
  }
868
 
869
  // Supplant the original source value with our ExactDN URL.
870
+ $exactdn_url = str_replace( '&#038;', '&', esc_url( $exactdn_url ) );
871
  $new_tag = str_replace( $src_orig, $exactdn_url, $new_tag );
872
 
873
  // If Lazy Load is in use, pass placeholder image through ExactDN.
875
  $placeholder_src = $this->generate_url( $placeholder_src );
876
 
877
  if ( $placeholder_src != $placeholder_src_orig ) {
878
+ $new_tag = str_replace( $placeholder_src_orig, str_replace( '&#038;', '&', esc_url( $placeholder_src ) ), $new_tag );
879
  }
880
 
881
  unset( $placeholder_src );
887
  } elseif ( ! preg_match( '#data-lazy-(original|src)=#i', $images['img_tag'][ $index ] ) && $this->validate_image_url( $src, true ) ) {
888
  ewwwio_debug_message( 'found a potential exactdn src url to insert into srcset' );
889
  // Find the width attribute.
890
+ $width = $this->get_img_width( $images['img_tag'][ $index ] );
 
891
  if ( $width ) {
 
892
  ewwwio_debug_message( 'found the width' );
893
  // Insert new image src into the srcset as well, if we have a width.
894
  if (
895
  false !== $width &&
896
  false === strpos( $width, '%' ) &&
897
  false !== strpos( $src, $width ) &&
898
+ false !== strpos( $src, $this->exactdn_domain )
 
 
 
 
 
899
  ) {
900
  $new_tag = $tag;
901
  $exactdn_url = $src;
913
  }
914
  }
915
  } // End if().
916
+ // At this point, we discard the original src in favor of the ExactDN url.
917
+ if ( ! empty( $exactdn_url ) ) {
918
+ $src = $exactdn_url;
919
+ }
920
+ if ( ! ewww_image_optimizer_get_option( 'exactdn_prevent_srcset_fill' ) && ! preg_match( '#data-lazy-(original|src)=#i', $images['img_tag'][ $index ] ) && false !== strpos( $src, $this->exactdn_domain ) ) {
921
  if ( ! $this->get_attribute( $images['img_tag'][ $index ], 'srcset' ) && ! $this->get_attribute( $images['img_tag'][ $index ], 'sizes' ) ) {
922
+ $zoom = false;
923
+ // If $width is empty, we'll search the url for a width param, then we try searching the img element, with fall back to the filename.
924
+ if ( empty( $width ) ) {
925
+ // This only searches for w, resize, or fit flags, others are ignored.
926
+ $width = $this->get_exactdn_width_from_url( $src );
927
+ if ( $width ) {
928
+ $zoom = true;
929
+ }
930
+ }
931
+ if ( empty( $width ) ) {
932
+ $width = $this->get_img_width( $images['img_tag'][ $index ] );
933
+ }
934
+ if ( empty( $width ) ) {
935
+ list( $width, $discard_height ) = $this->get_dimensions_from_filename( $src );
936
+ }
937
+ if ( false !== strpos( $src, 'crop=' ) || false !== strpos( $src, '&h=' ) || false !== strpos( $src, '?h=' ) ) {
938
+ $width = false;
939
+ }
940
  // Then add a srcset and sizes.
941
+ if ( $width ) {
942
+ $srcset = $this->generate_image_srcset( $src, $width, $zoom );
943
+ if ( $srcset ) {
944
+ $new_tag = $images['img_tag'][ $index ];
945
+ $this->set_attribute( $new_tag, 'srcset', $srcset );
946
+ $this->set_attribute( $new_tag, 'sizes', sprintf( '(max-width: %1$dpx) 100vw, %1$dpx', $width ) );
947
+ // Replace original tag with modified version.
948
+ $content = str_replace( $images['img_tag'][ $index ], $new_tag, $content );
949
+ }
950
  }
951
  }
952
  }
1489
  return sprintf( '(max-width: %1$dpx) 100vw, %1$dpx', $content_width );
1490
  }
1491
 
1492
+ /**
1493
+ * Creates an image `srcset` attribute based on the detected width.
1494
+ *
1495
+ * @param string $url The url of the image.
1496
+ * @param int $width Image width to use for calculations.
1497
+ * @param bool $zoom Whether to use zoom or w param.
1498
+ * @uses this::validate_image_url, this::generate_url, this::parse_from_filename
1499
+ * @uses this::strip_image_dimensions_maybe, this::get_content_width
1500
+ * @return string A srcset attribute with ExactDN image urls and widths.
1501
+ */
1502
+ public function generate_image_srcset( $url, $width, $zoom = false ) {
1503
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1504
+ // Don't foul up the admin side of things.
1505
+ if ( is_admin() ) {
1506
+ return '';
1507
+ }
1508
+
1509
+ /**
1510
+ * Filter the multiplier ExactDN uses to create new srcset items.
1511
+ * Return false to short-circuit and bypass auto-generation.
1512
+ *
1513
+ * @param array|bool $multipliers Array of multipliers to use or false to bypass.
1514
+ */
1515
+ $multipliers = apply_filters( 'exactdn_srcset_multipliers', array( .2, .4, .6, .8, 1, 2, 3 ) );
1516
+ /**
1517
+ * Filter the width ExactDN will use to create srcset attribute.
1518
+ * Return a falsy value to short-circuit and bypass srcset fill.
1519
+ *
1520
+ * @param int|bool $width The max width for this $url, or false to bypass.
1521
+ */
1522
+ $width = apply_filters( 'exactdn_srcset_fill_width', $width, $url );
1523
+ $srcset = '';
1524
+
1525
+ if (
1526
+ /** Short-circuit via exactdn_srcset_multipliers filter. */
1527
+ is_array( $multipliers )
1528
+ && $width
1529
+ /** This filter is already documented in class-exactdn.php */
1530
+ && ! apply_filters( 'exactdn_skip_image', false, $url, null )
1531
+ ) {
1532
+ $sources = null;
1533
+
1534
+ foreach ( $multipliers as $multiplier ) {
1535
+ $newwidth = intval( $width * $multiplier );
1536
+
1537
+ if ( $zoom ) {
1538
+ $args = array(
1539
+ 'zoom' => $multiplier,
1540
+ );
1541
+ } else {
1542
+ $args = array(
1543
+ 'w' => $newwidth,
1544
+ );
1545
+ }
1546
+
1547
+ $sources[ $newwidth ] = array(
1548
+ 'url' => $this->generate_url( $url, $args ),
1549
+ 'descriptor' => 'w',
1550
+ 'value' => $newwidth,
1551
+ );
1552
+ }
1553
+ }
1554
+ if ( ! empty( $sources ) ) {
1555
+ foreach ( $sources as $source ) {
1556
+ $srcset .= str_replace( ' ', '%20', $source['url'] ) . ' ' . $source['value'] . $source['descriptor'] . ', ';
1557
+ }
1558
+ }
1559
+ /* ewwwio_debug_message( print_r( $sources, true ) ); */
1560
+ return rtrim( $srcset, ', ' );
1561
+ }
1562
+
1563
  /**
1564
  * Check for smart-cropping plugin to adjust cropping parameters.
1565
  * Currently supports Theia Smart Thumbnails using the theiaSmartThumbnails_position meta.
1674
  }
1675
 
1676
  // Parse URL and ensure needed keys exist, since the array returned by `parse_url` only includes the URL components it finds.
1677
+ $url_info = wp_parse_args(
1678
+ $parsed_url,
1679
+ array(
1680
+ 'scheme' => null,
1681
+ 'host' => null,
1682
+ 'port' => null,
1683
+ 'path' => null,
1684
+ )
1685
+ );
1686
 
1687
  // Bail if scheme isn't http or port is set that isn't port 80.
1688
  if (
1705
  }
1706
 
1707
  // Bail if the image already went through ExactDN.
1708
+ if ( ! $exactdn_is_valid && $this->exactdn_domain === $url_info['host'] ) {
 
 
 
 
 
 
 
 
 
 
 
 
1709
  ewwwio_debug_message( 'exactdn image' );
1710
  return false;
1711
  }
2039
  $webp_quality = apply_filters( 'jpeg_quality', $jpg_quality, 'image/webp' );
2040
 
2041
  $more_args = array();
2042
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) ) {
2043
  $more_args['strip'] = 'all';
2044
  }
2045
  if ( ewww_image_optimizer_get_option( 'exactdn_lossy' ) ) {
common.php CHANGED
@@ -11,17 +11,13 @@
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?
@@ -29,7 +25,7 @@ if ( ! defined( 'ABSPATH' ) ) {
29
  exit;
30
  }
31
 
32
- define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '432.0' );
33
 
34
  // Initialize a couple globals.
35
  $ewww_debug = '';
@@ -123,6 +119,10 @@ add_filter( 'load_image_to_edit_path', 'ewww_image_optimizer_editor_save_pre' );
123
  add_filter( 'jpeg_quality', 'ewww_image_optimizer_set_jpg_quality' );
124
  // Makes sure the plugin bypasses any files affected by the Folders to Ignore setting.
125
  add_filter( 'ewww_image_optimizer_bypass', 'ewww_image_optimizer_ignore_file', 10, 2 );
 
 
 
 
126
  // Loads the plugin translations.
127
  add_action( 'plugins_loaded', 'ewww_image_optimizer_preinit' );
128
  // Checks for nextgen/nextcellent/flagallery existence, and loads the appropriate classes.
@@ -488,6 +488,10 @@ function ewww_image_optimizer_upgrade() {
488
  ewww_image_optimizer_enable_background_optimization();
489
  ewww_image_optimizer_install_table();
490
  ewww_image_optimizer_set_defaults();
 
 
 
 
491
  // This will get re-enabled if things are too slow.
492
  ewww_image_optimizer_set_option( 'exactdn_prevent_db_queries', false );
493
  delete_option( 'ewww_image_optimizer_exactdn_verify_method' );
@@ -510,6 +514,9 @@ function ewww_image_optimizer_upgrade() {
510
  if ( get_option( 'ewww_image_optimizer_version' ) < 407 ) {
511
  add_site_option( 'exactdn_all_the_things', true );
512
  }
 
 
 
513
  ewww_image_optimizer_remove_obsolete_settings();
514
  update_option( 'ewww_image_optimizer_version', EWWW_IMAGE_OPTIMIZER_VERSION );
515
  }
@@ -537,9 +544,7 @@ function ewww_image_optimizer_enable_background_optimization() {
537
  }
538
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_background_optimization', false );
539
  ewwwio_debug_message( 'running test async handler' );
540
- $ewwwio_test_async->data( array(
541
- 'ewwwio_test_verify' => '949c34123cf2a4e4ce2f985135830df4a1b2adc24905f53d2fd3f5df5b162932',
542
- ) )->dispatch();
543
  ewww_image_optimizer_debug_log();
544
  }
545
 
@@ -583,8 +588,8 @@ function ewww_image_optimizer_admin_init() {
583
  update_site_option( 'ewww_image_optimizer_cloud_key', ewww_image_optimizer_cloud_key_sanitize( $_POST['ewww_image_optimizer_cloud_key'] ) );
584
  $_POST['ewww_image_optimizer_debug'] = ( empty( $_POST['ewww_image_optimizer_debug'] ) ? false : true );
585
  update_site_option( 'ewww_image_optimizer_debug', $_POST['ewww_image_optimizer_debug'] );
586
- $_POST['ewww_image_optimizer_jpegtran_copy'] = ( empty( $_POST['ewww_image_optimizer_jpegtran_copy'] ) ? false : true );
587
- update_site_option( 'ewww_image_optimizer_jpegtran_copy', $_POST['ewww_image_optimizer_jpegtran_copy'] );
588
  $_POST['ewww_image_optimizer_jpg_level'] = empty( $_POST['ewww_image_optimizer_jpg_level'] ) ? '' : $_POST['ewww_image_optimizer_jpg_level'];
589
  update_site_option( 'ewww_image_optimizer_jpg_level', (int) $_POST['ewww_image_optimizer_jpg_level'] );
590
  $_POST['ewww_image_optimizer_png_level'] = empty( $_POST['ewww_image_optimizer_png_level'] ) ? '' : $_POST['ewww_image_optimizer_png_level'];
@@ -621,6 +626,10 @@ function ewww_image_optimizer_admin_init() {
621
  update_site_option( 'ewww_image_optimizer_enable_cloudinary', $_POST['ewww_image_optimizer_enable_cloudinary'] );
622
  $_POST['ewww_image_optimizer_exactdn'] = ( empty( $_POST['ewww_image_optimizer_exactdn'] ) ? false : true );
623
  update_site_option( 'ewww_image_optimizer_exactdn', $_POST['ewww_image_optimizer_exactdn'] );
 
 
 
 
624
  $_POST['ewww_image_optimizer_maxmediawidth'] = empty( $_POST['ewww_image_optimizer_maxmediawidth'] ) ? 0 : $_POST['ewww_image_optimizer_maxmediawidth'];
625
  update_site_option( 'ewww_image_optimizer_maxmediawidth', (int) $_POST['ewww_image_optimizer_maxmediawidth'] );
626
  $_POST['ewww_image_optimizer_maxmediaheight'] = empty( $_POST['ewww_image_optimizer_maxmediaheight'] ) ? 0 : $_POST['ewww_image_optimizer_maxmediaheight'];
@@ -667,7 +676,7 @@ function ewww_image_optimizer_admin_init() {
667
  update_option( 'ewww_image_optimizer_disable_pngout', true );
668
  update_option( 'ewww_image_optimizer_optipng_level', 2 );
669
  update_option( 'ewww_image_optimizer_pngout_level', 2 );
670
- update_option( 'ewww_image_optimizer_jpegtran_copy', true );
671
  update_option( 'ewww_image_optimizer_jpg_level', '10' );
672
  update_option( 'ewww_image_optimizer_png_level', '10' );
673
  update_option( 'ewww_image_optimizer_gif_level', '10' );
@@ -675,7 +684,7 @@ function ewww_image_optimizer_admin_init() {
675
  // Register all the common EWWW IO settings.
676
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_cloud_key', 'ewww_image_optimizer_cloud_key_sanitize' );
677
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_debug', 'boolval' );
678
- register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_jpegtran_copy', 'boolval' );
679
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_jpg_level', 'intval' );
680
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_png_level', 'intval' );
681
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_gif_level', 'intval' );
@@ -692,6 +701,8 @@ function ewww_image_optimizer_admin_init() {
692
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_allow_tracking', array( $ewwwio_tracking, 'check_for_settings_optin' ) );
693
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_enable_help', 'boolval' );
694
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_exactdn', 'boolval' );
 
 
695
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_resize_detection', 'boolval' );
696
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxmediawidth', 'intval' );
697
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxmediaheight', 'intval' );
@@ -744,10 +755,10 @@ function ewww_image_optimizer_admin_init() {
744
  }
745
  ewww_image_optimizer_privacy_policy_content();
746
  ewww_image_optimizer_ajax_compat_check();
747
- // Remove the false when the next bump is coming.
748
- if ( defined( 'PHP_VERSION_ID' ) && PHP_VERSION_ID < 50500 ) {
749
- add_action( 'network_admin_notices', 'ewww_image_optimizer_php54_warning' );
750
- add_action( 'admin_notices', 'ewww_image_optimizer_php54_warning' );
751
  }
752
  ewwwio_memory( __FUNCTION__ );
753
  }
@@ -813,7 +824,9 @@ function ewww_image_optimizer_ajax_compat_check() {
813
  if ( ! empty( $_POST['iw-action'] ) ) {
814
  $action = $_POST['iw-action'];
815
  ewwwio_debug_message( "doing $action" );
816
- remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
 
 
817
  if ( 'applywatermark' === $action ) {
818
  remove_filter( 'wp_generate_attachment_metadata', 'ewww_image_optimizer_resize_from_meta_data', 15 );
819
  add_action( 'iw_after_apply_watermark', 'ewww_image_optimizer_single_size_optimize', 10, 2 );
@@ -847,7 +860,7 @@ function ewww_image_optimizer_privacy_policy_content() {
847
  if ( ! defined( 'EWWW_IO_CLOUD_PLUGIN' ) || ! EWWW_IO_CLOUD_PLUGIN ) {
848
  $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>';
849
  }
850
- $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>';
851
  $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>';
852
  $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>';
853
  wp_add_privacy_policy_content( 'EWWW Image Optimizer', $content );
@@ -1297,16 +1310,17 @@ function ewww_image_optimizer_pngout_installed() {
1297
  '<p>' . sprintf(
1298
  /* translators: 1: An error message 2: The folder where pngout should be installed */
1299
  esc_html__( 'Pngout was not installed: %1$s. Make sure this folder is writable: %2$s', 'ewww-image-optimizer' ),
1300
- sanitize_text_field( $_REQUEST['ewww_error'] ), EWWW_IMAGE_OPTIMIZER_TOOL_PATH
 
1301
  ) . "</p>\n" .
1302
  "</div>\n";
1303
  }
1304
  }
1305
  /**
1306
- * Display a notice that PHP version 5.4 support is going away.
1307
  */
1308
- function ewww_image_optimizer_php54_warning() {
1309
- 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>';
1310
  }
1311
 
1312
  /**
@@ -1427,7 +1441,9 @@ function ewww_image_optimizer_add_attachment() {
1427
  */
1428
  function ewww_image_optimizer_image_sizes( $sizes ) {
1429
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1430
- remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
 
 
1431
  // This happens right after thumbs and meta are generated.
1432
  add_filter( 'wp_generate_attachment_metadata', 'ewww_image_optimizer_restore_editor_hooks', 1 );
1433
  add_filter( 'mpp_generate_metadata', 'ewww_image_optimizer_restore_editor_hooks', 1 );
@@ -1445,7 +1461,9 @@ function ewww_image_optimizer_image_sizes( $sizes ) {
1445
  function ewww_image_optimizer_restore_editor_hooks( $metadata = false ) {
1446
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1447
  if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_noauto' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_editor' ) ) {
1448
- add_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
 
 
1449
  }
1450
  if ( function_exists( 'wr2x_wp_generate_attachment_metadata' ) ) {
1451
  remove_filter( 'wp_generate_attachment_metadata', 'wr2x_wp_generate_attachment_metadata' );
@@ -1473,7 +1491,9 @@ function ewww_image_optimizer_restore_editor_hooks( $metadata = false ) {
1473
  function ewww_image_optimizer_editor_save_pre( $image ) {
1474
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1475
  if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_noauto' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_editor' ) ) {
1476
- remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
 
 
1477
  add_filter( 'wp_update_attachment_metadata', 'ewww_image_optimizer_restore_editor_hooks', 1 );
1478
  add_filter( 'wp_update_attachment_metadata', 'ewww_image_optimizer_resize_from_meta_data', 15, 2 );
1479
  }
@@ -1519,7 +1539,8 @@ function ewww_image_optimizer_path_renamed( $post, $old_filepath, $new_filepath
1519
  }
1520
  ewwwio_debug_message( "$old_filepath changed to $new_filepath" );
1521
  // Replace the 'temp' path in the database with the real path.
1522
- $ewwwdb->update( $ewwwdb->ewwwio_images,
 
1523
  array(
1524
  'path' => ewww_image_optimizer_relative_path_remove( $new_filepath ),
1525
  ),
@@ -1549,7 +1570,9 @@ function ewww_image_optimizer_retina_wrapper( $meta ) {
1549
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_noauto' ) || ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_editor' ) ) {
1550
  return $meta;
1551
  }
1552
- remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
 
 
1553
  if ( class_exists( 'Meow_WR2X_Core' ) ) {
1554
  global $wr2x_core;
1555
  if ( is_object( $wr2x_core ) ) {
@@ -1558,7 +1581,8 @@ function ewww_image_optimizer_retina_wrapper( $meta ) {
1558
  } else {
1559
  $meta = wr2x_wp_generate_attachment_metadata( $meta );
1560
  }
1561
- add_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
 
1562
  return $meta;
1563
  }
1564
 
@@ -1735,12 +1759,10 @@ function ewww_image_optimizer_w3tc_update_files( $files ) {
1735
  * @return array|bool Information about the uploads dir, or false on failure.
1736
  */
1737
  function ewww_image_optimizer_upload_info() {
1738
- $upload_info = @wp_upload_dir( null, false );
1739
 
1740
  if ( empty( $upload_info['error'] ) ) {
1741
- // Errors silenced because of PHP < 5.3.3, yuck.
1742
- $parse_url = @parse_url( $upload_info['baseurl'] );
1743
-
1744
  if ( $parse_url ) {
1745
  $baseurlpath = ( ! empty( $parse_url['path'] ) ? trim( $parse_url['path'], '/' ) : '' );
1746
  } else {
@@ -1985,7 +2007,8 @@ function ewww_image_optimizer_retina( $id, $retina_path ) {
1985
  $ewwwdb = $wpdb;
1986
  }
1987
  // Replace the 'temp' path in the database with the real path.
1988
- $ewwwdb->update( $ewwwdb->ewwwio_images,
 
1989
  array(
1990
  'path' => ewww_image_optimizer_relative_path_remove( $retina_path ),
1991
  'attachment_id' => $id,
@@ -2164,9 +2187,11 @@ function ewww_image_optimizer_imagick_support() {
2164
  if ( extension_loaded( 'imagick' ) ) {
2165
  $imagick = new Imagick();
2166
  $formats = $imagick->queryFormats();
 
2167
  if ( in_array( 'PNG', $formats ) && in_array( 'JPG', $formats ) ) {
2168
  return true;
2169
  }
 
2170
  }
2171
  return false;
2172
  }
@@ -2181,9 +2206,11 @@ function ewww_image_optimizer_gmagick_support() {
2181
  if ( extension_loaded( 'gmagick' ) ) {
2182
  $gmagick = new Gmagick();
2183
  $formats = $gmagick->queryFormats();
 
2184
  if ( in_array( 'PNG', $formats ) && in_array( 'JPG', $formats ) ) {
2185
  return true;
2186
  }
 
2187
  }
2188
  return false;
2189
  }
@@ -2252,10 +2279,15 @@ function ewww_image_optimizer_aux_paths_sanitize( $input ) {
2252
  continue;
2253
  }
2254
  if ( ! empty( $path ) ) {
2255
- add_settings_error( 'ewww_image_optimizer_aux_paths', "ewwwio-aux-paths-$i", sprintf(
2256
- /* translators: %s: A file system path */
2257
- esc_html__( 'Could not save Folder to Optimize: %s. Please ensure that it is a valid location on the server.', 'ewww-image-optimizer' ), esc_html( $path )
2258
- ) );
 
 
 
 
 
2259
  }
2260
  } // End foreach().
2261
  } // End if().
@@ -2311,10 +2343,15 @@ function ewww_image_optimizer_webp_paths_sanitize( $paths ) {
2311
  $path = esc_url( $path, null, 'db' );
2312
  if ( ! empty( $path ) ) {
2313
  if ( ! substr_count( $path, '.' ) ) {
2314
- add_settings_error( 'ewww_image_optimizer_webp_paths', "ewwwio-webp-paths-$i", sprintf(
2315
- /* translators: %s: A url or domain name */
2316
- esc_html__( 'Could not save WebP URL: %s.', 'ewww-image-optimizer' ), esc_html( $original_path )
2317
- ) . ' ' . esc_html__( 'Please enter a valid url including the domain name.', 'ewww-image-optimizer' ) );
 
 
 
 
 
2318
  continue;
2319
  }
2320
  $paths_saved[] = str_replace( 'http://', '', $path );
@@ -2476,9 +2513,7 @@ function ewww_image_optimizer_manual() {
2476
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
2477
  }
2478
  ewwwio_ob_clean();
2479
- wp_die( ewwwio_json_encode( array(
2480
- 'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
2481
- ) ) );
2482
  }
2483
  // Make sure we didn't accidentally get to this page without an attachment to work on.
2484
  if ( false === isset( $_REQUEST['ewww_attachment_ID'] ) ) {
@@ -2487,9 +2522,7 @@ function ewww_image_optimizer_manual() {
2487
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
2488
  }
2489
  ewwwio_ob_clean();
2490
- wp_die( ewwwio_json_encode( array(
2491
- 'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ),
2492
- ) ) );
2493
  }
2494
  session_write_close();
2495
  // Store the attachment ID value.
@@ -2499,9 +2532,7 @@ function ewww_image_optimizer_manual() {
2499
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
2500
  }
2501
  ewwwio_ob_clean();
2502
- wp_die( ewwwio_json_encode( array(
2503
- 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
2504
- ) ) );
2505
  }
2506
  // Retrieve the existing attachment metadata.
2507
  $original_meta = wp_get_attachment_metadata( $attachment_id );
@@ -2519,9 +2550,7 @@ function ewww_image_optimizer_manual() {
2519
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
2520
  }
2521
  ewwwio_ob_clean();
2522
- wp_die( ewwwio_json_encode( array(
2523
- 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
2524
- ) ) );
2525
  }
2526
  $basename = '';
2527
  if ( is_array( $new_meta ) && ! empty( $new_meta['file'] ) ) {
@@ -2530,16 +2559,14 @@ function ewww_image_optimizer_manual() {
2530
  // Update the attachment metadata in the database.
2531
  $meta_saved = wp_update_attachment_metadata( $attachment_id, $new_meta );
2532
  if ( ! $meta_saved ) {
2533
- ewwwio_debug_message( 'failed to save meta' );
2534
  }
2535
  if ( get_transient( 'ewww_image_optimizer_cloud_status' ) == 'exceeded' || ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_exceeded' ) > time() ) {
2536
  if ( ! wp_doing_ajax() ) {
2537
  wp_die( esc_html__( 'License exceeded', 'ewww-image-optimizer' ) );
2538
  }
2539
  ewwwio_ob_clean();
2540
- wp_die( ewwwio_json_encode( array(
2541
- 'error' => esc_html__( 'License exceeded', 'ewww-image-optimizer' ),
2542
- ) ) );
2543
  }
2544
  $success = ewww_image_optimizer_custom_column( 'ewww-image-optimizer', $attachment_id, $new_meta, true );
2545
  ewww_image_optimizer_debug_log();
@@ -2555,10 +2582,14 @@ function ewww_image_optimizer_manual() {
2555
  }
2556
  ewwwio_memory( __FUNCTION__ );
2557
  ewwwio_ob_clean();
2558
- wp_die( ewwwio_json_encode( array(
2559
- 'success' => $success,
2560
- 'basename' => $basename,
2561
- ) ) );
 
 
 
 
2562
  }
2563
 
2564
  /**
@@ -2631,36 +2662,26 @@ function ewww_image_optimizer_cloud_restore_single_image_handler() {
2631
  if ( false === current_user_can( $permissions ) ) {
2632
  // Display error message if insufficient permissions.
2633
  ewwwio_ob_clean();
2634
- wp_die( ewwwio_json_encode( array(
2635
- 'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
2636
- ) ) );
2637
  }
2638
  // Make sure we didn't accidentally get to this page without an attachment to work on.
2639
  if ( empty( $_REQUEST['ewww_image_id'] ) ) {
2640
  // Display an error message since we don't have anything to work on.
2641
  ewwwio_ob_clean();
2642
- wp_die( ewwwio_json_encode( array(
2643
- 'error' => esc_html__( 'No image ID was provided.', 'ewww-image-optimizer' ),
2644
- ) ) );
2645
  }
2646
  if ( empty( $_REQUEST['ewww_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) ) {
2647
  ewwwio_ob_clean();
2648
- wp_die( ewwwio_json_encode( array(
2649
- 'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ),
2650
- ) ) );
2651
  }
2652
  session_write_close();
2653
  $image = (int) $_REQUEST['ewww_image_id'];
2654
  if ( ewww_image_optimizer_cloud_restore_single_image( $image ) ) {
2655
  ewwwio_ob_clean();
2656
- wp_die( ewwwio_json_encode( array(
2657
- 'success' => 1,
2658
- ) ) );
2659
  }
2660
  ewwwio_ob_clean();
2661
- wp_die( ewwwio_json_encode( array(
2662
- 'error' => esc_html__( 'Unable to restore image.', 'ewww-image-optimizer' ),
2663
- ) ) );
2664
  }
2665
 
2666
  /**
@@ -2694,15 +2715,18 @@ function ewww_image_optimizer_cloud_restore_single_image( $image ) {
2694
  if ( $ssl ) {
2695
  $url = set_url_scheme( $url, 'https' );
2696
  }
2697
- $result = wp_remote_post( $url, array(
2698
- 'timeout' => 30,
2699
- 'sslverify' => false,
2700
- 'body' => array(
2701
- 'api_key' => $api_key,
2702
- 'domain' => $domain,
2703
- 'hash' => $image['backup'],
2704
- ),
2705
- ) );
 
 
 
2706
  if ( is_wp_error( $result ) ) {
2707
  $error_message = $result->get_error_message();
2708
  ewwwio_debug_message( "restore request failed: $error_message" );
@@ -2781,9 +2805,7 @@ function ewww_image_optimizer_delete( $id ) {
2781
  }
2782
  }
2783
  }
2784
- $ewwwdb->delete( $ewwwdb->ewwwio_images, array(
2785
- 'attachment_id' => $id,
2786
- ) );
2787
  }
2788
  // Retrieve the image metadata.
2789
  $meta = wp_get_attachment_metadata( $id );
@@ -2809,16 +2831,12 @@ function ewww_image_optimizer_delete( $id ) {
2809
  // If the original file still exists and no posts contain links to the image.
2810
  if ( is_file( $file_path ) && empty( $rows ) ) {
2811
  unlink( $file_path );
2812
- $ewwwdb->delete( $ewwwdb->ewwwio_images, array(
2813
- 'path' => ewww_image_optimizer_relative_path_remove( $file_path ),
2814
- ) );
2815
  }
2816
  }
2817
  // Remove the regular image from the ewwwio_images tables.
2818
  list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
2819
- $ewwwdb->delete( $ewwwdb->ewwwio_images, array(
2820
- 'path' => ewww_image_optimizer_relative_path_remove( $file_path ),
2821
- ) );
2822
  // Resized versions, so we can continue.
2823
  if ( isset( $meta['sizes'] ) && ewww_image_optimizer_iterable( $meta['sizes'] ) ) {
2824
  // One way or another, $file_path is now set, and we can get the base folder name.
@@ -2833,9 +2851,7 @@ function ewww_image_optimizer_delete( $id ) {
2833
  if ( is_file( $webpfileold ) ) {
2834
  unlink( $webpfileold );
2835
  }
2836
- $ewwwdb->delete( $ewwwdb->ewwwio_images, array(
2837
- 'path' => ewww_image_optimizer_relative_path_remove( $base_dir . $data['file'] ),
2838
- ) );
2839
  // If the original resize is set, and still exists.
2840
  if ( ! empty( $data['orig_file'] ) && is_file( $base_dir . $data['orig_file'] ) ) {
2841
  unset( $srows );
@@ -2847,9 +2863,7 @@ function ewww_image_optimizer_delete( $id ) {
2847
  // If there are no posts containing links to the original, delete it.
2848
  if ( empty( $srows ) ) {
2849
  unlink( $base_dir . $data['orig_file'] );
2850
- $ewwwdb->delete( $ewwwdb->ewwwio_images, array(
2851
- 'path' => ewww_image_optimizer_relative_path_remove( $base_dir . $data['orig_file'] ),
2852
- ) );
2853
  }
2854
  }
2855
  }
@@ -3038,13 +3052,16 @@ function ewww_image_optimizer_cloud_verify( $cache = true, $api_key = '' ) {
3038
  * @return array The results of the http POST request.
3039
  */
3040
  function ewww_image_optimizer_cloud_post_key( $url, $key ) {
3041
- $result = wp_remote_post( $url, array(
3042
- 'timeout' => 5,
3043
- 'sslverify' => false,
3044
- 'body' => array(
3045
- 'api_key' => $key,
3046
- ),
3047
- ) );
 
 
 
3048
  return $result;
3049
  }
3050
 
@@ -3063,13 +3080,16 @@ function ewww_image_optimizer_cloud_quota( $raw = false ) {
3063
  $url = set_url_scheme( $url, 'https' );
3064
  }
3065
  add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
3066
- $result = wp_remote_post( $url, array(
3067
- 'timeout' => 5,
3068
- 'sslverify' => false,
3069
- 'body' => array(
3070
- 'api_key' => $api_key,
3071
- ),
3072
- ) );
 
 
 
3073
  if ( is_wp_error( $result ) ) {
3074
  $error_message = $result->get_error_message();
3075
  ewwwio_debug_message( "quota request failed: $error_message" );
@@ -3087,28 +3107,43 @@ function ewww_image_optimizer_cloud_quota( $raw = false ) {
3087
  return $quota;
3088
  }
3089
  if ( 0 == $quota['licensed'] && $quota['consumed'] > 0 ) {
3090
- return esc_html( sprintf(
3091
- /* translators: 1: Number of images 2: Number of days until renewal */
3092
- _n( 'optimized %1$d images, renewal is in %2$d day.', 'optimized %1$d images, renewal is in %2$d days.', $quota['days'], 'ewww-image-optimizer' ), $quota['consumed'], $quota['days']
3093
- ) );
 
 
 
 
3094
  } elseif ( 0 == $quota['licensed'] && $quota['consumed'] < 0 ) {
3095
- return esc_html( sprintf(
3096
- /* translators: 1: Number of images */
3097
- _n( '%1$d image credit remaining.', '%1$d image credits remaining.', abs( $quota['consumed'] ), 'ewww-image-optimizer' ), abs( $quota['consumed'] )
3098
- ) );
 
 
 
3099
  } elseif ( $quota['licensed'] > 0 && $quota['consumed'] < 0 ) {
3100
  $real_quota = $quota['licensed'] - $quota['consumed'];
3101
- return esc_html( sprintf(
3102
- /* translators: 1: Number of images */
3103
- _n( '%1$d image credit remaining.', '%1$d image credits remaining.', $real_quota, 'ewww-image-optimizer' ), $real_quota
3104
- ) );
 
 
 
3105
  } elseif ( 0 == $quota['licensed'] && 0 == $quota['consumed'] && 0 == $quota['days'] && 0 == $quota['metered'] ) {
3106
  return esc_html__( 'no credits remaining, please purchase more.', 'ewww-image-optimizer' );
3107
  } else {
3108
- return esc_html( sprintf(
3109
- /* translators: 1: Number of image credits used 2: Number of image credits available 3: days until subscription renewal */
3110
- _n( 'used %1$d of %2$d, usage will reset in %3$d day.', 'used %1$d of %2$d, usage will reset in %3$d days.', $quota['days'], 'ewww-image-optimizer' ), $quota['consumed'], $quota['licensed'], $quota['days']
3111
- ) );
 
 
 
 
 
3112
  }
3113
  }
3114
  }
@@ -3165,7 +3200,7 @@ function ewww_image_optimizer_cloud_optimizer( $file, $type, $convert = false, $
3165
  }
3166
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_skip_full' ) && $fullsize ) {
3167
  $metadata = 1;
3168
- } elseif ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) ) {
3169
  // Don't copy metadata.
3170
  $metadata = 0;
3171
  } else {
@@ -3300,12 +3335,15 @@ function ewww_image_optimizer_cloud_optimizer( $file, $type, $convert = false, $
3300
  $payload .= '--' . $boundary . '--';
3301
 
3302
  add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
3303
- $response = wp_remote_post( $url, array(
3304
- 'timeout' => 300,
3305
- 'headers' => $headers,
3306
- 'sslverify' => false,
3307
- 'body' => $payload,
3308
- ) );
 
 
 
3309
  if ( is_wp_error( $response ) ) {
3310
  $error_message = $response->get_error_message();
3311
  ewwwio_debug_message( "optimize failed: $error_message" );
@@ -3430,12 +3468,15 @@ function ewww_image_optimizer_cloud_autorotate( $file, $type ) {
3430
  $payload .= '--' . $boundary . '--';
3431
 
3432
  add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
3433
- $response = wp_remote_post( $url, array(
3434
- 'timeout' => 60,
3435
- 'headers' => $headers,
3436
- 'sslverify' => false,
3437
- 'body' => $payload,
3438
- ) );
 
 
 
3439
  if ( is_wp_error( $response ) ) {
3440
  $error_message = $response->get_error_message();
3441
  ewwwio_debug_message( "rotate failed: $error_message" );
@@ -3462,6 +3503,133 @@ function ewww_image_optimizer_cloud_autorotate( $file, $type ) {
3462
  }
3463
  }
3464
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3465
  /**
3466
  * Setup our own database connection with full utf8 capability.
3467
  *
@@ -3523,8 +3691,9 @@ function ewww_image_optimizer_db_init() {
3523
  if ( is_wp_error( $prefix ) ) {
3524
  wp_load_translations_early();
3525
  wp_die(
3526
- /* translators: 1: $table_prefix 2: wp-config.php */
3527
- sprintf( __( '<strong>ERROR</strong>: %1$s in %2$s can only contain numbers, letters, and underscores.' ),
 
3528
  '<code>$table_prefix</code>',
3529
  '<code>wp-config.php</code>'
3530
  )
@@ -3594,7 +3763,8 @@ function ewww_image_optimizer_check_table( $file, $orig_size ) {
3594
  // Make sure the image isn't pending.
3595
  if ( $image['pending'] ) {
3596
  global $wpdb;
3597
- $wpdb->update( $wpdb->ewwwio_images,
 
3598
  array(
3599
  'pending' => 0,
3600
  ),
@@ -3717,7 +3887,8 @@ function ewww_image_optimizer_update_table( $attachment, $opt_size, $orig_size,
3717
  ewwwio_debug_message( print_r( $updates, true ) );
3718
  }
3719
  // Update information for the image.
3720
- $record_updated = $ewwwdb->update( $ewwwdb->ewwwio_images,
 
3721
  $updates,
3722
  array(
3723
  'id' => $already_optimized['id'],
@@ -3876,10 +4047,13 @@ function ewww_image_optimizer_aux_images_loop( $attachment = null, $auto = false
3876
  // Calculate how much time has elapsed since we started.
3877
  $elapsed = microtime( true ) - $started;
3878
  // Output how much time has elapsed since we started.
3879
- $output['results'] .= sprintf( esc_html(
3880
- /* translators: %s: number of seconds */
3881
- _n( 'Elapsed: %s second', 'Elapsed: %s seconds', $elapsed, 'ewww-image-optimizer' )
3882
- ) . '</p>', number_format_i18n( $elapsed ) );
 
 
 
3883
  if ( get_site_option( 'ewww_image_optimizer_debug' ) ) {
3884
  global $ewww_debug;
3885
  $output['results'] .= '<div style="background-color:#ffff99;">' . $ewww_debug . '</div>';
@@ -4161,7 +4335,8 @@ function ewww_image_optimizer_update_table_as3cf( $local_path, $s3_path ) {
4161
  // If we found records for both local and s3 paths, we delete the s3 record, but store the original size in the local record.
4162
  if ( ! empty( $found_local_image ) && is_array( $found_local_image ) ) {
4163
  ewwwio_debug_message( "found $local_path in db" );
4164
- $ewwwdb->delete( $ewwwdb->ewwwio_images,
 
4165
  array(
4166
  'id' => $s3_image['id'],
4167
  ),
@@ -4170,7 +4345,8 @@ function ewww_image_optimizer_update_table_as3cf( $local_path, $s3_path ) {
4170
  )
4171
  );
4172
  if ( $s3_image['orig_size'] > $found_local_image['orig_size'] ) {
4173
- $ewwwdb->update( $ewwwdb->ewwwio_images,
 
4174
  array(
4175
  'orig_size' => $s3_image['orig_size'],
4176
  'results' => $s3_image['results'],
@@ -4183,7 +4359,8 @@ function ewww_image_optimizer_update_table_as3cf( $local_path, $s3_path ) {
4183
  } else {
4184
  // If we just found an s3 path and no local match, then we just update the path in the table to the local path.
4185
  ewwwio_debug_message( 'just updating s3 to local' );
4186
- $ewwwdb->update( $ewwwdb->ewwwio_images,
 
4187
  array(
4188
  'path' => ewww_image_optimizer_relative_path_remove( $local_path ),
4189
  ),
@@ -4210,6 +4387,76 @@ function ewww_image_optimizer_raise_memory_limit( $memory_limit ) {
4210
  }
4211
  }
4212
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4213
  /**
4214
  * If a JPG image is using the EXIF orientiation, correct the rotation, and reset the Orientation.
4215
  *
@@ -4232,7 +4479,7 @@ function ewww_image_optimizer_autorotate( $file ) {
4232
  if ( ! $orientation || 1 == $orientation ) {
4233
  return;
4234
  }
4235
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) < 20 ) {
4236
  // Read the exif, if it fails, we won't autorotate.
4237
  try {
4238
  $jpeg = new PelJpeg( $file );
@@ -4411,7 +4658,9 @@ function ewww_image_optimizer_resize_upload( $file ) {
4411
  }
4412
 
4413
  // From here...
4414
- remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
 
 
4415
  $editor = wp_get_image_editor( $file );
4416
  if ( is_wp_error( $editor ) ) {
4417
  ewwwio_debug_message( 'could not get image editor' );
@@ -4442,7 +4691,8 @@ function ewww_image_optimizer_resize_upload( $file ) {
4442
  }
4443
  $resized_image = $editor->resize( $newwidth, $newheight, $crop );
4444
  if ( is_wp_error( $resized_image ) ) {
4445
- ewwwio_debug_message( 'error during resizing' );
 
4446
  return false;
4447
  }
4448
  $new_file = $editor->generate_filename( 'tmp' );
@@ -4450,10 +4700,12 @@ function ewww_image_optimizer_resize_upload( $file ) {
4450
  ewwwio_debug_message( "before resizing: $orig_size" );
4451
  $saved = $editor->save( $new_file );
4452
  if ( is_wp_error( $saved ) ) {
4453
- ewwwio_debug_message( 'error saving resized image' );
 
4454
  }
4455
  if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_noauto' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_editor' ) ) {
4456
- add_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
 
4457
  }
4458
  // to here is replaced by cloud/API function.
4459
  $new_size = ewww_image_optimizer_filesize( $new_file );
@@ -4463,7 +4715,7 @@ function ewww_image_optimizer_resize_upload( $file ) {
4463
  ewwwio_debug_message( "after resizing: $new_size" );
4464
  // TODO: see if there is a way to just check that meta exists on the new image.
4465
  // Use PEL to get the exif (if Remove Meta is unchecked) and GD is in use, so we can save it to the new image.
4466
- if ( 'image/jpeg' === $type && ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_skip_full' ) || ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) ) && ! ewww_image_optimizer_imagick_support() ) {
4467
  ewwwio_debug_message( 'manually copying metadata for GD' );
4468
  try {
4469
  $old_jpeg = new PelJpeg( $file );
@@ -4504,7 +4756,8 @@ function ewww_image_optimizer_resize_upload( $file ) {
4504
  $already_optimized = ewww_image_optimizer_find_already_optimized( $file );
4505
  // If the original file has never been optimized, then just update the record that was created with the proper filename (because the resized file has usually been optimized).
4506
  if ( empty( $already_optimized ) ) {
4507
- $tmp_exists = $ewwwdb->update( $ewwwdb->ewwwio_images,
 
4508
  array(
4509
  'path' => ewww_image_optimizer_relative_path_remove( $file ),
4510
  'orig_size' => $orig_size,
@@ -4515,16 +4768,20 @@ function ewww_image_optimizer_resize_upload( $file ) {
4515
  );
4516
  // If the tmp file didn't get optimized (and it shouldn't), then just insert a dummy record to be updated shortly.
4517
  if ( ! $tmp_exists ) {
4518
- $ewwwdb->insert( $ewwwdb->ewwwio_images, array(
4519
- 'path' => ewww_image_optimizer_relative_path_remove( $file ),
4520
- 'orig_size' => $orig_size,
4521
- ) );
 
 
 
4522
  }
4523
  } else {
4524
  // Otherwise, we delete the record created from optimizing the resized file.
4525
  $temp_optimized = ewww_image_optimizer_find_already_optimized( $new_file );
4526
  if ( is_array( $temp_optimized ) && ! empty( $temp_optimized['id'] ) ) {
4527
- $ewwwdb->delete( $ewwwdb->ewwwio_images,
 
4528
  array(
4529
  'id' => $temp_optimized['id'],
4530
  ),
@@ -4552,7 +4809,7 @@ function ewww_image_optimizer_resize_upload( $file ) {
4552
  */
4553
  function ewww_image_optimizer_get_orientation( $file, $type ) {
4554
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
4555
- if ( function_exists( 'exif_read_data' ) && 'image/jpeg' === $type ) {
4556
  $exif = @exif_read_data( $file );
4557
  if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
4558
  ewwwio_debug_message( print_r( $exif, true ) );
@@ -4781,7 +5038,9 @@ function ewww_image_optimizer_test_parallel_opt( $type = '', $id = 0 ) {
4781
  function ewww_image_optimizer_rebuild_meta( $attachment_id ) {
4782
  $file = get_attached_file( $attachment_id );
4783
  if ( is_file( $file ) ) {
4784
- remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
 
 
4785
  remove_all_filters( 'wp_generate_attachment_metadata' );
4786
  ewwwio_debug_message( "generating new meta for $attachment_id" );
4787
  $meta = wp_generate_attachment_metadata( $attachment_id, $file );
@@ -4917,7 +5176,8 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
4917
  if ( is_array( $already_optimized ) ) {
4918
  ewwwio_debug_message( "updating existing record, path: $file_path, size: " . $image_size );
4919
  // Store info on the current image for future reference.
4920
- $ewwwdb->update( $ewwwdb->ewwwio_images,
 
4921
  array(
4922
  'path' => ewww_image_optimizer_relative_path_remove( $file_path ),
4923
  'attachment_id' => $id,
@@ -4952,11 +5212,13 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
4952
  $ewwwio_media_background = new EWWWIO_Media_Background_Process();
4953
  }
4954
  ewwwio_debug_message( "backgrounding optimization for $id" );
4955
- $ewwwio_media_background->push_to_queue( array(
4956
- 'id' => $id,
4957
- 'new' => $new_image,
4958
- 'type' => $type,
4959
- ) );
 
 
4960
  $ewwwio_media_background->save()->dispatch();
4961
  set_transient( 'ewwwio-background-in-progress-' . $id, true, 24 * HOUR_IN_SECONDS );
4962
  if ( $log ) {
@@ -5067,7 +5329,8 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5067
  if ( is_array( $already_optimized ) ) {
5068
  ewwwio_debug_message( "updating existing record, path: $ims_path, size: " . $image_size );
5069
  // Store info on the current image for future reference.
5070
- $ewwwdb->update( $ewwwdb->ewwwio_images,
 
5071
  array(
5072
  'path' => ewww_image_optimizer_relative_path_remove( $ims_path ),
5073
  ),
@@ -5295,9 +5558,10 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5295
  }
5296
  if ( class_exists( 'Cloudinary' ) && Cloudinary::config_get( 'api_secret' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_cloudinary' ) && ! empty( $new_image ) ) {
5297
  try {
5298
- $result = CloudinaryUploader::upload( $file, array(
5299
- 'use_filename' => true,
5300
- ) );
 
5301
  } catch ( Exception $e ) {
5302
  $error = $e->getMessage();
5303
  }
@@ -5307,10 +5571,12 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5307
  ewwwio_debug_message( 'successfully uploaded to Cloudinary' );
5308
  // Register the attachment in the database as a cloudinary attachment.
5309
  $old_url = wp_get_attachment_url( $id );
5310
- wp_update_post( array(
5311
- 'ID' => $id,
5312
- 'guid' => $result['url'],
5313
- ) );
 
 
5314
  update_attached_file( $id, $result['url'] );
5315
  $meta['cloudinary'] = true;
5316
  $errors = array();
@@ -5350,6 +5616,38 @@ function ewww_image_optimizer_detect_wpsf_location_lock() {
5350
  return false;
5351
  }
5352
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5353
  /**
5354
  * Update the attachment's meta data after being converted.
5355
  *
@@ -5453,10 +5751,12 @@ function ewww_image_optimizer_update_attachment( $meta, $id ) {
5453
  $mime = 'image/gif';
5454
  }
5455
  // Update the attachment post with the new mimetype and id.
5456
- wp_update_post( array(
5457
- 'ID' => $id,
5458
- 'post_mime_type' => $mime,
5459
- ) );
 
 
5460
  ewww_image_optimizer_debug_log();
5461
  ewwwio_memory( __FUNCTION__ );
5462
  return $meta;
@@ -6003,13 +6303,15 @@ function ewww_image_optimizer_custom_column( $column_name, $id, $meta = null, $r
6003
  // Output the optimizer actions.
6004
  if ( current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
6005
  // Display a link to re-optimize manually.
6006
- $output .= '<div>' . sprintf( "<a class='ewww-manual-optimize' data-id='$id' data-nonce='$ewww_manual_nonce' href=\"admin.php?action=ewww_image_optimizer_manual_optimize&amp;ewww_manual_nonce=$ewww_manual_nonce&amp;ewww_force=1&amp;ewww_attachment_ID=%d\">%s</a>",
 
6007
  $id,
6008
  esc_html__( 'Re-optimize', 'ewww-image-optimizer' )
6009
  ) . '</div>';
6010
  }
6011
  if ( $backup_available && current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
6012
- $output .= '<div>' . sprintf( "<a class='ewww-manual-cloud-restore' data-id='$id' data-nonce='$ewww_manual_nonce' href=\"admin.php?action=ewww_image_optimizer_manual_cloud_restore&amp;ewww_manual_nonce=$ewww_manual_nonce&amp;ewww_attachment_ID=%d\">%s</a>",
 
6013
  $id,
6014
  esc_html__( 'Restore original', 'ewww-image-optimizer' )
6015
  ) . '</div>';
@@ -6019,10 +6321,13 @@ function ewww_image_optimizer_custom_column( $column_name, $id, $meta = null, $r
6019
  // Give the user the option to optimize the image right now.
6020
  if ( isset( $meta['sizes'] ) && ewww_image_optimizer_iterable( $meta['sizes'] ) ) {
6021
  $sizes_to_opt = ewww_image_optimizer_count_unoptimized_sizes( $meta['sizes'] ) + 1;
6022
- $output .= '<div>' . sprintf( esc_html(
6023
- /* translators: %d: The number of resize/thumbnail images */
6024
- _n( '%d size to compress', '%d sizes to compress', $sizes_to_opt, 'ewww-image-optimizer' )
6025
- ), $sizes_to_opt ) . '</div>';
 
 
 
6026
  }
6027
  $output .= '<div>' . sprintf( "<a class='ewww-manual-optimize' data-id='$id' data-nonce='$ewww_manual_nonce' href=\"admin.php?action=ewww_image_optimizer_manual_optimize&amp;ewww_manual_nonce=$ewww_manual_nonce&amp;ewww_attachment_ID=%d\">%s</a>", $id, esc_html__( 'Optimize now!', 'ewww-image-optimizer' ) ) . '</div>';
6028
  }
@@ -6071,7 +6376,8 @@ function ewww_image_optimizer_custom_column( $column_name, $id, $meta = null, $r
6071
 
6072
  if ( empty( $msg ) && current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
6073
  // Output a link to re-optimize manually.
6074
- $output .= '<div>' . sprintf("<a class='ewww-manual-optimize' data-id='$id' data-nonce='$ewww_manual_nonce' href=\"admin.php?action=ewww_image_optimizer_manual_optimize&amp;ewww_manual_nonce=$ewww_manual_nonce&amp;ewww_force=1&amp;ewww_attachment_ID=%d\">%s</a>",
 
6075
  $id,
6076
  esc_html__( 'Re-optimize', 'ewww-image-optimizer' )
6077
  );
@@ -6087,12 +6393,14 @@ function ewww_image_optimizer_custom_column( $column_name, $id, $meta = null, $r
6087
  $restorable = true;
6088
  }
6089
  if ( $restorable && current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
6090
- $output .= '<div>' . sprintf( "<a class='ewww-manual-restore' data-id='$id' data-nonce='$ewww_manual_nonce' href=\"admin.php?action=ewww_image_optimizer_manual_restore&amp;ewww_manual_nonce=$ewww_manual_nonce&amp;ewww_attachment_ID=%d\">%s</a>",
 
6091
  $id,
6092
  esc_html__( 'Restore original', 'ewww-image-optimizer' )
6093
  ) . '</div>';
6094
  } elseif ( $backup_available && current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
6095
- $output .= '<div>' . sprintf( "<a class='ewww-manual-cloud-restore' data-id='$id' data-nonce='$ewww_manual_nonce' href=\"admin.php?action=ewww_image_optimizer_manual_cloud_restore&amp;ewww_manual_nonce=$ewww_manual_nonce&amp;ewww_attachment_ID=%d\">%s</a>",
 
6096
  $id,
6097
  esc_html__( 'Restore original', 'ewww-image-optimizer' )
6098
  ) . '</div>';
@@ -6101,10 +6409,13 @@ function ewww_image_optimizer_custom_column( $column_name, $id, $meta = null, $r
6101
  // Otherwise, this must be an image we haven't processed.
6102
  if ( isset( $meta['sizes'] ) && ewww_image_optimizer_iterable( $meta['sizes'] ) ) {
6103
  $sizes_to_opt = ewww_image_optimizer_count_unoptimized_sizes( $meta['sizes'] ) + 1;
6104
- $output .= '<div>' . sprintf( esc_html(
6105
- /* translators: %d: The number of resize/thumbnail images */
6106
- _n( '%d size to compress', '%d sizes to compress', $sizes_to_opt, 'ewww-image-optimizer' )
6107
- ), $sizes_to_opt ) . '</div>';
 
 
 
6108
  } else {
6109
  $output .= '<div>' . esc_html__( 'Not processed', 'ewww-image-optimizer' ) . '</div>';
6110
  }
@@ -6235,10 +6546,13 @@ function ewww_image_optimizer_custom_column_results( $id, $optimized_images ) {
6235
  }
6236
  $detail_output .= '</table>';
6237
 
6238
- $output .= '<div>' . sprintf( esc_html(
6239
- /* translators: %d: number of resizes/thumbnails compressed */
6240
- _n( '%d size compressed', '%d sizes compressed', $sizes_to_opt, 'ewww-image-optimizer' )
6241
- ), $sizes_to_opt );
 
 
 
6242
  $output .= " <a href='#TB_inline?width=550&height=450&inlineId=ewww-attachment-detail-$id' class='thickbox'>(+)</a></div>";
6243
  $results_msg = ewww_image_optimizer_image_results( $orig_size, $opt_size );
6244
  // Output the optimizer results.
@@ -6503,13 +6817,15 @@ function ewww_image_optimizer_bulk_action_handler() {
6503
  check_admin_referer( 'bulk-media' );
6504
  // Prep the attachment IDs for optimization.
6505
  $ids = implode( ',', array_map( 'intval', $_REQUEST['media'] ) );
6506
- wp_redirect( add_query_arg(
6507
- array(
6508
- 'page' => 'ewww-image-optimizer-bulk',
6509
- 'ids' => $ids,
6510
- ),
6511
- admin_url( 'upload.php' )
6512
- ) );
 
 
6513
  ewwwio_memory( __FUNCTION__ );
6514
  exit();
6515
  }
@@ -6599,9 +6915,7 @@ function ewww_image_optimizer_settings_script( $hook ) {
6599
  wp_enqueue_style( 'jquery-ui-tooltip-custom', plugins_url( '/includes/jquery-ui-1.10.1.custom.css', __FILE__ ), array(), EWWW_IMAGE_OPTIMIZER_VERSION );
6600
  wp_enqueue_script( 'postbox' );
6601
  wp_enqueue_script( 'dashboard' );
6602
- wp_localize_script( 'ewwwbulkscript', 'ewww_vars', array(
6603
- '_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-settings' ),
6604
- ) );
6605
  ewwwio_memory( __FUNCTION__ );
6606
  return;
6607
  }
@@ -6632,17 +6946,20 @@ function ewww_image_optimizer_savings() {
6632
  }
6633
  if ( function_exists( 'get_sites' ) ) {
6634
  ewwwio_debug_message( 'retrieving list of sites the easy way (4.6+)' );
6635
- $blogs = get_sites( array(
6636
- 'fields' => 'ids',
6637
- 'number' => 1000,
6638
- ) );
6639
-
 
6640
  } elseif ( function_exists( 'wp_get_sites' ) ) {
6641
  ewwwio_debug_message( 'retrieving list of sites the easy way (pre 4.6)' );
6642
- $blogs = wp_get_sites( array(
6643
- 'network_id' => $wpdb->siteid,
6644
- 'limit' => 1000,
6645
- ) );
 
 
6646
  }
6647
  if ( ewww_image_optimizer_iterable( $blogs ) ) {
6648
  foreach ( $blogs as $blog ) {
@@ -7038,12 +7355,12 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7038
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) > 20 ) {
7039
  $compress_score += 50;
7040
  } else {
7041
- $compress_recommendations[] = esc_html__( 'Enable premium lossy compression for JPG images.', 'ewww-image-optimizer' );
7042
  }
7043
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) > 20 ) {
7044
  $compress_score += 20;
7045
  } else {
7046
- $compress_recommendations[] = esc_html__( 'Enable premium lossy compression for PNG images.', 'ewww-image-optimizer' );
7047
  }
7048
  $status_notices .= '<span style="color: #3eadc9; font-weight: bolder">' . esc_html__( 'Verified,', 'ewww-image-optimizer' ) . ' </span>' . ewww_image_optimizer_cloud_quota();
7049
  } elseif ( false !== strpos( $verify_cloud, 'exceeded' ) ) {
@@ -7079,7 +7396,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7079
  if ( ewww_image_optimizer_get_option( 'exactdn_lossy' ) ) {
7080
  $compress_score = 100;
7081
  } elseif ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) < 30 ) {
7082
- $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' );
7083
  }
7084
  } elseif ( $exactdn->get_exactdn_domain() && $exactdn->get_exactdn_option( 'verified' ) ) {
7085
  $status_notices .= '<span style="color: orange; font-weight: bolder">' . esc_html__( 'Temporarily disabled.', 'ewww-image-optimizer' ) . ' </span>';
@@ -7238,7 +7555,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7238
  $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";
7239
  }
7240
 
7241
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) == true ) {
7242
  $compress_score += 5;
7243
  } else {
7244
  $compress_recommendations[] = esc_html__( 'Remove metadata from JPG images.', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/7-basic-configuration', '585373d5c697912ffd6c0bb2' );
@@ -7379,48 +7696,48 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7379
  }
7380
  $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>' .
7381
  "<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";
7382
- $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" .
7383
- "<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";
7384
- ewwwio_debug_message( 'remove metadata: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) == true ? 'on' : 'off' ) );
7385
  $output[] = "<tr class='$network_class'><th>&nbsp;</th><td>" .
7386
  "<p class='$network_class description'>" . esc_html__( 'All methods used by the EWWW Image Optimizer are intended to produce visually identical images.', 'ewww-image-optimizer' ) .
7387
- ' ' . esc_html__( 'Lossless compression is actually identical to the original, while lossy reduces the quality a small amount.', 'ewww-image-optimizer' ) . "</p>\n" .
7388
  ( ! 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" : '' );
7389
  $output[] = "</td></tr>\n";
7390
  $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" .
7391
  "<td><span><select id='ewww_image_optimizer_jpg_level' name='ewww_image_optimizer_jpg_level'>\n" .
7392
  "<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";
7393
  if ( defined( 'EWWW_IMAGE_OPTIMIZER_TOOL_PATH' ) ) {
7394
- $output[] = "<option class='$network_class' value='10'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ), 10, false ) . '>' . esc_html__( 'Lossless Compression', 'ewww-image-optimizer' ) . "</option>\n";
7395
  }
7396
- $output[] = "<option class='$network_class' $disable_level value='20'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ), 20, false ) . '>' . esc_html__( 'Maximum Lossless Compression', 'ewww-image-optimizer' ) . " *</option>\n" .
7397
- "<option $disable_level value='30'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ), 30, false ) . '>' . esc_html__( 'Lossy Compression', 'ewww-image-optimizer' ) . " *</option>\n" .
7398
- "<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" .
7399
  "</select></td></tr>\n";
7400
  ewwwio_debug_message( 'jpg level: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) );
7401
  $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" .
7402
  "<td><span><select id='ewww_image_optimizer_png_level' name='ewww_image_optimizer_png_level'>\n" .
7403
  "<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";
7404
  if ( defined( 'EWWW_IMAGE_OPTIMIZER_TOOL_PATH' ) ) {
7405
- $output[] = "<option class='$network_class' value='10'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ), 10, false ) . '>' . esc_html__( 'Lossless Compression', 'ewww-image-optimizer' ) . "</option>\n";
7406
  }
7407
  $output[] = "<option class='$network_class' $disable_level value='20' " . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ), 20, false ) .
7408
- selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ), 30, false ) . '>' . esc_html__( 'Maximum Lossless Compression', 'ewww-image-optimizer' ) . " *</option>\n" .
7409
- "<option value='40'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ), 40, false ) . '>' . esc_html__( 'Lossy Compression', 'ewww-image-optimizer' ) . "</option>\n" .
7410
- "<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" .
7411
  "</select></td></tr>\n";
7412
  ewwwio_debug_message( 'png level: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) );
7413
  $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" .
7414
  "<td><span><select id='ewww_image_optimizer_gif_level' name='ewww_image_optimizer_gif_level'>\n" .
7415
  "<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" .
7416
- "<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" .
7417
  "</select></td></tr>\n";
7418
  ewwwio_debug_message( 'gif level: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' ) );
7419
  $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" .
7420
  "<td><span><select id='ewww_image_optimizer_pdf_level' name='ewww_image_optimizer_pdf_level'>\n" .
7421
  "<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" .
7422
- "<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" .
7423
- "<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" .
7424
  "</select></td></tr>\n";
7425
  ewwwio_debug_message( 'pdf level: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ) );
7426
  ewwwio_debug_message( 'bulk delay: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_delay' ) );
@@ -7449,7 +7766,13 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7449
  '<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>' .
7450
  "</p></td></tr>\n";
7451
  ewwwio_debug_message( 'ExactDN enabled: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) == true ? 'on' : 'off' ) );
 
 
 
7452
  ewwwio_debug_message( 'ExactDN all the things: ' . ( ewww_image_optimizer_get_option( 'exactdn_all_the_things' ) == true ? 'on' : 'off' ) );
 
 
 
7453
  ewwwio_debug_message( 'ExactDN lossy: ' . intval( ewww_image_optimizer_get_option( 'exactdn_lossy' ) ) );
7454
  ewwwio_debug_message( 'ExactDN resize existing: ' . ( ewww_image_optimizer_get_option( 'exactdn_resize_existing' ) == true ? 'on' : 'off' ) );
7455
  ewwwio_debug_message( 'ExactDN attachment queries: ' . ( ewww_image_optimizer_get_option( 'exactdn_prevent_db_queries' ) == true ? 'off' : 'on' ) );
@@ -7662,6 +7985,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7662
  '</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' " .
7663
  ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) == true ? "checked='true'" : '' ) . ' /> ' .
7664
  esc_html__( 'Use this if the Apache rewrite rules do not work, or if your images are served from a CDN.', 'ewww-image-optimizer' ) . ' ' .
 
7665
  /* translators: %s: Cache Enabler (link) */
7666
  ( ! 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>';
7667
  }
@@ -7958,11 +8282,13 @@ function ewww_image_optimizer_admin_bar_init() {
7958
  */
7959
  function ewww_image_optimizer_admin_bar_menu() {
7960
  global $wp_admin_bar;
7961
- $wp_admin_bar->add_menu( array(
7962
- 'id' => 'resize-detection',
7963
- 'parent' => 'top-secondary',
7964
- 'title' => __( 'Detect Scaled Images', 'ewww-image-optimizer' ),
7965
- ) );
 
 
7966
  }
7967
 
7968
  /**
@@ -8196,12 +8522,13 @@ function ewww_image_optimizer_image_queue_debug() {
8196
 
8197
  $key = 'wp_ewwwio_media_optimize_batch_%';
8198
  $queues = $wpdb->get_results(
8199
- $wpdb->prepare( "
8200
- SELECT *
8201
  FROM $wpdb->options
8202
  WHERE option_name LIKE %s AND option_value != ''
8203
- ORDER BY option_id ASC
8204
- ", $key ),
 
8205
  ARRAY_A
8206
  );
8207
 
@@ -8346,4 +8673,14 @@ function ewwwio_dump_var( $var, $var2 = false, $var3 = false ) {
8346
  ewwwio_debug_message( print_r( $var3, true ) );
8347
  return $var;
8348
  }
 
 
 
 
 
 
 
 
 
 
8349
  ?>
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: might be able to use the Custom Bulk Actions in 4.7 to support the bulk optimize drop-down menu.
15
  // 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.
16
  // TODO: Add a custom async function for parallel mode to store image as pending and use the row ID instead of relative path.
17
  // TODO: write some tests for update_table and check_table, find_already_opt, and remove_dups.
18
  // TODO: write some conversion tests.
19
  // TODO: check this patch, to see if the use of 'full' causes any issues: https://core.trac.wordpress.org/ticket/37840 .
 
20
  // TODO: use this: https://codex.wordpress.org/AJAX_in_Plugins#The_post-load_JavaScript_Event .
 
 
21
  // TODO: handle relative urls with ExactDN.
22
  // TODO: see if we can parse all use tags and use the bypass mechanism to avoid ExactDN + SVG issues.
23
  // TODO: can some of the bulk "fallbacks" be implemented for async processing?
25
  exit;
26
  }
27
 
28
+ define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '440.0' );
29
 
30
  // Initialize a couple globals.
31
  $ewww_debug = '';
119
  add_filter( 'jpeg_quality', 'ewww_image_optimizer_set_jpg_quality' );
120
  // Makes sure the plugin bypasses any files affected by the Folders to Ignore setting.
121
  add_filter( 'ewww_image_optimizer_bypass', 'ewww_image_optimizer_ignore_file', 10, 2 );
122
+ // Ensure we populate the queue with webp images for WP Offload S3.
123
+ add_filter( 'as3cf_attachment_file_paths', 'ewww_image_optimizer_as3cf_attachment_file_paths', 10, 2 );
124
+ // Fix the ContentType for WP Offload S3 on WebP images.
125
+ add_filter( 'as3cf_object_meta', 'ewww_image_optimizer_as3cf_object_meta' );
126
  // Loads the plugin translations.
127
  add_action( 'plugins_loaded', 'ewww_image_optimizer_preinit' );
128
  // Checks for nextgen/nextcellent/flagallery existence, and loads the appropriate classes.
488
  ewww_image_optimizer_enable_background_optimization();
489
  ewww_image_optimizer_install_table();
490
  ewww_image_optimizer_set_defaults();
491
+ if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) || ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) < 30 ) {
492
+ add_site_option( 'exactdn_lossy', true );
493
+ update_option( 'exactdn_lossy', true );
494
+ }
495
  // This will get re-enabled if things are too slow.
496
  ewww_image_optimizer_set_option( 'exactdn_prevent_db_queries', false );
497
  delete_option( 'ewww_image_optimizer_exactdn_verify_method' );
514
  if ( get_option( 'ewww_image_optimizer_version' ) < 407 ) {
515
  add_site_option( 'exactdn_all_the_things', true );
516
  }
517
+ if ( get_option( 'ewww_image_optimizer_version' ) > 0 && get_option( 'ewww_image_optimizer_version' ) < 434 && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) ) {
518
+ ewww_image_optimizer_set_option( 'ewww_image_optimizer_metadata_remove', false );
519
+ }
520
  ewww_image_optimizer_remove_obsolete_settings();
521
  update_option( 'ewww_image_optimizer_version', EWWW_IMAGE_OPTIMIZER_VERSION );
522
  }
544
  }
545
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_background_optimization', false );
546
  ewwwio_debug_message( 'running test async handler' );
547
+ $ewwwio_test_async->data( array( 'ewwwio_test_verify' => '949c34123cf2a4e4ce2f985135830df4a1b2adc24905f53d2fd3f5df5b162932' ) )->dispatch();
 
 
548
  ewww_image_optimizer_debug_log();
549
  }
550
 
588
  update_site_option( 'ewww_image_optimizer_cloud_key', ewww_image_optimizer_cloud_key_sanitize( $_POST['ewww_image_optimizer_cloud_key'] ) );
589
  $_POST['ewww_image_optimizer_debug'] = ( empty( $_POST['ewww_image_optimizer_debug'] ) ? false : true );
590
  update_site_option( 'ewww_image_optimizer_debug', $_POST['ewww_image_optimizer_debug'] );
591
+ $_POST['ewww_image_optimizer_metadata_remove'] = ( empty( $_POST['ewww_image_optimizer_metadata_remove'] ) ? false : true );
592
+ update_site_option( 'ewww_image_optimizer_metadata_remove', $_POST['ewww_image_optimizer_metadata_remove'] );
593
  $_POST['ewww_image_optimizer_jpg_level'] = empty( $_POST['ewww_image_optimizer_jpg_level'] ) ? '' : $_POST['ewww_image_optimizer_jpg_level'];
594
  update_site_option( 'ewww_image_optimizer_jpg_level', (int) $_POST['ewww_image_optimizer_jpg_level'] );
595
  $_POST['ewww_image_optimizer_png_level'] = empty( $_POST['ewww_image_optimizer_png_level'] ) ? '' : $_POST['ewww_image_optimizer_png_level'];
626
  update_site_option( 'ewww_image_optimizer_enable_cloudinary', $_POST['ewww_image_optimizer_enable_cloudinary'] );
627
  $_POST['ewww_image_optimizer_exactdn'] = ( empty( $_POST['ewww_image_optimizer_exactdn'] ) ? false : true );
628
  update_site_option( 'ewww_image_optimizer_exactdn', $_POST['ewww_image_optimizer_exactdn'] );
629
+ $_POST['exactdn_all_the_things'] = ( empty( $_POST['exactdn_all_the_things'] ) ? false : true );
630
+ update_site_option( 'exactdn_all_the_things', $_POST['exactdn_all_the_things'] );
631
+ $_POST['exactdn_lossy'] = ( empty( $_POST['exactdn_lossy'] ) ? false : true );
632
+ update_site_option( 'exactdn_lossy', $_POST['exactdn_lossy'] );
633
  $_POST['ewww_image_optimizer_maxmediawidth'] = empty( $_POST['ewww_image_optimizer_maxmediawidth'] ) ? 0 : $_POST['ewww_image_optimizer_maxmediawidth'];
634
  update_site_option( 'ewww_image_optimizer_maxmediawidth', (int) $_POST['ewww_image_optimizer_maxmediawidth'] );
635
  $_POST['ewww_image_optimizer_maxmediaheight'] = empty( $_POST['ewww_image_optimizer_maxmediaheight'] ) ? 0 : $_POST['ewww_image_optimizer_maxmediaheight'];
676
  update_option( 'ewww_image_optimizer_disable_pngout', true );
677
  update_option( 'ewww_image_optimizer_optipng_level', 2 );
678
  update_option( 'ewww_image_optimizer_pngout_level', 2 );
679
+ update_option( 'ewww_image_optimizer_metadata_remove', true );
680
  update_option( 'ewww_image_optimizer_jpg_level', '10' );
681
  update_option( 'ewww_image_optimizer_png_level', '10' );
682
  update_option( 'ewww_image_optimizer_gif_level', '10' );
684
  // Register all the common EWWW IO settings.
685
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_cloud_key', 'ewww_image_optimizer_cloud_key_sanitize' );
686
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_debug', 'boolval' );
687
+ register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_metadata_remove', 'boolval' );
688
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_jpg_level', 'intval' );
689
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_png_level', 'intval' );
690
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_gif_level', 'intval' );
701
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_allow_tracking', array( $ewwwio_tracking, 'check_for_settings_optin' ) );
702
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_enable_help', 'boolval' );
703
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_exactdn', 'boolval' );
704
+ register_setting( 'ewww_image_optimizer_options', 'exactdn_all_the_things', 'boolval' );
705
+ register_setting( 'ewww_image_optimizer_options', 'exactdn_lossy', 'boolval' );
706
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_resize_detection', 'boolval' );
707
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxmediawidth', 'intval' );
708
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxmediaheight', 'intval' );
755
  }
756
  ewww_image_optimizer_privacy_policy_content();
757
  ewww_image_optimizer_ajax_compat_check();
758
+ // Increase the version when the next bump is coming.
759
+ if ( defined( 'PHP_VERSION_ID' ) && PHP_VERSION_ID < 50600 ) {
760
+ add_action( 'network_admin_notices', 'ewww_image_optimizer_php55_warning' );
761
+ add_action( 'admin_notices', 'ewww_image_optimizer_php55_warning' );
762
  }
763
  ewwwio_memory( __FUNCTION__ );
764
  }
824
  if ( ! empty( $_POST['iw-action'] ) ) {
825
  $action = $_POST['iw-action'];
826
  ewwwio_debug_message( "doing $action" );
827
+ global $ewww_preempt_editor;
828
+ $ewww_preempt_editor = true;
829
+ /* remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 ); */
830
  if ( 'applywatermark' === $action ) {
831
  remove_filter( 'wp_generate_attachment_metadata', 'ewww_image_optimizer_resize_from_meta_data', 15 );
832
  add_action( 'iw_after_apply_watermark', 'ewww_image_optimizer_single_size_optimize', 10, 2 );
860
  if ( ! defined( 'EWWW_IO_CLOUD_PLUGIN' ) || ! EWWW_IO_CLOUD_PLUGIN ) {
861
  $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>';
862
  }
863
+ $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 foreign 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>';
864
  $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>';
865
  $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>';
866
  wp_add_privacy_policy_content( 'EWWW Image Optimizer', $content );
1310
  '<p>' . sprintf(
1311
  /* translators: 1: An error message 2: The folder where pngout should be installed */
1312
  esc_html__( 'Pngout was not installed: %1$s. Make sure this folder is writable: %2$s', 'ewww-image-optimizer' ),
1313
+ sanitize_text_field( $_REQUEST['ewww_error'] ),
1314
+ EWWW_IMAGE_OPTIMIZER_TOOL_PATH
1315
  ) . "</p>\n" .
1316
  "</div>\n";
1317
  }
1318
  }
1319
  /**
1320
+ * Display a notice that PHP version 5.5 support is going away.
1321
  */
1322
+ function ewww_image_optimizer_php55_warning() {
1323
+ echo '<div id="ewww-image-optimizer-notice-php55" class="notice notice-info"><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.6 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>';
1324
  }
1325
 
1326
  /**
1441
  */
1442
  function ewww_image_optimizer_image_sizes( $sizes ) {
1443
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1444
+ /* remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 ); */
1445
+ global $ewww_preempt_editor;
1446
+ $ewww_preempt_editor = true;
1447
  // This happens right after thumbs and meta are generated.
1448
  add_filter( 'wp_generate_attachment_metadata', 'ewww_image_optimizer_restore_editor_hooks', 1 );
1449
  add_filter( 'mpp_generate_metadata', 'ewww_image_optimizer_restore_editor_hooks', 1 );
1461
  function ewww_image_optimizer_restore_editor_hooks( $metadata = false ) {
1462
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1463
  if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_noauto' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_editor' ) ) {
1464
+ global $ewww_preempt_editor;
1465
+ $ewww_preempt_editor = false;
1466
+ /* add_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 ); */
1467
  }
1468
  if ( function_exists( 'wr2x_wp_generate_attachment_metadata' ) ) {
1469
  remove_filter( 'wp_generate_attachment_metadata', 'wr2x_wp_generate_attachment_metadata' );
1491
  function ewww_image_optimizer_editor_save_pre( $image ) {
1492
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1493
  if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_noauto' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_editor' ) ) {
1494
+ global $ewww_preempt_editor;
1495
+ $ewww_preempt_editor = true;
1496
+ /* remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 ); */
1497
  add_filter( 'wp_update_attachment_metadata', 'ewww_image_optimizer_restore_editor_hooks', 1 );
1498
  add_filter( 'wp_update_attachment_metadata', 'ewww_image_optimizer_resize_from_meta_data', 15, 2 );
1499
  }
1539
  }
1540
  ewwwio_debug_message( "$old_filepath changed to $new_filepath" );
1541
  // Replace the 'temp' path in the database with the real path.
1542
+ $ewwwdb->update(
1543
+ $ewwwdb->ewwwio_images,
1544
  array(
1545
  'path' => ewww_image_optimizer_relative_path_remove( $new_filepath ),
1546
  ),
1570
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_noauto' ) || ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_editor' ) ) {
1571
  return $meta;
1572
  }
1573
+ global $ewww_preempt_editor;
1574
+ $ewww_preempt_editor = true;
1575
+ /* remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 ); */
1576
  if ( class_exists( 'Meow_WR2X_Core' ) ) {
1577
  global $wr2x_core;
1578
  if ( is_object( $wr2x_core ) ) {
1581
  } else {
1582
  $meta = wr2x_wp_generate_attachment_metadata( $meta );
1583
  }
1584
+ $ewww_preempt_editor = false;
1585
+ /* add_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 ); */
1586
  return $meta;
1587
  }
1588
 
1759
  * @return array|bool Information about the uploads dir, or false on failure.
1760
  */
1761
  function ewww_image_optimizer_upload_info() {
1762
+ $upload_info = wp_upload_dir( null, false );
1763
 
1764
  if ( empty( $upload_info['error'] ) ) {
1765
+ $parse_url = parse_url( $upload_info['baseurl'] );
 
 
1766
  if ( $parse_url ) {
1767
  $baseurlpath = ( ! empty( $parse_url['path'] ) ? trim( $parse_url['path'], '/' ) : '' );
1768
  } else {
2007
  $ewwwdb = $wpdb;
2008
  }
2009
  // Replace the 'temp' path in the database with the real path.
2010
+ $ewwwdb->update(
2011
+ $ewwwdb->ewwwio_images,
2012
  array(
2013
  'path' => ewww_image_optimizer_relative_path_remove( $retina_path ),
2014
  'attachment_id' => $id,
2187
  if ( extension_loaded( 'imagick' ) ) {
2188
  $imagick = new Imagick();
2189
  $formats = $imagick->queryFormats();
2190
+ ewwwio_debug_message( implode( ',', $formats ) );
2191
  if ( in_array( 'PNG', $formats ) && in_array( 'JPG', $formats ) ) {
2192
  return true;
2193
  }
2194
+ ewwwio_debug_message( 'imagick found, but PNG or JPG not supported' );
2195
  }
2196
  return false;
2197
  }
2206
  if ( extension_loaded( 'gmagick' ) ) {
2207
  $gmagick = new Gmagick();
2208
  $formats = $gmagick->queryFormats();
2209
+ ewwwio_debug_message( implode( ',', $formats ) );
2210
  if ( in_array( 'PNG', $formats ) && in_array( 'JPG', $formats ) ) {
2211
  return true;
2212
  }
2213
+ ewwwio_debug_message( 'gmagick found, but PNG or JPG not supported' );
2214
  }
2215
  return false;
2216
  }
2279
  continue;
2280
  }
2281
  if ( ! empty( $path ) ) {
2282
+ add_settings_error(
2283
+ 'ewww_image_optimizer_aux_paths',
2284
+ "ewwwio-aux-paths-$i",
2285
+ sprintf(
2286
+ /* translators: %s: A file system path */
2287
+ esc_html__( 'Could not save Folder to Optimize: %s. Please ensure that it is a valid location on the server.', 'ewww-image-optimizer' ),
2288
+ esc_html( $path )
2289
+ )
2290
+ );
2291
  }
2292
  } // End foreach().
2293
  } // End if().
2343
  $path = esc_url( $path, null, 'db' );
2344
  if ( ! empty( $path ) ) {
2345
  if ( ! substr_count( $path, '.' ) ) {
2346
+ add_settings_error(
2347
+ 'ewww_image_optimizer_webp_paths',
2348
+ "ewwwio-webp-paths-$i",
2349
+ sprintf(
2350
+ /* translators: %s: A url or domain name */
2351
+ esc_html__( 'Could not save WebP URL: %s.', 'ewww-image-optimizer' ),
2352
+ esc_html( $original_path )
2353
+ ) . ' ' . esc_html__( 'Please enter a valid url including the domain name.', 'ewww-image-optimizer' )
2354
+ );
2355
  continue;
2356
  }
2357
  $paths_saved[] = str_replace( 'http://', '', $path );
2513
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
2514
  }
2515
  ewwwio_ob_clean();
2516
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) ) ) );
 
 
2517
  }
2518
  // Make sure we didn't accidentally get to this page without an attachment to work on.
2519
  if ( false === isset( $_REQUEST['ewww_attachment_ID'] ) ) {
2522
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
2523
  }
2524
  ewwwio_ob_clean();
2525
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) ) ) );
 
 
2526
  }
2527
  session_write_close();
2528
  // Store the attachment ID value.
2532
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
2533
  }
2534
  ewwwio_ob_clean();
2535
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ) ) ) );
 
 
2536
  }
2537
  // Retrieve the existing attachment metadata.
2538
  $original_meta = wp_get_attachment_metadata( $attachment_id );
2550
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
2551
  }
2552
  ewwwio_ob_clean();
2553
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ) ) ) );
 
 
2554
  }
2555
  $basename = '';
2556
  if ( is_array( $new_meta ) && ! empty( $new_meta['file'] ) ) {
2559
  // Update the attachment metadata in the database.
2560
  $meta_saved = wp_update_attachment_metadata( $attachment_id, $new_meta );
2561
  if ( ! $meta_saved ) {
2562
+ ewwwio_debug_message( 'failed to save meta, or no changes' );
2563
  }
2564
  if ( get_transient( 'ewww_image_optimizer_cloud_status' ) == 'exceeded' || ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_exceeded' ) > time() ) {
2565
  if ( ! wp_doing_ajax() ) {
2566
  wp_die( esc_html__( 'License exceeded', 'ewww-image-optimizer' ) );
2567
  }
2568
  ewwwio_ob_clean();
2569
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'License exceeded', 'ewww-image-optimizer' ) ) ) );
 
 
2570
  }
2571
  $success = ewww_image_optimizer_custom_column( 'ewww-image-optimizer', $attachment_id, $new_meta, true );
2572
  ewww_image_optimizer_debug_log();
2582
  }
2583
  ewwwio_memory( __FUNCTION__ );
2584
  ewwwio_ob_clean();
2585
+ wp_die(
2586
+ ewwwio_json_encode(
2587
+ array(
2588
+ 'success' => $success,
2589
+ 'basename' => $basename,
2590
+ )
2591
+ )
2592
+ );
2593
  }
2594
 
2595
  /**
2662
  if ( false === current_user_can( $permissions ) ) {
2663
  // Display error message if insufficient permissions.
2664
  ewwwio_ob_clean();
2665
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) ) ) );
 
 
2666
  }
2667
  // Make sure we didn't accidentally get to this page without an attachment to work on.
2668
  if ( empty( $_REQUEST['ewww_image_id'] ) ) {
2669
  // Display an error message since we don't have anything to work on.
2670
  ewwwio_ob_clean();
2671
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'No image ID was provided.', 'ewww-image-optimizer' ) ) ) );
 
 
2672
  }
2673
  if ( empty( $_REQUEST['ewww_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) ) {
2674
  ewwwio_ob_clean();
2675
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) ) ) );
 
 
2676
  }
2677
  session_write_close();
2678
  $image = (int) $_REQUEST['ewww_image_id'];
2679
  if ( ewww_image_optimizer_cloud_restore_single_image( $image ) ) {
2680
  ewwwio_ob_clean();
2681
+ wp_die( ewwwio_json_encode( array( 'success' => 1 ) ) );
 
 
2682
  }
2683
  ewwwio_ob_clean();
2684
+ wp_die( ewwwio_json_encode( array( 'error' => esc_html__( 'Unable to restore image.', 'ewww-image-optimizer' ) ) ) );
 
 
2685
  }
2686
 
2687
  /**
2715
  if ( $ssl ) {
2716
  $url = set_url_scheme( $url, 'https' );
2717
  }
2718
+ $result = wp_remote_post(
2719
+ $url,
2720
+ array(
2721
+ 'timeout' => 30,
2722
+ 'sslverify' => false,
2723
+ 'body' => array(
2724
+ 'api_key' => $api_key,
2725
+ 'domain' => $domain,
2726
+ 'hash' => $image['backup'],
2727
+ ),
2728
+ )
2729
+ );
2730
  if ( is_wp_error( $result ) ) {
2731
  $error_message = $result->get_error_message();
2732
  ewwwio_debug_message( "restore request failed: $error_message" );
2805
  }
2806
  }
2807
  }
2808
+ $ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'attachment_id' => $id ) );
 
 
2809
  }
2810
  // Retrieve the image metadata.
2811
  $meta = wp_get_attachment_metadata( $id );
2831
  // If the original file still exists and no posts contain links to the image.
2832
  if ( is_file( $file_path ) && empty( $rows ) ) {
2833
  unlink( $file_path );
2834
+ $ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relative_path_remove( $file_path ) ) );
 
 
2835
  }
2836
  }
2837
  // Remove the regular image from the ewwwio_images tables.
2838
  list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
2839
+ $ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relative_path_remove( $file_path ) ) );
 
 
2840
  // Resized versions, so we can continue.
2841
  if ( isset( $meta['sizes'] ) && ewww_image_optimizer_iterable( $meta['sizes'] ) ) {
2842
  // One way or another, $file_path is now set, and we can get the base folder name.
2851
  if ( is_file( $webpfileold ) ) {
2852
  unlink( $webpfileold );
2853
  }
2854
+ $ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relative_path_remove( $base_dir . $data['file'] ) ) );
 
 
2855
  // If the original resize is set, and still exists.
2856
  if ( ! empty( $data['orig_file'] ) && is_file( $base_dir . $data['orig_file'] ) ) {
2857
  unset( $srows );
2863
  // If there are no posts containing links to the original, delete it.
2864
  if ( empty( $srows ) ) {
2865
  unlink( $base_dir . $data['orig_file'] );
2866
+ $ewwwdb->delete( $ewwwdb->ewwwio_images, array( 'path' => ewww_image_optimizer_relative_path_remove( $base_dir . $data['orig_file'] ) ) );
 
 
2867
  }
2868
  }
2869
  }
3052
  * @return array The results of the http POST request.
3053
  */
3054
  function ewww_image_optimizer_cloud_post_key( $url, $key ) {
3055
+ $result = wp_remote_post(
3056
+ $url,
3057
+ array(
3058
+ 'timeout' => 5,
3059
+ 'sslverify' => false,
3060
+ 'body' => array(
3061
+ 'api_key' => $key,
3062
+ ),
3063
+ )
3064
+ );
3065
  return $result;
3066
  }
3067
 
3080
  $url = set_url_scheme( $url, 'https' );
3081
  }
3082
  add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
3083
+ $result = wp_remote_post(
3084
+ $url,
3085
+ array(
3086
+ 'timeout' => 5,
3087
+ 'sslverify' => false,
3088
+ 'body' => array(
3089
+ 'api_key' => $api_key,
3090
+ ),
3091
+ )
3092
+ );
3093
  if ( is_wp_error( $result ) ) {
3094
  $error_message = $result->get_error_message();
3095
  ewwwio_debug_message( "quota request failed: $error_message" );
3107
  return $quota;
3108
  }
3109
  if ( 0 == $quota['licensed'] && $quota['consumed'] > 0 ) {
3110
+ return esc_html(
3111
+ sprintf(
3112
+ /* translators: 1: Number of images 2: Number of days until renewal */
3113
+ _n( 'optimized %1$d images, renewal is in %2$d day.', 'optimized %1$d images, renewal is in %2$d days.', $quota['days'], 'ewww-image-optimizer' ),
3114
+ $quota['consumed'],
3115
+ $quota['days']
3116
+ )
3117
+ );
3118
  } elseif ( 0 == $quota['licensed'] && $quota['consumed'] < 0 ) {
3119
+ return esc_html(
3120
+ sprintf(
3121
+ /* translators: 1: Number of images */
3122
+ _n( '%1$d image credit remaining.', '%1$d image credits remaining.', abs( $quota['consumed'] ), 'ewww-image-optimizer' ),
3123
+ abs( $quota['consumed'] )
3124
+ )
3125
+ );
3126
  } elseif ( $quota['licensed'] > 0 && $quota['consumed'] < 0 ) {
3127
  $real_quota = $quota['licensed'] - $quota['consumed'];
3128
+ return esc_html(
3129
+ sprintf(
3130
+ /* translators: 1: Number of images */
3131
+ _n( '%1$d image credit remaining.', '%1$d image credits remaining.', $real_quota, 'ewww-image-optimizer' ),
3132
+ $real_quota
3133
+ )
3134
+ );
3135
  } elseif ( 0 == $quota['licensed'] && 0 == $quota['consumed'] && 0 == $quota['days'] && 0 == $quota['metered'] ) {
3136
  return esc_html__( 'no credits remaining, please purchase more.', 'ewww-image-optimizer' );
3137
  } else {
3138
+ return esc_html(
3139
+ sprintf(
3140
+ /* translators: 1: Number of image credits used 2: Number of image credits available 3: days until subscription renewal */
3141
+ _n( 'used %1$d of %2$d, usage will reset in %3$d day.', 'used %1$d of %2$d, usage will reset in %3$d days.', $quota['days'], 'ewww-image-optimizer' ),
3142
+ $quota['consumed'],
3143
+ $quota['licensed'],
3144
+ $quota['days']
3145
+ )
3146
+ );
3147
  }
3148
  }
3149
  }
3200
  }
3201
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_skip_full' ) && $fullsize ) {
3202
  $metadata = 1;
3203
+ } elseif ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) ) {
3204
  // Don't copy metadata.
3205
  $metadata = 0;
3206
  } else {
3335
  $payload .= '--' . $boundary . '--';
3336
 
3337
  add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
3338
+ $response = wp_remote_post(
3339
+ $url,
3340
+ array(
3341
+ 'timeout' => 300,
3342
+ 'headers' => $headers,
3343
+ 'sslverify' => false,
3344
+ 'body' => $payload,
3345
+ )
3346
+ );
3347
  if ( is_wp_error( $response ) ) {
3348
  $error_message = $response->get_error_message();
3349
  ewwwio_debug_message( "optimize failed: $error_message" );
3468
  $payload .= '--' . $boundary . '--';
3469
 
3470
  add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
3471
+ $response = wp_remote_post(
3472
+ $url,
3473
+ array(
3474
+ 'timeout' => 60,
3475
+ 'headers' => $headers,
3476
+ 'sslverify' => false,
3477
+ 'body' => $payload,
3478
+ )
3479
+ );
3480
  if ( is_wp_error( $response ) ) {
3481
  $error_message = $response->get_error_message();
3482
  ewwwio_debug_message( "rotate failed: $error_message" );
3503
  }
3504
  }
3505
 
3506
+ /**
3507
+ * Uses the API to resize images.
3508
+ *
3509
+ * @since 4.4.0
3510
+ *
3511
+ * @param string $file The file to resize.
3512
+ * @param string $type File type of the file.
3513
+ * @param int|null $max_w Desired image width.
3514
+ * @param int|null $max_h Desired image height.
3515
+ * @param bool $crop Optional. Scale by default, crop if true.
3516
+ * @return string|WP_Error The image contents or the error message.
3517
+ */
3518
+ function ewww_image_optimizer_cloud_resize( $file, $type, $max_w, $max_h, $crop = false ) {
3519
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
3520
+ if ( ! ewwwio_check_memory_available( filesize( $file ) * 2.2 ) ) { // 2.2 = upload buffer + download buffer (2) multiplied by a factor of 1.1 for extra wiggle room.
3521
+ $memory_required = filesize( $file ) * 2.2;
3522
+ ewwwio_debug_message( "possibly insufficient memory for cloud (resize) operation: $memory_required" );
3523
+ if ( function_exists( 'wp_raise_memory_limit' ) ) {
3524
+ add_filter( 'image_memory_limit', 'ewww_image_optimizer_raise_memory_limit' );
3525
+ wp_raise_memory_limit( 'image' );
3526
+ }
3527
+ ewww_image_optimizer_debug_log();
3528
+ }
3529
+ $ewww_status = get_transient( 'ewww_image_optimizer_cloud_status' );
3530
+ $started = microtime( true );
3531
+ if ( false !== strpos( $ewww_status, 'exceeded' ) ) {
3532
+ if ( ! ewww_image_optimizer_cloud_verify() ) {
3533
+ ewwwio_debug_message( 'cloud verify failed, image not resized' );
3534
+ return new WP_Error( 'invalid_key', __( 'Could not verify API key', 'ewww-image-optimizer' ) );
3535
+ }
3536
+ }
3537
+ // Calculate how much time has elapsed since we started.
3538
+ $elapsed = microtime( true ) - $started;
3539
+ ewwwio_debug_message( "cloud verify took $elapsed seconds" );
3540
+ $ewww_status = get_transient( 'ewww_image_optimizer_cloud_status' );
3541
+ if ( ( ! empty( $ewww_status ) && preg_match( '/exceeded/', $ewww_status ) ) || ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_exceeded' ) > time() ) {
3542
+ ewwwio_debug_message( 'license exceeded, image not rotated' );
3543
+ return new WP_Error( 'invalid_key', __( 'License Exceeded', 'ewww-image-optimizer' ) );
3544
+ }
3545
+ ewwwio_debug_message( "file: $file " );
3546
+ ewwwio_debug_message( "width: $max_w" );
3547
+ ewwwio_debug_message( "height: $max_h" );
3548
+ $api_key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
3549
+ if ( empty( $api_key ) ) {
3550
+ return new WP_Error( 'invalid_key', __( 'Could not verify API key', 'ewww-image-optimizer' ) );
3551
+ }
3552
+ $url = 'http://optimize.exactlywww.com/resize/';
3553
+ $ssl = wp_http_supports( array( 'ssl' ) );
3554
+ if ( $ssl ) {
3555
+ $url = set_url_scheme( $url, 'https' );
3556
+ }
3557
+ $boundary = wp_generate_password( 24, false );
3558
+
3559
+ $headers = array(
3560
+ 'content-type' => 'multipart/form-data; boundary=' . $boundary,
3561
+ 'timeout' => 60,
3562
+ 'httpversion' => '1.0',
3563
+ 'blocking' => true,
3564
+ );
3565
+
3566
+ $post_fields = array(
3567
+ 'filename' => $file,
3568
+ 'api_key' => $api_key,
3569
+ 'width' => (int) $max_w,
3570
+ 'height' => (int) $max_h,
3571
+ 'crop' => (int) $crop,
3572
+ );
3573
+
3574
+ $payload = '';
3575
+ foreach ( $post_fields as $name => $value ) {
3576
+ $payload .= '--' . $boundary;
3577
+ $payload .= "\r\n";
3578
+ $payload .= 'Content-Disposition: form-data; name="' . $name . '"' . "\r\n\r\n";
3579
+ $payload .= $value;
3580
+ $payload .= "\r\n";
3581
+ }
3582
+
3583
+ $payload .= '--' . $boundary;
3584
+ $payload .= "\r\n";
3585
+ $payload .= 'Content-Disposition: form-data; name="file"; filename="' . basename( $file ) . '"' . "\r\n";
3586
+ $payload .= 'Content-Type: ' . $type . "\r\n";
3587
+ $payload .= "\r\n";
3588
+ $payload .= file_get_contents( $file );
3589
+ $payload .= "\r\n";
3590
+ $payload .= '--' . $boundary;
3591
+ $payload .= 'Content-Disposition: form-data; name="submitHandler"' . "\r\n";
3592
+ $payload .= "\r\n";
3593
+ $payload .= "Upload\r\n";
3594
+ $payload .= '--' . $boundary . '--';
3595
+
3596
+ add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
3597
+ $response = wp_remote_post(
3598
+ $url,
3599
+ array(
3600
+ 'timeout' => 60,
3601
+ 'headers' => $headers,
3602
+ 'sslverify' => false,
3603
+ 'body' => $payload,
3604
+ )
3605
+ );
3606
+ if ( is_wp_error( $response ) ) {
3607
+ $error_message = $response->get_error_message();
3608
+ ewwwio_debug_message( "resize failed: $error_message" );
3609
+ return $response;
3610
+ } else {
3611
+ $tempfile = $file . '.tmp';
3612
+ file_put_contents( $tempfile, $response['body'] );
3613
+ $orig_size = filesize( $file );
3614
+ $newsize = $orig_size;
3615
+ if ( false !== strpos( $response['body'], 'error' ) ) {
3616
+ $response = json_decode( $response['body'], true );
3617
+ ewwwio_debug_message( 'API resize error: ' . $response['error'] );
3618
+ unlink( $tempfile );
3619
+ return new WP_Error( 'image_resize_error', $response['error'] );
3620
+ } elseif ( false !== strpos( ewww_image_optimizer_mimetype( $tempfile, 'i' ), 'image' ) ) {
3621
+ $newsize = filesize( $tempfile );
3622
+ ewww_image_optimizer_is_animated( $tempfile );
3623
+ ewwwio_debug_message( "API resize success: $newsize (new) vs. $orig_size (original)" );
3624
+ unlink( $tempfile );
3625
+ return $response['body'];
3626
+ }
3627
+ unlink( $tempfile );
3628
+ ewwwio_debug_message( 'API resize error: unknown' );
3629
+ return new WP_Error( 'image_resize_error', __( 'Unknown resize error', 'ewww-image-optimizer' ) );
3630
+ }
3631
+ }
3632
+
3633
  /**
3634
  * Setup our own database connection with full utf8 capability.
3635
  *
3691
  if ( is_wp_error( $prefix ) ) {
3692
  wp_load_translations_early();
3693
  wp_die(
3694
+ sprintf(
3695
+ /* translators: 1: $table_prefix 2: wp-config.php */
3696
+ __( '<strong>ERROR</strong>: %1$s in %2$s can only contain numbers, letters, and underscores.' ),
3697
  '<code>$table_prefix</code>',
3698
  '<code>wp-config.php</code>'
3699
  )
3763
  // Make sure the image isn't pending.
3764
  if ( $image['pending'] ) {
3765
  global $wpdb;
3766
+ $wpdb->update(
3767
+ $wpdb->ewwwio_images,
3768
  array(
3769
  'pending' => 0,
3770
  ),
3887
  ewwwio_debug_message( print_r( $updates, true ) );
3888
  }
3889
  // Update information for the image.
3890
+ $record_updated = $ewwwdb->update(
3891
+ $ewwwdb->ewwwio_images,
3892
  $updates,
3893
  array(
3894
  'id' => $already_optimized['id'],
4047
  // Calculate how much time has elapsed since we started.
4048
  $elapsed = microtime( true ) - $started;
4049
  // Output how much time has elapsed since we started.
4050
+ $output['results'] .= sprintf(
4051
+ esc_html(
4052
+ /* translators: %s: number of seconds */
4053
+ _n( 'Elapsed: %s second', 'Elapsed: %s seconds', $elapsed, 'ewww-image-optimizer' )
4054
+ ) . '</p>',
4055
+ number_format_i18n( $elapsed )
4056
+ );
4057
  if ( get_site_option( 'ewww_image_optimizer_debug' ) ) {
4058
  global $ewww_debug;
4059
  $output['results'] .= '<div style="background-color:#ffff99;">' . $ewww_debug . '</div>';
4335
  // If we found records for both local and s3 paths, we delete the s3 record, but store the original size in the local record.
4336
  if ( ! empty( $found_local_image ) && is_array( $found_local_image ) ) {
4337
  ewwwio_debug_message( "found $local_path in db" );
4338
+ $ewwwdb->delete(
4339
+ $ewwwdb->ewwwio_images,
4340
  array(
4341
  'id' => $s3_image['id'],
4342
  ),
4345
  )
4346
  );
4347
  if ( $s3_image['orig_size'] > $found_local_image['orig_size'] ) {
4348
+ $ewwwdb->update(
4349
+ $ewwwdb->ewwwio_images,
4350
  array(
4351
  'orig_size' => $s3_image['orig_size'],
4352
  'results' => $s3_image['results'],
4359
  } else {
4360
  // If we just found an s3 path and no local match, then we just update the path in the table to the local path.
4361
  ewwwio_debug_message( 'just updating s3 to local' );
4362
+ $ewwwdb->update(
4363
+ $ewwwdb->ewwwio_images,
4364
  array(
4365
  'path' => ewww_image_optimizer_relative_path_remove( $local_path ),
4366
  ),
4387
  }
4388
  }
4389
 
4390
+ /**
4391
+ * Determines scaling dimensions to be used for two phase cropping.
4392
+ *
4393
+ * @param int $current_width The width of the original image.
4394
+ * @param int $current_height The height of the original image.
4395
+ * @param int $max_width The maximum width of the final image.
4396
+ * @param int $max_height The maximum height of the final image.
4397
+ * @return array X coordinate, Y coordinate, width and height in pixels.
4398
+ */
4399
+ function ewwwio_crop_dimensions( $current_width, $current_height, $max_width = 0, $max_height = 0 ) {
4400
+ if ( ! $max_width && ! $max_height ) {
4401
+ return array( 0, 0, $current_width, $current_height );
4402
+ }
4403
+ if ( $max_width ) {
4404
+ $max_width = min( $max_width, $current_width );
4405
+ } else {
4406
+ $max_width = $current_width;
4407
+ }
4408
+ if ( $max_height ) {
4409
+ $max_height = min( $max_height, $current_height );
4410
+ } else {
4411
+ $max_height = $current_height;
4412
+ }
4413
+ $w = $current_width;
4414
+ $h = $current_height;
4415
+ $x = 0;
4416
+ $y = 0;
4417
+
4418
+ if ( $current_height > $current_width ) {
4419
+ $h = round( $current_width * $max_height / $max_width );
4420
+ $y = round( ( $current_height - $h ) / 2 );
4421
+ } elseif ( $current_height == $current_width ) {
4422
+ if ( $max_width > $max_height ) {
4423
+ $h = round( $current_width * $max_height / $max_width );
4424
+ $y = round( ( $current_height - $h ) / 2 );
4425
+ } else {
4426
+ $w = round( $current_height * $max_width / $max_height );
4427
+ $x = round( ( $current_width - $w ) / 2 );
4428
+ }
4429
+ } else {
4430
+ $w = round( $current_height * $max_width / $max_height );
4431
+ $x = round( ( $current_width - $w ) / 2 );
4432
+ }
4433
+ return array( $x, $y, $w, $h );
4434
+ }
4435
+
4436
+ /**
4437
+ * Uses gifsicle or the API to resize an image.
4438
+ *
4439
+ * @since 4.4.0
4440
+ *
4441
+ * @param string $file The file to resize.
4442
+ * @param int|null $max_w Desired image width.
4443
+ * @param int|null $max_h Desired image height.
4444
+ * @param bool $crop Optional. Scale by default, crop if true.
4445
+ * @return string|WP_Error The image contents or the error message.
4446
+ */
4447
+ function ewww_image_optimizer_better_resize( $file, $max_w, $max_h, $crop = false ) {
4448
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
4449
+ $type = ewww_image_optimizer_mimetype( $file, 'i' );
4450
+ if ( false === strpos( $type, 'image' ) ) {
4451
+ ewwwio_debug_message( 'not an image, no resizing possible' );
4452
+ return new WP_Error( 'invalid_image', __( 'File is not an image.' ), $file );
4453
+ }
4454
+ if ( 'image/gif' == $type && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) && function_exists( 'ewww_image_optimizer_gifsicle_resize' ) ) {
4455
+ return ewww_image_optimizer_gifsicle_resize( $file, $max_w, $max_h, $crop );
4456
+ }
4457
+ return ewww_image_optimizer_cloud_resize( $file, $type, $max_w, $max_h, $crop );
4458
+ }
4459
+
4460
  /**
4461
  * If a JPG image is using the EXIF orientiation, correct the rotation, and reset the Orientation.
4462
  *
4479
  if ( ! $orientation || 1 == $orientation ) {
4480
  return;
4481
  }
4482
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) < 20 && function_exists( 'ewww_image_optimizer_jpegtran_autorotate' ) ) {
4483
  // Read the exif, if it fails, we won't autorotate.
4484
  try {
4485
  $jpeg = new PelJpeg( $file );
4658
  }
4659
 
4660
  // From here...
4661
+ global $ewww_preempt_editor;
4662
+ $ewww_preempt_editor = true;
4663
+ /* remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 ); */
4664
  $editor = wp_get_image_editor( $file );
4665
  if ( is_wp_error( $editor ) ) {
4666
  ewwwio_debug_message( 'could not get image editor' );
4691
  }
4692
  $resized_image = $editor->resize( $newwidth, $newheight, $crop );
4693
  if ( is_wp_error( $resized_image ) ) {
4694
+ $error_message = $resized_image->get_error_message();
4695
+ ewwwio_debug_message( "error during resizing: $error_message" );
4696
  return false;
4697
  }
4698
  $new_file = $editor->generate_filename( 'tmp' );
4700
  ewwwio_debug_message( "before resizing: $orig_size" );
4701
  $saved = $editor->save( $new_file );
4702
  if ( is_wp_error( $saved ) ) {
4703
+ $error_message = $saved->get_error_message();
4704
+ ewwwio_debug_message( "error saving resized image: $error_message" );
4705
  }
4706
  if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_noauto' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_editor' ) ) {
4707
+ $ewww_preempt_editor = false;
4708
+ /* add_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 ); */
4709
  }
4710
  // to here is replaced by cloud/API function.
4711
  $new_size = ewww_image_optimizer_filesize( $new_file );
4715
  ewwwio_debug_message( "after resizing: $new_size" );
4716
  // TODO: see if there is a way to just check that meta exists on the new image.
4717
  // Use PEL to get the exif (if Remove Meta is unchecked) and GD is in use, so we can save it to the new image.
4718
+ if ( 'image/jpeg' === $type && ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_skip_full' ) || ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) ) && ! ewww_image_optimizer_imagick_support() ) {
4719
  ewwwio_debug_message( 'manually copying metadata for GD' );
4720
  try {
4721
  $old_jpeg = new PelJpeg( $file );
4756
  $already_optimized = ewww_image_optimizer_find_already_optimized( $file );
4757
  // If the original file has never been optimized, then just update the record that was created with the proper filename (because the resized file has usually been optimized).
4758
  if ( empty( $already_optimized ) ) {
4759
+ $tmp_exists = $ewwwdb->update(
4760
+ $ewwwdb->ewwwio_images,
4761
  array(
4762
  'path' => ewww_image_optimizer_relative_path_remove( $file ),
4763
  'orig_size' => $orig_size,
4768
  );
4769
  // If the tmp file didn't get optimized (and it shouldn't), then just insert a dummy record to be updated shortly.
4770
  if ( ! $tmp_exists ) {
4771
+ $ewwwdb->insert(
4772
+ $ewwwdb->ewwwio_images,
4773
+ array(
4774
+ 'path' => ewww_image_optimizer_relative_path_remove( $file ),
4775
+ 'orig_size' => $orig_size,
4776
+ )
4777
+ );
4778
  }
4779
  } else {
4780
  // Otherwise, we delete the record created from optimizing the resized file.
4781
  $temp_optimized = ewww_image_optimizer_find_already_optimized( $new_file );
4782
  if ( is_array( $temp_optimized ) && ! empty( $temp_optimized['id'] ) ) {
4783
+ $ewwwdb->delete(
4784
+ $ewwwdb->ewwwio_images,
4785
  array(
4786
  'id' => $temp_optimized['id'],
4787
  ),
4809
  */
4810
  function ewww_image_optimizer_get_orientation( $file, $type ) {
4811
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
4812
+ if ( function_exists( 'exif_read_data' ) && 'image/jpeg' === $type && is_readable( $file ) ) {
4813
  $exif = @exif_read_data( $file );
4814
  if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
4815
  ewwwio_debug_message( print_r( $exif, true ) );
5038
  function ewww_image_optimizer_rebuild_meta( $attachment_id ) {
5039
  $file = get_attached_file( $attachment_id );
5040
  if ( is_file( $file ) ) {
5041
+ global $ewww_preempt_editor;
5042
+ $ewww_preempt_editor = true;
5043
+ /* remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 ); */
5044
  remove_all_filters( 'wp_generate_attachment_metadata' );
5045
  ewwwio_debug_message( "generating new meta for $attachment_id" );
5046
  $meta = wp_generate_attachment_metadata( $attachment_id, $file );
5176
  if ( is_array( $already_optimized ) ) {
5177
  ewwwio_debug_message( "updating existing record, path: $file_path, size: " . $image_size );
5178
  // Store info on the current image for future reference.
5179
+ $ewwwdb->update(
5180
+ $ewwwdb->ewwwio_images,
5181
  array(
5182
  'path' => ewww_image_optimizer_relative_path_remove( $file_path ),
5183
  'attachment_id' => $id,
5212
  $ewwwio_media_background = new EWWWIO_Media_Background_Process();
5213
  }
5214
  ewwwio_debug_message( "backgrounding optimization for $id" );
5215
+ $ewwwio_media_background->push_to_queue(
5216
+ array(
5217
+ 'id' => $id,
5218
+ 'new' => $new_image,
5219
+ 'type' => $type,
5220
+ )
5221
+ );
5222
  $ewwwio_media_background->save()->dispatch();
5223
  set_transient( 'ewwwio-background-in-progress-' . $id, true, 24 * HOUR_IN_SECONDS );
5224
  if ( $log ) {
5329
  if ( is_array( $already_optimized ) ) {
5330
  ewwwio_debug_message( "updating existing record, path: $ims_path, size: " . $image_size );
5331
  // Store info on the current image for future reference.
5332
+ $ewwwdb->update(
5333
+ $ewwwdb->ewwwio_images,
5334
  array(
5335
  'path' => ewww_image_optimizer_relative_path_remove( $ims_path ),
5336
  ),
5558
  }
5559
  if ( class_exists( 'Cloudinary' ) && Cloudinary::config_get( 'api_secret' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_cloudinary' ) && ! empty( $new_image ) ) {
5560
  try {
5561
+ $result = CloudinaryUploader::upload(
5562
+ $file,
5563
+ array( 'use_filename' => true )
5564
+ );
5565
  } catch ( Exception $e ) {
5566
  $error = $e->getMessage();
5567
  }
5571
  ewwwio_debug_message( 'successfully uploaded to Cloudinary' );
5572
  // Register the attachment in the database as a cloudinary attachment.
5573
  $old_url = wp_get_attachment_url( $id );
5574
+ wp_update_post(
5575
+ array(
5576
+ 'ID' => $id,
5577
+ 'guid' => $result['url'],
5578
+ )
5579
+ );
5580
  update_attached_file( $id, $result['url'] );
5581
  $meta['cloudinary'] = true;
5582
  $errors = array();
5616
  return false;
5617
  }
5618
 
5619
+ /**
5620
+ * Parse image paths for WP Offload S3.
5621
+ *
5622
+ * Adds WebP derivatives so that they can be uploaded.
5623
+ *
5624
+ * @param array $paths The image paths currently queued for upload.
5625
+ * @param int $id The ID number of the image in the database.
5626
+ * @return array Attachment meta field.
5627
+ */
5628
+ function ewww_image_optimizer_as3cf_attachment_file_paths( $paths, $id ) {
5629
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
5630
+ foreach ( $paths as $size => $path ) {
5631
+ if ( is_string( $path ) ) {
5632
+ $paths[ $size . '-webp' ] = $path . '.webp';
5633
+ ewwwio_debug_message( "added $path.webp to as3cf queue" );
5634
+ }
5635
+ }
5636
+ return $paths;
5637
+ }
5638
+ /**
5639
+ * Fixes the ContentType for WebP images because WP mimetype detection stinks.
5640
+ *
5641
+ * @param array $args The parameters to be used for the S3 upload.
5642
+ * @return array The same parameters with ContentType corrected.
5643
+ */
5644
+ function ewww_image_optimizer_as3cf_object_meta( $args ) {
5645
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
5646
+ if ( ! empty( $args['SourceFile'] ) && is_file( $args['SourceFile'] ) && empty( $args['ContentType'] ) && false !== strpos( $args['SourceFile'], '.webp' ) ) {
5647
+ $args['ContentType'] = ewww_image_optimizer_quick_mimetype( $args['SourceFile'] );
5648
+ }
5649
+ return $args;
5650
+ }
5651
  /**
5652
  * Update the attachment's meta data after being converted.
5653
  *
5751
  $mime = 'image/gif';
5752
  }
5753
  // Update the attachment post with the new mimetype and id.
5754
+ wp_update_post(
5755
+ array(
5756
+ 'ID' => $id,
5757
+ 'post_mime_type' => $mime,
5758
+ )
5759
+ );
5760
  ewww_image_optimizer_debug_log();
5761
  ewwwio_memory( __FUNCTION__ );
5762
  return $meta;
6303
  // Output the optimizer actions.
6304
  if ( current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
6305
  // Display a link to re-optimize manually.
6306
+ $output .= '<div>' . sprintf(
6307
+ "<a class='ewww-manual-optimize' data-id='$id' data-nonce='$ewww_manual_nonce' href=\"admin.php?action=ewww_image_optimizer_manual_optimize&amp;ewww_manual_nonce=$ewww_manual_nonce&amp;ewww_force=1&amp;ewww_attachment_ID=%d\">%s</a>",
6308
  $id,
6309
  esc_html__( 'Re-optimize', 'ewww-image-optimizer' )
6310
  ) . '</div>';
6311
  }
6312
  if ( $backup_available && current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
6313
+ $output .= '<div>' . sprintf(
6314
+ "<a class='ewww-manual-cloud-restore' data-id='$id' data-nonce='$ewww_manual_nonce' href=\"admin.php?action=ewww_image_optimizer_manual_cloud_restore&amp;ewww_manual_nonce=$ewww_manual_nonce&amp;ewww_attachment_ID=%d\">%s</a>",
6315
  $id,
6316
  esc_html__( 'Restore original', 'ewww-image-optimizer' )
6317
  ) . '</div>';
6321
  // Give the user the option to optimize the image right now.
6322
  if ( isset( $meta['sizes'] ) && ewww_image_optimizer_iterable( $meta['sizes'] ) ) {
6323
  $sizes_to_opt = ewww_image_optimizer_count_unoptimized_sizes( $meta['sizes'] ) + 1;
6324
+ $output .= '<div>' . sprintf(
6325
+ esc_html(
6326
+ /* translators: %d: The number of resize/thumbnail images */
6327
+ _n( '%d size to compress', '%d sizes to compress', $sizes_to_opt, 'ewww-image-optimizer' )
6328
+ ),
6329
+ $sizes_to_opt
6330
+ ) . '</div>';
6331
  }
6332
  $output .= '<div>' . sprintf( "<a class='ewww-manual-optimize' data-id='$id' data-nonce='$ewww_manual_nonce' href=\"admin.php?action=ewww_image_optimizer_manual_optimize&amp;ewww_manual_nonce=$ewww_manual_nonce&amp;ewww_attachment_ID=%d\">%s</a>", $id, esc_html__( 'Optimize now!', 'ewww-image-optimizer' ) ) . '</div>';
6333
  }
6376
 
6377
  if ( empty( $msg ) && current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
6378
  // Output a link to re-optimize manually.
6379
+ $output .= '<div>' . sprintf(
6380
+ "<a class='ewww-manual-optimize' data-id='$id' data-nonce='$ewww_manual_nonce' href=\"admin.php?action=ewww_image_optimizer_manual_optimize&amp;ewww_manual_nonce=$ewww_manual_nonce&amp;ewww_force=1&amp;ewww_attachment_ID=%d\">%s</a>",
6381
  $id,
6382
  esc_html__( 'Re-optimize', 'ewww-image-optimizer' )
6383
  );
6393
  $restorable = true;
6394
  }
6395
  if ( $restorable && current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
6396
+ $output .= '<div>' . sprintf(
6397
+ "<a class='ewww-manual-restore' data-id='$id' data-nonce='$ewww_manual_nonce' href=\"admin.php?action=ewww_image_optimizer_manual_restore&amp;ewww_manual_nonce=$ewww_manual_nonce&amp;ewww_attachment_ID=%d\">%s</a>",
6398
  $id,
6399
  esc_html__( 'Restore original', 'ewww-image-optimizer' )
6400
  ) . '</div>';
6401
  } elseif ( $backup_available && current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
6402
+ $output .= '<div>' . sprintf(
6403
+ "<a class='ewww-manual-cloud-restore' data-id='$id' data-nonce='$ewww_manual_nonce' href=\"admin.php?action=ewww_image_optimizer_manual_cloud_restore&amp;ewww_manual_nonce=$ewww_manual_nonce&amp;ewww_attachment_ID=%d\">%s</a>",
6404
  $id,
6405
  esc_html__( 'Restore original', 'ewww-image-optimizer' )
6406
  ) . '</div>';
6409
  // Otherwise, this must be an image we haven't processed.
6410
  if ( isset( $meta['sizes'] ) && ewww_image_optimizer_iterable( $meta['sizes'] ) ) {
6411
  $sizes_to_opt = ewww_image_optimizer_count_unoptimized_sizes( $meta['sizes'] ) + 1;
6412
+ $output .= '<div>' . sprintf(
6413
+ esc_html(
6414
+ /* translators: %d: The number of resize/thumbnail images */
6415
+ _n( '%d size to compress', '%d sizes to compress', $sizes_to_opt, 'ewww-image-optimizer' )
6416
+ ),
6417
+ $sizes_to_opt
6418
+ ) . '</div>';
6419
  } else {
6420
  $output .= '<div>' . esc_html__( 'Not processed', 'ewww-image-optimizer' ) . '</div>';
6421
  }
6546
  }
6547
  $detail_output .= '</table>';
6548
 
6549
+ $output .= '<div>' . sprintf(
6550
+ esc_html(
6551
+ /* translators: %d: number of resizes/thumbnails compressed */
6552
+ _n( '%d size compressed', '%d sizes compressed', $sizes_to_opt, 'ewww-image-optimizer' )
6553
+ ),
6554
+ $sizes_to_opt
6555
+ );
6556
  $output .= " <a href='#TB_inline?width=550&height=450&inlineId=ewww-attachment-detail-$id' class='thickbox'>(+)</a></div>";
6557
  $results_msg = ewww_image_optimizer_image_results( $orig_size, $opt_size );
6558
  // Output the optimizer results.
6817
  check_admin_referer( 'bulk-media' );
6818
  // Prep the attachment IDs for optimization.
6819
  $ids = implode( ',', array_map( 'intval', $_REQUEST['media'] ) );
6820
+ wp_redirect(
6821
+ add_query_arg(
6822
+ array(
6823
+ 'page' => 'ewww-image-optimizer-bulk',
6824
+ 'ids' => $ids,
6825
+ ),
6826
+ admin_url( 'upload.php' )
6827
+ )
6828
+ );
6829
  ewwwio_memory( __FUNCTION__ );
6830
  exit();
6831
  }
6915
  wp_enqueue_style( 'jquery-ui-tooltip-custom', plugins_url( '/includes/jquery-ui-1.10.1.custom.css', __FILE__ ), array(), EWWW_IMAGE_OPTIMIZER_VERSION );
6916
  wp_enqueue_script( 'postbox' );
6917
  wp_enqueue_script( 'dashboard' );
6918
+ wp_localize_script( 'ewwwbulkscript', 'ewww_vars', array( '_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-settings' ) ) );
 
 
6919
  ewwwio_memory( __FUNCTION__ );
6920
  return;
6921
  }
6946
  }
6947
  if ( function_exists( 'get_sites' ) ) {
6948
  ewwwio_debug_message( 'retrieving list of sites the easy way (4.6+)' );
6949
+ $blogs = get_sites(
6950
+ array(
6951
+ 'fields' => 'ids',
6952
+ 'number' => 1000,
6953
+ )
6954
+ );
6955
  } elseif ( function_exists( 'wp_get_sites' ) ) {
6956
  ewwwio_debug_message( 'retrieving list of sites the easy way (pre 4.6)' );
6957
+ $blogs = wp_get_sites(
6958
+ array(
6959
+ 'network_id' => $wpdb->siteid,
6960
+ 'limit' => 1000,
6961
+ )
6962
+ );
6963
  }
6964
  if ( ewww_image_optimizer_iterable( $blogs ) ) {
6965
  foreach ( $blogs as $blog ) {
7355
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) > 20 ) {
7356
  $compress_score += 50;
7357
  } else {
7358
+ $compress_recommendations[] = esc_html__( 'Enable premium compression for JPG images.', 'ewww-image-optimizer' );
7359
  }
7360
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) > 20 ) {
7361
  $compress_score += 20;
7362
  } else {
7363
+ $compress_recommendations[] = esc_html__( 'Enable premium compression for PNG images.', 'ewww-image-optimizer' );
7364
  }
7365
  $status_notices .= '<span style="color: #3eadc9; font-weight: bolder">' . esc_html__( 'Verified,', 'ewww-image-optimizer' ) . ' </span>' . ewww_image_optimizer_cloud_quota();
7366
  } elseif ( false !== strpos( $verify_cloud, 'exceeded' ) ) {
7396
  if ( ewww_image_optimizer_get_option( 'exactdn_lossy' ) ) {
7397
  $compress_score = 100;
7398
  } elseif ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) < 30 ) {
7399
+ $compress_recommendations[] = esc_html__( 'Enable premium compression.', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/47-getting-more-from-exactdn', '59de6631042863379ddc953c' );
7400
  }
7401
  } elseif ( $exactdn->get_exactdn_domain() && $exactdn->get_exactdn_option( 'verified' ) ) {
7402
  $status_notices .= '<span style="color: orange; font-weight: bolder">' . esc_html__( 'Temporarily disabled.', 'ewww-image-optimizer' ) . ' </span>';
7555
  $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";
7556
  }
7557
 
7558
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) == true ) {
7559
  $compress_score += 5;
7560
  } else {
7561
  $compress_recommendations[] = esc_html__( 'Remove metadata from JPG images.', 'ewww-image-optimizer' ) . ewwwio_help_link( 'https://docs.ewww.io/article/7-basic-configuration', '585373d5c697912ffd6c0bb2' );
7696
  }
7697
  $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>' .
7698
  "<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";
7699
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_metadata_remove'>" . esc_html__( 'Remove Metadata', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/7-basic-configuration', '585373d5c697912ffd6c0bb2' ) . "</th>\n" .
7700
+ "<td><input type='checkbox' id='ewww_image_optimizer_metadata_remove' name='ewww_image_optimizer_metadata_remove' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) == 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";
7701
+ ewwwio_debug_message( 'remove metadata: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) == true ? 'on' : 'off' ) );
7702
  $output[] = "<tr class='$network_class'><th>&nbsp;</th><td>" .
7703
  "<p class='$network_class description'>" . esc_html__( 'All methods used by the EWWW Image Optimizer are intended to produce visually identical images.', 'ewww-image-optimizer' ) .
7704
+ /* ' ' . esc_html__( 'Lossless compression is actually identical to the original, while lossy reduces the quality a small amount.', 'ewww-image-optimizer' ) . */ "</p>\n" .
7705
  ( ! 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" : '' );
7706
  $output[] = "</td></tr>\n";
7707
  $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" .
7708
  "<td><span><select id='ewww_image_optimizer_jpg_level' name='ewww_image_optimizer_jpg_level'>\n" .
7709
  "<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";
7710
  if ( defined( 'EWWW_IMAGE_OPTIMIZER_TOOL_PATH' ) ) {
7711
+ $output[] = "<option class='$network_class' value='10'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ), 10, false ) . '>' . esc_html__( 'Pixel Perfect', 'ewww-image-optimizer' ) . "</option>\n";
7712
  }
7713
+ $output[] = "<option class='$network_class' $disable_level value='20'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ), 20, false ) . '>' . esc_html__( 'Pixel Perfect Plus', 'ewww-image-optimizer' ) . " *</option>\n" .
7714
+ "<option $disable_level value='30'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ), 30, false ) . '>' . esc_html__( 'Premium', 'ewww-image-optimizer' ) . " *</option>\n" .
7715
+ "<option $disable_level value='40'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ), 40, false ) . '>' . esc_html__( 'Premium Plus', 'ewww-image-optimizer' ) . " *</option>\n" .
7716
  "</select></td></tr>\n";
7717
  ewwwio_debug_message( 'jpg level: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) );
7718
  $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" .
7719
  "<td><span><select id='ewww_image_optimizer_png_level' name='ewww_image_optimizer_png_level'>\n" .
7720
  "<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";
7721
  if ( defined( 'EWWW_IMAGE_OPTIMIZER_TOOL_PATH' ) ) {
7722
+ $output[] = "<option class='$network_class' value='10'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ), 10, false ) . '>' . esc_html__( 'Pixel Perfect', 'ewww-image-optimizer' ) . "</option>\n";
7723
  }
7724
  $output[] = "<option class='$network_class' $disable_level value='20' " . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ), 20, false ) .
7725
+ selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ), 30, false ) . '>' . esc_html__( 'Pixel Perfect Plus', 'ewww-image-optimizer' ) . " *</option>\n" .
7726
+ "<option value='40'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ), 40, false ) . '>' . esc_html__( 'Premium', 'ewww-image-optimizer' ) . "</option>\n" .
7727
+ "<option $disable_level value='50'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ), 50, false ) . '>' . esc_html__( 'Premium Plus', 'ewww-image-optimizer' ) . " *</option>\n" .
7728
  "</select></td></tr>\n";
7729
  ewwwio_debug_message( 'png level: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) );
7730
  $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" .
7731
  "<td><span><select id='ewww_image_optimizer_gif_level' name='ewww_image_optimizer_gif_level'>\n" .
7732
  "<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" .
7733
+ "<option value='10'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' ), 10, false ) . '>' . esc_html__( 'Pixel Perfect', 'ewww-image-optimizer' ) . "</option>\n" .
7734
  "</select></td></tr>\n";
7735
  ewwwio_debug_message( 'gif level: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' ) );
7736
  $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" .
7737
  "<td><span><select id='ewww_image_optimizer_pdf_level' name='ewww_image_optimizer_pdf_level'>\n" .
7738
  "<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" .
7739
+ "<option $disable_level value='10'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ), 10, false ) . '>' . esc_html__( 'Pixel Perfect', 'ewww-image-optimizer' ) . " *</option>\n" .
7740
+ "<option $disable_level value='20'" . selected( ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ), 20, false ) . '>' . esc_html__( 'High Compression', 'ewww-image-optimizer' ) . " *</option>\n" .
7741
  "</select></td></tr>\n";
7742
  ewwwio_debug_message( 'pdf level: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ) );
7743
  ewwwio_debug_message( 'bulk delay: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_delay' ) );
7766
  '<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>' .
7767
  "</p></td></tr>\n";
7768
  ewwwio_debug_message( 'ExactDN enabled: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) == true ? 'on' : 'off' ) );
7769
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_backup_files'>" . esc_html__( 'Include All Resources', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/47-getting-more-from-exactdn', '59de6631042863379ddc953c' ) . '</th>' .
7770
+ "<td><input type='checkbox' id='exactdn_all_the_things' name='exactdn_all_the_things' value='true' " .
7771
+ ( ewww_image_optimizer_get_option( 'exactdn_all_the_things' ) ? "checked='true'" : '' ) . '> ' . esc_html__( 'Use ExactDN for all resources in wp-includes/ and wp-content/, including JavaScript, CSS, fonts, etc.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7772
  ewwwio_debug_message( 'ExactDN all the things: ' . ( ewww_image_optimizer_get_option( 'exactdn_all_the_things' ) == true ? 'on' : 'off' ) );
7773
+ $output[] = "<tr class='$network_class'><th scope='row'><label for='exactdn_lossy'>" . esc_html__( 'Premium Compression', 'ewww-image-optimizer' ) . '</label>' . ewwwio_help_link( 'https://docs.ewww.io/article/47-getting-more-from-exactdn', '59de6631042863379ddc953c' ) . '</th>' .
7774
+ "<td><input type='checkbox' id='exactdn_lossy' name='exactdn_lossy' value='true' " .
7775
+ ( ewww_image_optimizer_get_option( 'exactdn_lossy' ) ? "checked='true'" : '' ) . '> ' . esc_html__( 'Enable high quality premium compression for all images. Disable to use Pixel Perfect mode instead.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7776
  ewwwio_debug_message( 'ExactDN lossy: ' . intval( ewww_image_optimizer_get_option( 'exactdn_lossy' ) ) );
7777
  ewwwio_debug_message( 'ExactDN resize existing: ' . ( ewww_image_optimizer_get_option( 'exactdn_resize_existing' ) == true ? 'on' : 'off' ) );
7778
  ewwwio_debug_message( 'ExactDN attachment queries: ' . ( ewww_image_optimizer_get_option( 'exactdn_prevent_db_queries' ) == true ? 'off' : 'on' ) );
7985
  '</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' " .
7986
  ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) == true ? "checked='true'" : '' ) . ' /> ' .
7987
  esc_html__( 'Use this if the Apache rewrite rules do not work, or if your images are served from a CDN.', 'ewww-image-optimizer' ) . ' ' .
7988
+ esc_html__( 'Requires jQuery, but may be loaded using async/defer methods or even combined with other scripts.', 'ewww-image-optimizer' ) . ' ' .
7989
  /* translators: %s: Cache Enabler (link) */
7990
  ( ! 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>';
7991
  }
8282
  */
8283
  function ewww_image_optimizer_admin_bar_menu() {
8284
  global $wp_admin_bar;
8285
+ $wp_admin_bar->add_menu(
8286
+ array(
8287
+ 'id' => 'resize-detection',
8288
+ 'parent' => 'top-secondary',
8289
+ 'title' => __( 'Detect Scaled Images', 'ewww-image-optimizer' ),
8290
+ )
8291
+ );
8292
  }
8293
 
8294
  /**
8522
 
8523
  $key = 'wp_ewwwio_media_optimize_batch_%';
8524
  $queues = $wpdb->get_results(
8525
+ $wpdb->prepare(
8526
+ "SELECT *
8527
  FROM $wpdb->options
8528
  WHERE option_name LIKE %s AND option_value != ''
8529
+ ORDER BY option_id ASC",
8530
+ $key
8531
+ ),
8532
  ARRAY_A
8533
  );
8534
 
8673
  ewwwio_debug_message( print_r( $var3, true ) );
8674
  return $var;
8675
  }
8676
+
8677
+ /**
8678
+ * Dummy function to preserve old strings.
8679
+ */
8680
+ function ewwwio_preserve_strings() {
8681
+ $string1 = __( 'Lossless Compression', 'ewww-image-optimizer' );
8682
+ $string2 = __( 'Lossy Compression', 'ewww-image-optimizer' );
8683
+ $string3 = __( 'Maximum Lossless Compression', 'ewww-image-optimizer' );
8684
+ $string4 = __( 'Maximum Lossy Compression', 'ewww-image-optimizer' );
8685
+ }
8686
  ?>
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.3.2
18
  Author URI: https://ewww.io/
19
  License: GPLv3
20
  */
@@ -37,7 +37,7 @@ if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_TOOL_PATH' ) ) {
37
  }
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.
@@ -135,7 +135,7 @@ if ( ! function_exists( 'ewww_image_optimizer_unsupported_php' ) ) {
135
  * Display a notice that the PHP version is too old.
136
  */
137
  function ewww_image_optimizer_unsupported_php() {
138
- echo "<div id='ewww-image-optimizer-warning-php' class='error'><p><strong>" . esc_html__( 'EWWW Image Optimizer requires PHP 5.4 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' ) . '</strong></p></div>';
139
  }
140
 
141
  /**
14
  Description: Reduce file sizes for images within WordPress including NextGEN Gallery and GRAND FlAGallery. Uses jpegtran, optipng/pngout, and gifsicle.
15
  Author: Shane Bishop
16
  Text Domain: ewww-image-optimizer
17
+ Version: 4.4.0
18
  Author URI: https://ewww.io/
19
  License: GPLv3
20
  */
37
  }
38
 
39
  // Check the PHP version.
40
+ if ( ! defined( 'PHP_VERSION_ID' ) || PHP_VERSION_ID < 50500 ) {
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.
135
  * Display a notice that the PHP version is too old.
136
  */
137
  function ewww_image_optimizer_unsupported_php() {
138
+ echo '<div id="ewww-image-optimizer-warning-php" class="error"><p><a href="https://docs.ewww.io/article/55-upgrading-php" target="_blank" data-beacon-article="5ab2baa6042863478ea7c2ae">' . esc_html__( 'EWWW Image Optimizer requires 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>';
139
  }
140
 
141
  /**
includes/load_webp.js CHANGED
@@ -1,477 +1,484 @@
 
 
 
 
1
  /*
2
  * arrive.js
3
- * v2.3.1
4
  * https://github.com/uzairfarooq/arrive
5
- * MIT licensed - https://github.com/uzairfarooq/arrive/blob/master/LICENSE
6
  *
7
- * Copyright (c) 2014-2016 Uzair Farooq
8
  */
9
-
10
  var Arrive = (function(window, $, undefined) {
11
 
12
- "use strict";
13
-
14
- if(!window.MutationObserver || typeof HTMLElement === 'undefined'){
15
- return; //for unsupported browsers
16
- }
17
-
18
- var arriveUniqueId = 0;
19
-
20
- var utils = (function() {
21
- var matches = HTMLElement.prototype.matches || HTMLElement.prototype.webkitMatchesSelector || HTMLElement.prototype.mozMatchesSelector
22
- || HTMLElement.prototype.msMatchesSelector;
23
-
24
- return {
25
- matchesSelector: function(elem, selector) {
26
- return elem instanceof HTMLElement && matches.call(elem, selector);
27
- },
28
- // to enable function overloading - By John Resig (MIT Licensed)
29
- addMethod: function (object, name, fn) {
30
- var old = object[ name ];
31
- object[ name ] = function(){
32
- if ( fn.length == arguments.length )
33
- return fn.apply( this, arguments );
34
- else if ( typeof old == 'function' )
35
- return old.apply( this, arguments );
36
- };
37
- },
38
- callCallbacks: function(callbacksToBeCalled) {
39
- for (var i = 0, cb; cb = callbacksToBeCalled[i]; i++) {
40
- cb.callback.call(cb.elem);
41
- }
42
- },
43
- // traverse through all descendants of a node to check if event should be fired for any descendant
44
- checkChildNodesRecursively: function(nodes, registrationData, matchFunc, callbacksToBeCalled) {
45
- // check each new node if it matches the selector
46
- for (var i=0, node; node = nodes[i]; i++) {
47
- if (matchFunc(node, registrationData, callbacksToBeCalled)) {
48
- callbacksToBeCalled.push({ callback: registrationData.callback, elem: node });
49
- }
50
-
51
- if (node.childNodes.length > 0) {
52
- utils.checkChildNodesRecursively(node.childNodes, registrationData, matchFunc, callbacksToBeCalled);
53
- }
54
- }
55
- },
56
- mergeArrays: function(firstArr, secondArr){
57
- // Overwrites default options with user-defined options.
58
- var options = {},
59
- attrName;
60
- for (attrName in firstArr) {
61
- options[attrName] = firstArr[attrName];
62
- }
63
- for (attrName in secondArr) {
64
- options[attrName] = secondArr[attrName];
65
- }
66
- return options;
67
- },
68
- toElementsArray: function (elements) {
69
- // check if object is an array (or array like object)
70
- // Note: window object has .length property but it's not array of elements so don't consider it an array
71
- if (typeof elements !== "undefined" && (typeof elements.length !== "number" || elements === window)) {
72
- elements = [elements];
73
- }
74
- return elements;
75
- }
76
- };
77
- })();
78
-
79
-
80
- // Class to maintain state of all registered events of a single type
81
- var EventsBucket = (function() {
82
- var EventsBucket = function() {
83
- // holds all the events
84
-
85
- this._eventsBucket = [];
86
- // function to be called while adding an event, the function should do the event initialization/registration
87
- this._beforeAdding = null;
88
- // function to be called while removing an event, the function should do the event destruction
89
- this._beforeRemoving = null;
90
- };
91
-
92
- EventsBucket.prototype.addEvent = function(target, selector, options, callback) {
93
- var newEvent = {
94
- target: target,
95
- selector: selector,
96
- options: options,
97
- callback: callback,
98
- firedElems: []
99
- };
100
-
101
- if (this._beforeAdding) {
102
- this._beforeAdding(newEvent);
103
- }
104
-
105
- this._eventsBucket.push(newEvent);
106
- return newEvent;
107
- };
108
-
109
- EventsBucket.prototype.removeEvent = function(compareFunction) {
110
- for (var i=this._eventsBucket.length - 1, registeredEvent; registeredEvent = this._eventsBucket[i]; i--) {
111
- if (compareFunction(registeredEvent)) {
112
- if (this._beforeRemoving) {
113
- this._beforeRemoving(registeredEvent);
114
- }
115
- this._eventsBucket.splice(i, 1);
116
- }
117
- }
118
- };
119
-
120
- EventsBucket.prototype.beforeAdding = function(beforeAdding) {
121
- this._beforeAdding = beforeAdding;
122
- };
123
-
124
- EventsBucket.prototype.beforeRemoving = function(beforeRemoving) {
125
- this._beforeRemoving = beforeRemoving;
126
- };
127
-
128
- return EventsBucket;
129
- })();
130
-
131
-
132
- /**
133
- * @constructor
134
- * General class for binding/unbinding arrive and leave events
135
- */
136
- var MutationEvents = function(getObserverConfig, onMutation) {
137
- var eventsBucket = new EventsBucket(),
138
- me = this;
139
-
140
- var defaultOptions = {
141
- fireOnAttributesModification: false
142
- };
143
-
144
- // actual event registration before adding it to bucket
145
- eventsBucket.beforeAdding(function(registrationData) {
146
- var
147
- target = registrationData.target,
148
- selector = registrationData.selector,
149
- callback = registrationData.callback,
150
- observer;
151
-
152
- // mutation observer does not work on window or document
153
- if (target === window.document || target === window)
154
- target = document.getElementsByTagName("html")[0];
155
-
156
- // Create an observer instance
157
- observer = new MutationObserver(function(e) {
158
- onMutation.call(this, e, registrationData);
159
- });
160
-
161
- var config = getObserverConfig(registrationData.options);
162
-
163
- observer.observe(target, config);
164
-
165
- registrationData.observer = observer;
166
- registrationData.me = me;
167
- });
168
-
169
- // cleanup/unregister before removing an event
170
- eventsBucket.beforeRemoving(function (eventData) {
171
- eventData.observer.disconnect();
172
- });
173
-
174
- this.bindEvent = function(selector, options, callback) {
175
- options = utils.mergeArrays(defaultOptions, options);
176
-
177
- var elements = utils.toElementsArray(this);
178
-
179
- for (var i = 0; i < elements.length; i++) {
180
- eventsBucket.addEvent(elements[i], selector, options, callback);
181
- }
182
- };
183
-
184
- this.unbindEvent = function() {
185
- var elements = utils.toElementsArray(this);
186
- eventsBucket.removeEvent(function(eventObj) {
187
- for (var i = 0; i < elements.length; i++) {
188
- if (this === undefined || eventObj.target === elements[i]) {
189
- return true;
190
- }
191
  }
192
- return false;
193
- });
194
- };
195
-
196
- this.unbindEventWithSelectorOrCallback = function(selector) {
197
- var elements = utils.toElementsArray(this),
198
- callback = selector,
199
- compareFunction;
200
-
201
- if (typeof selector === "function") {
202
- compareFunction = function(eventObj) {
203
- for (var i = 0; i < elements.length; i++) {
204
- if ((this === undefined || eventObj.target === elements[i]) && eventObj.callback === callback) {
205
- return true;
206
- }
207
- }
208
- return false;
209
- };
210
- }
211
- else {
212
- compareFunction = function(eventObj) {
213
- for (var i = 0; i < elements.length; i++) {
214
- if ((this === undefined || eventObj.target === elements[i]) && eventObj.selector === selector) {
215
- return true;
216
- }
217
- }
218
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
  };
220
- }
221
- eventsBucket.removeEvent(compareFunction);
222
- };
223
-
224
- this.unbindEventWithSelectorAndCallback = function(selector, callback) {
225
- var elements = utils.toElementsArray(this);
226
- eventsBucket.removeEvent(function(eventObj) {
227
- for (var i = 0; i < elements.length; i++) {
228
- if ((this === undefined || eventObj.target === elements[i]) && eventObj.selector === selector && eventObj.callback === callback) {
229
- return true;
230
- }
231
- }
232
- return false;
233
- });
234
- };
235
-
236
- return this;
237
- };
238
-
239
-
240
- /**
241
- * @constructor
242
- * Processes 'arrive' events
243
- */
244
- var ArriveEvents = function() {
245
- var mutationEvents,
246
- me = this;
247
-
248
- // Default options for 'arrive' event
249
- var arriveDefaultOptions = {
250
- fireOnAttributesModification: false,
251
- onceOnly: false,
252
- existing: false
253
- };
254
-
255
- function getArriveObserverConfig(options) {
256
- var config = {
257
- attributes: false,
258
- childList: true,
259
- subtree: true
260
- };
261
-
262
- if (options.fireOnAttributesModification) {
263
- config.attributes = true;
264
- }
265
-
266
- return config;
267
- }
268
-
269
- function onArriveMutation(mutations, registrationData) {
270
- mutations.forEach(function( mutation ) {
271
- var newNodes = mutation.addedNodes,
272
- targetNode = mutation.target,
273
- callbacksToBeCalled = [];
274
-
275
- // If new nodes are added
276
- if( newNodes !== null && newNodes.length > 0 ) {
277
- utils.checkChildNodesRecursively(newNodes, registrationData, nodeMatchFunc, callbacksToBeCalled);
278
- }
279
- else if (mutation.type === "attributes") {
280
- if (nodeMatchFunc(targetNode, registrationData, callbacksToBeCalled)) {
281
- callbacksToBeCalled.push({ callback: registrationData.callback, elem: node });
282
- }
283
- }
284
 
285
- utils.callCallbacks(callbacksToBeCalled);
286
- });
287
- }
288
 
289
- function nodeMatchFunc(node, registrationData, callbacksToBeCalled) {
290
- // check a single node to see if it matches the selector
291
- if (utils.matchesSelector(node, registrationData.selector)) {
292
- if(node._id === undefined) {
293
- node._id = arriveUniqueId++;
294
- }
295
- // make sure the arrive event is not already fired for the element
296
- if (registrationData.firedElems.indexOf(node._id) == -1) {
297
-
298
- if (registrationData.options.onceOnly) {
299
- if (registrationData.firedElems.length === 0) {
300
- // On first callback, unbind event.
301
- registrationData.me.unbindEventWithSelectorAndCallback.call(
302
- registrationData.target, registrationData.selector, registrationData.callback);
303
- } else {
304
- // Ignore multiple mutations which may have been queued before the event was unbound.
305
- return;
306
- }
307
- }
308
-
309
- registrationData.firedElems.push(node._id);
310
- callbacksToBeCalled.push({ callback: registrationData.callback, elem: node });
311
- }
312
- }
313
- }
314
 
315
- arriveEvents = new MutationEvents(getArriveObserverConfig, onArriveMutation);
 
316
 
317
- var mutationBindEvent = arriveEvents.bindEvent;
 
 
 
 
 
318
 
319
- // override bindEvent function
320
- arriveEvents.bindEvent = function(selector, options, callback) {
 
 
 
 
 
 
 
321
 
322
- if (typeof callback === "undefined") {
323
- callback = options;
324
- options = arriveDefaultOptions;
325
- } else {
326
- options = utils.mergeArrays(arriveDefaultOptions, options);
327
- }
328
 
329
- var elements = utils.toElementsArray(this);
 
 
 
 
 
 
 
 
330
 
331
- if (options.existing) {
332
- var existing = [];
 
333
 
334
- for (var i = 0; i < elements.length; i++) {
335
- var nodes = elements[i].querySelectorAll(selector);
336
- for (var j = 0; j < nodes.length; j++) {
337
- existing.push({ callback: callback, elem: nodes[j] });
338
- }
339
- }
340
 
341
- // no need to bind event if the callback has to be fired only once and we have already found the element
342
- if (options.onceOnly && existing.length) {
343
- return callback.call(existing[0].elem);
344
- }
345
 
346
- setTimeout(utils.callCallbacks, 1, existing);
347
- }
348
 
349
- mutationBindEvent.call(this, selector, options, callback);
350
- };
351
 
352
- return arriveEvents;
353
- };
 
 
 
 
354
 
 
355
 
356
- /**
357
- * @constructor
358
- * Processes 'leave' events
359
- */
360
- var LeaveEvents = function() {
361
- var mutationEvents,
362
- me = this;
363
 
364
- // Default options for 'leave' event
365
- var leaveDefaultOptions = {};
 
 
 
 
366
 
367
- function getLeaveObserverConfig(options) {
368
- var config = {
369
- childList: true,
370
- subtree: true
371
- };
372
 
373
- return config;
374
- }
375
 
376
- function onLeaveMutation(mutations, registrationData) {
377
- mutations.forEach(function( mutation ) {
378
- var removedNodes = mutation.removedNodes,
379
- targetNode = mutation.target,
380
- callbacksToBeCalled = [];
381
 
382
- if( removedNodes !== null && removedNodes.length > 0 ) {
383
- utils.checkChildNodesRecursively(removedNodes, registrationData, nodeMatchFunc, callbacksToBeCalled);
384
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
385
 
386
- utils.callCallbacks(callbacksToBeCalled);
387
- });
388
- }
 
 
 
 
 
 
 
 
 
 
 
 
389
 
390
- function nodeMatchFunc(node, registrationData) {
391
- return utils.matchesSelector(node, registrationData.selector);
392
- }
393
 
394
- leaveEvents = new MutationEvents(getLeaveObserverConfig, onLeaveMutation);
395
 
396
- var mutationBindEvent = leaveEvents.bindEvent;
397
 
398
- // override bindEvent function
399
- leaveEvents.bindEvent = function(selector, options, callback) {
400
 
401
- if (typeof callback === "undefined") {
402
- callback = options;
403
- options = leaveDefaultOptions;
404
- } else {
405
- options = utils.mergeArrays(leaveDefaultOptions, options);
406
- }
407
 
408
- mutationBindEvent.call(this, selector, options, callback);
409
- };
410
 
411
- return leaveEvents;
412
- };
413
 
414
 
415
- var arriveEvents = new ArriveEvents(),
416
- leaveEvents = new LeaveEvents();
417
 
418
- function exposeUnbindApi(eventObj, exposeTo, funcName) {
419
- // expose unbind function with function overriding
420
- utils.addMethod(exposeTo, funcName, eventObj.unbindEvent);
421
- utils.addMethod(exposeTo, funcName, eventObj.unbindEventWithSelectorOrCallback);
422
- utils.addMethod(exposeTo, funcName, eventObj.unbindEventWithSelectorAndCallback);
423
- }
424
 
425
- /*** expose APIs ***/
426
- function exposeApi(exposeTo) {
427
- exposeTo.arrive = arriveEvents.bindEvent;
428
- exposeUnbindApi(arriveEvents, exposeTo, "unbindArrive");
429
 
430
- exposeTo.leave = leaveEvents.bindEvent;
431
- exposeUnbindApi(leaveEvents, exposeTo, "unbindLeave");
432
- }
433
 
434
- if ($) {
435
- exposeApi($.fn);
436
- }
437
- exposeApi(HTMLElement.prototype);
438
- exposeApi(NodeList.prototype);
439
- exposeApi(HTMLCollection.prototype);
440
- exposeApi(HTMLDocument.prototype);
441
- exposeApi(Window.prototype);
442
 
443
- var Arrive = {};
444
- // expose functions to unbind all arrive/leave events
445
- exposeUnbindApi(arriveEvents, Arrive, "unbindAllArrive");
446
- exposeUnbindApi(leaveEvents, Arrive, "unbindAllLeave");
447
 
448
- return Arrive;
449
 
450
  })(window, typeof jQuery === 'undefined' ? null : jQuery, undefined);
451
 
452
- // webp detection borrowed from https://developers.google.com/speed/webp/faq#how_can_i_detect_browser_support_using_javascript
453
  function check_webp_feature(feature, callback) {
454
- var kTestImages = {
455
- alpha: "UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",
456
- animation: "UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"
457
- };
458
- var webp_supported = false;
459
- var img = new Image();
460
- img.onload = function () {
461
- var result = (img.width > 0) && (img.height > 0);
462
- webp_supported = true;
463
- callback(result);
464
- };
465
- img.onerror = function () {
466
- webp_supported = false;
467
- callback(false);
468
- };
469
- img.src = "data:image/webp;base64," + kTestImages[feature];
470
  }
471
  function ewww_load_images(ewww_webp_supported) {
472
- jQuery(document).arrive('.ewww_webp', function() {
473
- ewww_load_images(ewww_webp_supported);
474
- });
475
  (function($) {
476
  var attr_prefix = 'data-';
477
  function ewww_copy_attrs(ewww_nscript, ewww_img) {
@@ -695,22 +702,33 @@ function ewww_load_images(ewww_webp_supported) {
695
  });
696
  }
697
  }
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($) {
@@ -720,7 +738,6 @@ function ewww_ngg_plus_parse_galleries(ewww_webp_supported) {
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($) {
1
+ /*globals jQuery,Window,HTMLElement,HTMLDocument,HTMLCollection,NodeList,MutationObserver */
2
+ /*exported Arrive*/
3
+ /*jshint latedef:false */
4
+
5
  /*
6
  * arrive.js
7
+ * v2.4.1
8
  * https://github.com/uzairfarooq/arrive
9
+ * MIT licensed
10
  *
11
+ * Copyright (c) 2014-2017 Uzair Farooq
12
  */
 
13
  var Arrive = (function(window, $, undefined) {
14
 
15
+ "use strict";
16
+
17
+ if(!window.MutationObserver || typeof HTMLElement === 'undefined'){
18
+ return; //for unsupported browsers
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  }
20
+
21
+ var arriveUniqueId = 0;
22
+
23
+ var utils = (function() {
24
+ var matches = HTMLElement.prototype.matches || HTMLElement.prototype.webkitMatchesSelector || HTMLElement.prototype.mozMatchesSelector
25
+ || HTMLElement.prototype.msMatchesSelector;
26
+
27
+ return {
28
+ matchesSelector: function(elem, selector) {
29
+ return elem instanceof HTMLElement && matches.call(elem, selector);
30
+ },
31
+ // to enable function overloading - By John Resig (MIT Licensed)
32
+ addMethod: function (object, name, fn) {
33
+ var old = object[ name ];
34
+ object[ name ] = function(){
35
+ if ( fn.length == arguments.length ) {
36
+ return fn.apply( this, arguments );
37
+ }
38
+ else if ( typeof old == 'function' ) {
39
+ return old.apply( this, arguments );
40
+ }
41
+ };
42
+ },
43
+ callCallbacks: function(callbacksToBeCalled, registrationData) {
44
+ if (registrationData && registrationData.options.onceOnly && registrationData.firedElems.length == 1) {
45
+ // as onlyOnce param is true, make sure we fire the event for only one item
46
+ callbacksToBeCalled = [callbacksToBeCalled[0]];
47
+ }
48
+
49
+ for (var i = 0, cb; (cb = callbacksToBeCalled[i]); i++) {
50
+ if (cb && cb.callback) {
51
+ cb.callback.call(cb.elem, cb.elem);
52
+ }
53
+ }
54
+
55
+ if (registrationData && registrationData.options.onceOnly && registrationData.firedElems.length == 1) {
56
+ // unbind event after first callback as onceOnly is true.
57
+ registrationData.me.unbindEventWithSelectorAndCallback.call(
58
+ registrationData.target, registrationData.selector, registrationData.callback
59
+ );
60
+ }
61
+ },
62
+ // traverse through all descendants of a node to check if event should be fired for any descendant
63
+ checkChildNodesRecursively: function(nodes, registrationData, matchFunc, callbacksToBeCalled) {
64
+ // check each new node if it matches the selector
65
+ for (var i=0, node; (node = nodes[i]); i++) {
66
+ if (matchFunc(node, registrationData, callbacksToBeCalled)) {
67
+ callbacksToBeCalled.push({ callback: registrationData.callback, elem: node });
68
+ }
69
+
70
+ if (node.childNodes.length > 0) {
71
+ utils.checkChildNodesRecursively(node.childNodes, registrationData, matchFunc, callbacksToBeCalled);
72
+ }
73
+ }
74
+ },
75
+ mergeArrays: function(firstArr, secondArr){
76
+ // Overwrites default options with user-defined options.
77
+ var options = {},
78
+ attrName;
79
+ for (attrName in firstArr) {
80
+ if (firstArr.hasOwnProperty(attrName)) {
81
+ options[attrName] = firstArr[attrName];
82
+ }
83
+ }
84
+ for (attrName in secondArr) {
85
+ if (secondArr.hasOwnProperty(attrName)) {
86
+ options[attrName] = secondArr[attrName];
87
+ }
88
+ }
89
+ return options;
90
+ },
91
+ toElementsArray: function (elements) {
92
+ // check if object is an array (or array like object)
93
+ // Note: window object has .length property but it's not array of elements so don't consider it an array
94
+ if (typeof elements !== "undefined" && (typeof elements.length !== "number" || elements === window)) {
95
+ elements = [elements];
96
+ }
97
+ return elements;
98
+ }
99
+ };
100
+ })();
101
+
102
+
103
+ // Class to maintain state of all registered events of a single type
104
+ var EventsBucket = (function() {
105
+ var EventsBucket = function() {
106
+ // holds all the events
107
+
108
+ this._eventsBucket = [];
109
+ // function to be called while adding an event, the function should do the event initialization/registration
110
+ this._beforeAdding = null;
111
+ // function to be called while removing an event, the function should do the event destruction
112
+ this._beforeRemoving = null;
113
+ };
114
+
115
+ EventsBucket.prototype.addEvent = function(target, selector, options, callback) {
116
+ var newEvent = {
117
+ target: target,
118
+ selector: selector,
119
+ options: options,
120
+ callback: callback,
121
+ firedElems: []
122
+ };
123
+
124
+ if (this._beforeAdding) {
125
+ this._beforeAdding(newEvent);
126
+ }
127
+
128
+ this._eventsBucket.push(newEvent);
129
+ return newEvent;
130
+ };
131
+
132
+ EventsBucket.prototype.removeEvent = function(compareFunction) {
133
+ for (var i=this._eventsBucket.length - 1, registeredEvent; (registeredEvent = this._eventsBucket[i]); i--) {
134
+ if (compareFunction(registeredEvent)) {
135
+ if (this._beforeRemoving) {
136
+ this._beforeRemoving(registeredEvent);
137
+ }
138
+
139
+ // mark callback as null so that even if an event mutation was already triggered it does not call callback
140
+ var removedEvents = this._eventsBucket.splice(i, 1);
141
+ if (removedEvents && removedEvents.length) {
142
+ removedEvents[0].callback = null;
143
+ }
144
+ }
145
+ }
146
+ };
147
+
148
+ EventsBucket.prototype.beforeAdding = function(beforeAdding) {
149
+ this._beforeAdding = beforeAdding;
150
+ };
151
+
152
+ EventsBucket.prototype.beforeRemoving = function(beforeRemoving) {
153
+ this._beforeRemoving = beforeRemoving;
154
+ };
155
+
156
+ return EventsBucket;
157
+ })();
158
+
159
+
160
+ /**
161
+ * @constructor
162
+ * General class for binding/unbinding arrive and leave events
163
+ */
164
+ var MutationEvents = function(getObserverConfig, onMutation) {
165
+ var eventsBucket = new EventsBucket(),
166
+ me = this;
167
+
168
+ var defaultOptions = {
169
+ fireOnAttributesModification: false
170
+ };
171
+
172
+ // actual event registration before adding it to bucket
173
+ eventsBucket.beforeAdding(function(registrationData) {
174
+ var
175
+ target = registrationData.target,
176
+ observer;
177
+
178
+ // mutation observer does not work on window or document
179
+ if (target === window.document || target === window) {
180
+ target = document.getElementsByTagName("html")[0];
181
+ }
182
+
183
+ // Create an observer instance
184
+ observer = new MutationObserver(function(e) {
185
+ onMutation.call(this, e, registrationData);
186
+ });
187
+
188
+ var config = getObserverConfig(registrationData.options);
189
+
190
+ observer.observe(target, config);
191
+
192
+ registrationData.observer = observer;
193
+ registrationData.me = me;
194
+ });
195
+
196
+ // cleanup/unregister before removing an event
197
+ eventsBucket.beforeRemoving(function (eventData) {
198
+ eventData.observer.disconnect();
199
+ });
200
+
201
+ this.bindEvent = function(selector, options, callback) {
202
+ options = utils.mergeArrays(defaultOptions, options);
203
+
204
+ var elements = utils.toElementsArray(this);
205
+
206
+ for (var i = 0; i < elements.length; i++) {
207
+ eventsBucket.addEvent(elements[i], selector, options, callback);
208
+ }
209
+ };
210
+
211
+ this.unbindEvent = function() {
212
+ var elements = utils.toElementsArray(this);
213
+ eventsBucket.removeEvent(function(eventObj) {
214
+ for (var i = 0; i < elements.length; i++) {
215
+ if (this === undefined || eventObj.target === elements[i]) {
216
+ return true;
217
+ }
218
+ }
219
+ return false;
220
+ });
221
+ };
222
+
223
+ this.unbindEventWithSelectorOrCallback = function(selector) {
224
+ var elements = utils.toElementsArray(this),
225
+ callback = selector,
226
+ compareFunction;
227
+
228
+ if (typeof selector === "function") {
229
+ compareFunction = function(eventObj) {
230
+ for (var i = 0; i < elements.length; i++) {
231
+ if ((this === undefined || eventObj.target === elements[i]) && eventObj.callback === callback) {
232
+ return true;
233
+ }
234
+ }
235
+ return false;
236
+ };
237
+ }
238
+ else {
239
+ compareFunction = function(eventObj) {
240
+ for (var i = 0; i < elements.length; i++) {
241
+ if ((this === undefined || eventObj.target === elements[i]) && eventObj.selector === selector) {
242
+ return true;
243
+ }
244
+ }
245
+ return false;
246
+ };
247
+ }
248
+ eventsBucket.removeEvent(compareFunction);
249
+ };
250
+
251
+ this.unbindEventWithSelectorAndCallback = function(selector, callback) {
252
+ var elements = utils.toElementsArray(this);
253
+ eventsBucket.removeEvent(function(eventObj) {
254
+ for (var i = 0; i < elements.length; i++) {
255
+ if ((this === undefined || eventObj.target === elements[i]) && eventObj.selector === selector && eventObj.callback === callback) {
256
+ return true;
257
+ }
258
+ }
259
+ return false;
260
+ });
261
+ };
262
+
263
+ return this;
264
  };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
265
 
 
 
 
266
 
267
+ /**
268
+ * @constructor
269
+ * Processes 'arrive' events
270
+ */
271
+ var ArriveEvents = function() {
272
+ // Default options for 'arrive' event
273
+ var arriveDefaultOptions = {
274
+ fireOnAttributesModification: false,
275
+ onceOnly: false,
276
+ existing: false
277
+ };
278
+
279
+ function getArriveObserverConfig(options) {
280
+ var config = {
281
+ attributes: false,
282
+ childList: true,
283
+ subtree: true
284
+ };
285
+
286
+ if (options.fireOnAttributesModification) {
287
+ config.attributes = true;
288
+ }
 
 
 
289
 
290
+ return config;
291
+ }
292
 
293
+ function onArriveMutation(mutations, registrationData) {
294
+ mutations.forEach(function( mutation ) {
295
+ var newNodes = mutation.addedNodes,
296
+ targetNode = mutation.target,
297
+ callbacksToBeCalled = [],
298
+ node;
299
 
300
+ // If new nodes are added
301
+ if( newNodes !== null && newNodes.length > 0 ) {
302
+ utils.checkChildNodesRecursively(newNodes, registrationData, nodeMatchFunc, callbacksToBeCalled);
303
+ }
304
+ else if (mutation.type === "attributes") {
305
+ if (nodeMatchFunc(targetNode, registrationData, callbacksToBeCalled)) {
306
+ callbacksToBeCalled.push({ callback: registrationData.callback, elem: targetNode });
307
+ }
308
+ }
309
 
310
+ utils.callCallbacks(callbacksToBeCalled, registrationData);
311
+ });
312
+ }
 
 
 
313
 
314
+ function nodeMatchFunc(node, registrationData, callbacksToBeCalled) {
315
+ // check a single node to see if it matches the selector
316
+ if (utils.matchesSelector(node, registrationData.selector)) {
317
+ if(node._id === undefined) {
318
+ node._id = arriveUniqueId++;
319
+ }
320
+ // make sure the arrive event is not already fired for the element
321
+ if (registrationData.firedElems.indexOf(node._id) == -1) {
322
+ registrationData.firedElems.push(node._id);
323
 
324
+ return true;
325
+ }
326
+ }
327
 
328
+ return false;
329
+ }
 
 
 
 
330
 
331
+ arriveEvents = new MutationEvents(getArriveObserverConfig, onArriveMutation);
 
 
 
332
 
333
+ var mutationBindEvent = arriveEvents.bindEvent;
 
334
 
335
+ // override bindEvent function
336
+ arriveEvents.bindEvent = function(selector, options, callback) {
337
 
338
+ if (typeof callback === "undefined") {
339
+ callback = options;
340
+ options = arriveDefaultOptions;
341
+ } else {
342
+ options = utils.mergeArrays(arriveDefaultOptions, options);
343
+ }
344
 
345
+ var elements = utils.toElementsArray(this);
346
 
347
+ if (options.existing) {
348
+ var existing = [];
 
 
 
 
 
349
 
350
+ for (var i = 0; i < elements.length; i++) {
351
+ var nodes = elements[i].querySelectorAll(selector);
352
+ for (var j = 0; j < nodes.length; j++) {
353
+ existing.push({ callback: callback, elem: nodes[j] });
354
+ }
355
+ }
356
 
357
+ // no need to bind event if the callback has to be fired only once and we have already found the element
358
+ if (options.onceOnly && existing.length) {
359
+ return callback.call(existing[0].elem, existing[0].elem);
360
+ }
 
361
 
362
+ setTimeout(utils.callCallbacks, 1, existing);
363
+ }
364
 
365
+ mutationBindEvent.call(this, selector, options, callback);
366
+ };
 
 
 
367
 
368
+ return arriveEvents;
369
+ };
370
+
371
+
372
+ /**
373
+ * @constructor
374
+ * Processes 'leave' events
375
+ */
376
+ var LeaveEvents = function() {
377
+ // Default options for 'leave' event
378
+ var leaveDefaultOptions = {};
379
+
380
+ function getLeaveObserverConfig() {
381
+ var config = {
382
+ childList: true,
383
+ subtree: true
384
+ };
385
 
386
+ return config;
387
+ }
388
+
389
+ function onLeaveMutation(mutations, registrationData) {
390
+ mutations.forEach(function( mutation ) {
391
+ var removedNodes = mutation.removedNodes,
392
+ callbacksToBeCalled = [];
393
+
394
+ if( removedNodes !== null && removedNodes.length > 0 ) {
395
+ utils.checkChildNodesRecursively(removedNodes, registrationData, nodeMatchFunc, callbacksToBeCalled);
396
+ }
397
+
398
+ utils.callCallbacks(callbacksToBeCalled, registrationData);
399
+ });
400
+ }
401
 
402
+ function nodeMatchFunc(node, registrationData) {
403
+ return utils.matchesSelector(node, registrationData.selector);
404
+ }
405
 
406
+ leaveEvents = new MutationEvents(getLeaveObserverConfig, onLeaveMutation);
407
 
408
+ var mutationBindEvent = leaveEvents.bindEvent;
409
 
410
+ // override bindEvent function
411
+ leaveEvents.bindEvent = function(selector, options, callback) {
412
 
413
+ if (typeof callback === "undefined") {
414
+ callback = options;
415
+ options = leaveDefaultOptions;
416
+ } else {
417
+ options = utils.mergeArrays(leaveDefaultOptions, options);
418
+ }
419
 
420
+ mutationBindEvent.call(this, selector, options, callback);
421
+ };
422
 
423
+ return leaveEvents;
424
+ };
425
 
426
 
427
+ var arriveEvents = new ArriveEvents(),
428
+ leaveEvents = new LeaveEvents();
429
 
430
+ function exposeUnbindApi(eventObj, exposeTo, funcName) {
431
+ // expose unbind function with function overriding
432
+ utils.addMethod(exposeTo, funcName, eventObj.unbindEvent);
433
+ utils.addMethod(exposeTo, funcName, eventObj.unbindEventWithSelectorOrCallback);
434
+ utils.addMethod(exposeTo, funcName, eventObj.unbindEventWithSelectorAndCallback);
435
+ }
436
 
437
+ /*** expose APIs ***/
438
+ function exposeApi(exposeTo) {
439
+ exposeTo.arrive = arriveEvents.bindEvent;
440
+ exposeUnbindApi(arriveEvents, exposeTo, "unbindArrive");
441
 
442
+ exposeTo.leave = leaveEvents.bindEvent;
443
+ exposeUnbindApi(leaveEvents, exposeTo, "unbindLeave");
444
+ }
445
 
446
+ if ($) {
447
+ exposeApi($.fn);
448
+ }
449
+ exposeApi(HTMLElement.prototype);
450
+ exposeApi(NodeList.prototype);
451
+ exposeApi(HTMLCollection.prototype);
452
+ exposeApi(HTMLDocument.prototype);
453
+ exposeApi(Window.prototype);
454
 
455
+ var Arrive = {};
456
+ // expose functions to unbind all arrive/leave events
457
+ exposeUnbindApi(arriveEvents, Arrive, "unbindAllArrive");
458
+ exposeUnbindApi(leaveEvents, Arrive, "unbindAllLeave");
459
 
460
+ return Arrive;
461
 
462
  })(window, typeof jQuery === 'undefined' ? null : jQuery, undefined);
463
 
464
+ // webp detection adapted from https://developers.google.com/speed/webp/faq#how_can_i_detect_browser_support_using_javascript
465
  function check_webp_feature(feature, callback) {
466
+ var kTestImages = {
467
+ alpha: "UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",
468
+ animation: "UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"
469
+ };
470
+ var img = new Image();
471
+ img.onload = function () {
472
+ ewww_webp_supported = (img.width > 0) && (img.height > 0);
473
+ callback(ewww_webp_supported);
474
+ };
475
+ img.onerror = function () {
476
+ ewww_webp_supported = false;
477
+ callback(false);
478
+ };
479
+ img.src = "data:image/webp;base64," + kTestImages[feature];
 
 
480
  }
481
  function ewww_load_images(ewww_webp_supported) {
 
 
 
482
  (function($) {
483
  var attr_prefix = 'data-';
484
  function ewww_copy_attrs(ewww_nscript, ewww_img) {
702
  });
703
  }
704
  }
705
+ var ewww_webp_supported = false;
706
+ var ewww_jquery_waiting_timer = 0;
707
+ ewww_jquery_waiting = setInterval(function () {
708
+ if (window.jQuery) {
709
+ check_webp_feature('alpha', ewww_load_images);
710
+ check_webp_feature('alpha', ewww_ngg_plus_load_galleries);
711
+ document.arrive('.ewww_webp', function() {
712
+ ewww_load_images(ewww_webp_supported);
713
+ });
714
+ var ewww_ngg_galleries_timer = 0;
715
+ var ewww_ngg_galleries = setInterval(function() {
716
+ if ( typeof galleries !== 'undefined' ) {
717
+ check_webp_feature('alpha', ewww_ngg_plus_parse_galleries);
718
+ clearInterval(ewww_ngg_galleries);
719
+ }
720
+ ewww_ngg_galleries_timer += 25;
721
+ if (ewww_ngg_galleries_timer > 1000) {
722
+ clearInterval(ewww_ngg_galleries);
723
+ }
724
+ }, 25);
725
+ clearInterval(ewww_jquery_waiting);
726
  }
727
+ ewww_jquery_waiting_timer +=100;
728
+ if (ewww_jquery_waiting_timer > 10000) {
729
+ clearInterval(ewww_jquery_waiting);
730
  }
731
+ }, 100);
732
  function ewww_ngg_plus_parse_galleries(ewww_webp_supported) {
733
  if (ewww_webp_supported) {
734
  (function($) {
738
  })(jQuery);
739
  }
740
  }
 
741
  function ewww_ngg_plus_load_galleries(ewww_webp_supported) {
742
  if (ewww_webp_supported) {
743
  (function($) {
includes/load_webp.min.js CHANGED
@@ -1 +1 @@
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);
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,e){e&&e.options.onceOnly&&1==e.firedElems.length&&(t=[t[0]]);for(var a,i=0;a=t[i];i++)a&&a.callback&&a.callback.call(a.elem,a.elem);e&&e.options.onceOnly&&1==e.firedElems.length&&e.me.unbindEventWithSelectorAndCallback.call(e.target,e.selector,e.callback)},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)t.hasOwnProperty(a)&&(i[a]=t[a]);for(a in e)e.hasOwnProperty(a)&&(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--)if(t(e)){this._beforeRemoving&&this._beforeRemoving(e);var i=this._eventsBucket.splice(a,1);i&&i.length&&(i[0].callback=null)}},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;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){return!(!u.matchesSelector(t,e.selector)||(t._id===c&&(t._id=i++),-1!=e.firedElems.indexOf(t._id))||(e.firedElems.push(t._id),0))}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.push({callback:r.callback,elem:a}),u.callCallbacks(i,r)})})).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,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(){return{childList:!0,subtree:!0}},function(t,i){t.forEach(function(t){var e=t.removedNodes,a=[];null!==e&&0<e.length&&u.checkChildNodesRecursively(e,i,r,a),u.callCallbacks(a,i)})})).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(){ewww_webp_supported=0<a.width&&0<a.height,e(ewww_webp_supported)},a.onerror=function(){e(ewww_webp_supported=!1)},a.src="data:image/webp;base64,"+{alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"}[t]}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()}))}var ewww_webp_supported=!1,ewww_jquery_waiting_timer=0;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}ewww_jquery_waiting=setInterval(function(){if(window.jQuery){check_webp_feature("alpha",ewww_load_images),check_webp_feature("alpha",ewww_ngg_plus_load_galleries),document.arrive(".ewww_webp",function(){ewww_load_images(ewww_webp_supported)});var t=0,e=setInterval(function(){"undefined"!=typeof galleries&&(check_webp_feature("alpha",ewww_ngg_plus_parse_galleries),clearInterval(e)),1e3<(t+=25)&&clearInterval(e)},25);clearInterval(ewww_jquery_waiting)}1e4<(ewww_jquery_waiting_timer+=100)&&clearInterval(ewww_jquery_waiting)},100);
license.txt CHANGED
@@ -672,3 +672,108 @@ may consider it more useful to permit linking proprietary applications with
672
  the library. If this is what you want to do, use the GNU Lesser General
673
  Public License instead of this License. But first, please read
674
  <http://www.gnu.org/philosophy/why-not-lgpl.html>.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
672
  the library. If this is what you want to do, use the GNU Lesser General
673
  Public License instead of this License. But first, please read
674
  <http://www.gnu.org/philosophy/why-not-lgpl.html>.
675
+
676
+ Licenses of included software:
677
+
678
+ arrive.js
679
+
680
+ Copyright (c) 2014-2017 Uzair Farooq
681
+
682
+ Permission is hereby granted, free of charge, to any person obtaining a copy
683
+ of this software and associated documentation files (the "Software"), to deal
684
+ in the Software without restriction, including without limitation the rights
685
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
686
+ copies of the Software, and to permit persons to whom the Software is
687
+ furnished to do so, subject to the following conditions:
688
+
689
+ The above copyright notice and this permission notice shall be included in
690
+ all copies or substantial portions of the Software.
691
+
692
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
693
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
694
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
695
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
696
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
697
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
698
+ THE SOFTWARE.
699
+
700
+ optipng
701
+
702
+ Copyright (C) 2001-2017 Cosmin Truta and the Contributing Authors.
703
+ For the purpose of copyright and licensing, the list of Contributing
704
+ Authors is available in the accompanying AUTHORS file.
705
+
706
+ This software is provided 'as-is', without any express or implied
707
+ warranty. In no event will the author(s) be held liable for any damages
708
+ arising from the use of this software.
709
+
710
+ pngquant.c
711
+
712
+ © 1989, 1991 by Jef Poskanzer.
713
+
714
+ Permission to use, copy, modify, and distribute this software and its
715
+ documentation for any purpose and without fee is hereby granted, provided
716
+ that the above copyright notice appear in all copies and that both that
717
+ copyright notice and this permission notice appear in supporting
718
+ documentation. This software is provided "as is" without express or
719
+ implied warranty.
720
+
721
+ pngquant.c and rwpng.c/h
722
+
723
+ © 1997-2002 by Greg Roelofs; based on an idea by Stefan Schneider.
724
+ © 2009-2017 by Kornel Lesiński.
725
+
726
+ All rights reserved.
727
+
728
+ Redistribution and use in source and binary forms, with or without modification,
729
+ are permitted provided that the following conditions are met:
730
+
731
+ 1. Redistributions of source code must retain the above copyright notice,
732
+ this list of conditions and the following disclaimer.
733
+
734
+ 2. Redistributions in binary form must reproduce the above copyright notice,
735
+ this list of conditions and the following disclaimer in the documentation
736
+ and/or other materials provided with the distribution.
737
+
738
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
739
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
740
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
741
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
742
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
743
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
744
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
745
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
746
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
747
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
748
+
749
+ WebP
750
+
751
+ Copyright (c) 2010, Google Inc. All rights reserved.
752
+
753
+ Redistribution and use in source and binary forms, with or without
754
+ modification, are permitted provided that the following conditions are
755
+ met:
756
+
757
+ * Redistributions of source code must retain the above copyright
758
+ notice, this list of conditions and the following disclaimer.
759
+
760
+ * Redistributions in binary form must reproduce the above copyright
761
+ notice, this list of conditions and the following disclaimer in
762
+ the documentation and/or other materials provided with the
763
+ distribution.
764
+
765
+ * Neither the name of Google nor the names of its contributors may
766
+ be used to endorse or promote products derived from this software
767
+ without specific prior written permission.
768
+
769
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
770
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
771
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
772
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
773
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
774
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
775
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
776
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
777
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
778
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
779
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
mwebp.php CHANGED
@@ -94,9 +94,11 @@ function ewww_image_optimizer_webp_script( $hook ) {
94
  wp_enqueue_script( 'ewwwwebpscript', plugins_url( '/includes/webp.js', __FILE__ ), array( 'jquery' ), EWWW_IMAGE_OPTIMIZER_VERSION );
95
  $image_count = count( $images );
96
  // Submit a couple variables to the javascript to work with.
97
- wp_localize_script( 'ewwwwebpscript', 'ewww_vars', array(
98
- 'ewww_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-webp' ),
99
- ) );
 
 
100
  }
101
 
102
  /**
94
  wp_enqueue_script( 'ewwwwebpscript', plugins_url( '/includes/webp.js', __FILE__ ), array( 'jquery' ), EWWW_IMAGE_OPTIMIZER_VERSION );
95
  $image_count = count( $images );
96
  // Submit a couple variables to the javascript to work with.
97
+ wp_localize_script(
98
+ 'ewwwwebpscript',
99
+ 'ewww_vars',
100
+ array( 'ewww_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-webp' ) )
101
+ );
102
  }
103
 
104
  /**
phpcs.ruleset.xml CHANGED
@@ -16,6 +16,11 @@
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" />
16
  <exclude name="Generic.PHP.NoSilencedErrors.Discouraged" />
17
  </rule>
18
 
19
+ <rule ref="WordPress.PHP.NoSilencedErrors">
20
+ <properties>
21
+ <property name="custom_whitelist" type="array" value="ini_get,exif_read_data,ob_end_flush"/>
22
+ </properties>
23
+ </rule>
24
  <rule ref="WordPress.NamingConventions.ValidVariableName">
25
  <properties>
26
  <property name="customPropertiesWhitelist" type="array" value="formatOutput,imgQuality,parentNode,nextSibling,documentElement,imagePath,webimagePath,thumbPath,fileName,Version,Name" />
readme.txt CHANGED
@@ -4,8 +4,8 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i
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.2
9
  License: GPLv3
10
 
11
  Speed up your website and improve your visitors' experience by automatically compressing and resizing images and PDFs. Boost SEO and improve sales.
@@ -174,6 +174,20 @@ http://developer.yahoo.com/performance/rules.html#opt_images
174
  * Feature requests can be submitted via https://ewww.io/contact-us/ and commented on here: https://trello.com/b/Fp81dWof/ewww-image-optimizer
175
  * If you would like to help translate this plugin in your language, get started here: https://translate.wordpress.org/projects/wp-plugins/ewww-image-optimizer/
176
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  = 4.3.2 =
178
  * changed: prevent dynamic JS/CSS urls within wp-admin/ from being rewritten by ExactDN
179
  * fixed: auto-convert PNG to JPG was running on images with transparency
@@ -210,52 +224,6 @@ http://developer.yahoo.com/performance/rules.html#opt_images
210
  * fixed: PNGOUT installer confirmation notice was missing
211
  * deprecated: PHP 5.4 support will be removed in the next major release (version 4.4)
212
 
213
- = 4.2.3 =
214
- * added: skip resizing for images with noresize in the filename
215
- * added: notice about plugins that remove query strings when ExactDN is active
216
- * changed: cache busting for ExactDN uses theme directory modified time with fallback to EWWW IO version
217
- * fixed: exactdn test verification attempts to access WP_Error as an array
218
-
219
- = 4.2.2 =
220
- * added: view pages with ExactDN or the entire plugin disabled via GET paramaters: ewwwio_disable and exactdn_disable
221
- * changed: moved to v2 quota endpoint for API
222
- * changed: S3 uploads no longer deferred until after optimization by default, define EWWW_IMAGE_OPTIMIZER_DEFER_S3 as true to override
223
- * changed: image editor extensions can be disabled separately from media library optimization via EWWW_IMAGE_OPTIMIZER_DISABLE_EDITOR
224
- * changed: use exactdn url instead of standard API url for verification simulation and fallback
225
- * fixed: async test outputs unescaped html on settings page when debugging enabled
226
- * fixed: debugging uses extra memory when dumping output to file
227
- * fixed: json_encode dies silently when passing non-utf8 data, results in AJAX/bulk errors
228
- * fixed: disabled auto-optimization bypassed for resizes when max dimensions are set
229
- * fixed: NextGEN support disabled for version 3
230
- * fixed: progressbar color does not match admin theme for NextGEN/Nextcellent
231
- * fixed: optimization details overlay styling missing for NextGEN with some locales
232
- * fixed: FlAGallery batch optimization from Manage Galleries/Images broken
233
- * fixed: undefined variable notices for resize detection and forced re-optimization
234
- * updated: PEL library for maintaining metadata during JPG auto-rotation
235
-
236
- = 4.2.1 =
237
- * fixed: EXACTDN_LOCAL_DOMAIN does not work with auto-verification
238
- * fixed: uncaught error during upgrade when 'SHOW FULL COLUMNS' fails
239
- * fixed: async simulation gets 403 error
240
-
241
- = 4.2.0 =
242
- * added: disable ExactDN attachment ID queries if they take too long
243
- * added: ExactDN compatibility with a3 Lazy Load
244
- * added: ability to re-test async/background mode if it gets disabled
245
- * changed: better compatibility between Autoptimize and ExactDN
246
- * changed: .webp files removed when restoring original from API
247
- * changed: Force re-optimize checkbox persists up to an hour if bulk optimizer is interrupted
248
- * fixed: CSS, JS, and other resources could be skipped by ExactDN in certain circumstances
249
- * fixed: Jupiter theme captcha incompatible with ExactDN
250
- * fixed: prevent calls to php_uname when it is disabled
251
- * fixed: MacOS X installer for PNGOUT
252
- * fixed: prevent notices due to empty output from exec()
253
- * fixed: ExactDN fails to crop when image_downsize() is called with explicit dimensions
254
- * fixed: ExactDN breaks image resizing with Themify themes
255
- * fixed: multi-site settings throws error during submission when ExactDN is active
256
- * fixed: single-site override option displayed when plugin activated per-site
257
- * removed: PHP 5.3 no longer supported
258
-
259
  = Earlier versions =
260
  Please refer to the separate changelog.txt file.
261
 
@@ -280,83 +248,3 @@ Please refer to the separate changelog.txt file.
280
 
281
  Written by [Shane Bishop](https://ewww.io). Based upon CW Image Optimizer, which was written by [Jacob Allred](http://www.jacoballred.com/) at [Corban Works, LLC](http://www.corbanworks.com/). CW Image Optimizer was based on WP Smush.it. Jpegtran is the work of the Independent JPEG Group. PEL is the work of Martin Geisler, Lars Olesen, and Erik Oskam. ExactDN class based upon the Photon module from Jetpack.
282
 
283
- = optipng =
284
-
285
- Copyright (C) 2001-2017 Cosmin Truta and the Contributing Authors.
286
- For the purpose of copyright and licensing, the list of Contributing
287
- Authors is available in the accompanying AUTHORS file.
288
-
289
- This software is provided 'as-is', without any express or implied
290
- warranty. In no event will the author(s) be held liable for any damages
291
- arising from the use of this software.
292
-
293
- = pngquant.c =
294
-
295
- © 1989, 1991 by Jef Poskanzer.
296
-
297
- Permission to use, copy, modify, and distribute this software and its
298
- documentation for any purpose and without fee is hereby granted, provided
299
- that the above copyright notice appear in all copies and that both that
300
- copyright notice and this permission notice appear in supporting
301
- documentation. This software is provided "as is" without express or
302
- implied warranty.
303
-
304
- = pngquant.c and rwpng.c/h =
305
-
306
- © 1997-2002 by Greg Roelofs; based on an idea by Stefan Schneider.
307
- © 2009-2017 by Kornel Lesiński.
308
-
309
- All rights reserved.
310
-
311
- Redistribution and use in source and binary forms, with or without modification,
312
- are permitted provided that the following conditions are met:
313
-
314
- 1. Redistributions of source code must retain the above copyright notice,
315
- this list of conditions and the following disclaimer.
316
-
317
- 2. Redistributions in binary form must reproduce the above copyright notice,
318
- this list of conditions and the following disclaimer in the documentation
319
- and/or other materials provided with the distribution.
320
-
321
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
322
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
323
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
324
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
325
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
326
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
327
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
328
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
329
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
330
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
331
-
332
- = WebP =
333
-
334
- Copyright (c) 2010, Google Inc. All rights reserved.
335
-
336
- Redistribution and use in source and binary forms, with or without
337
- modification, are permitted provided that the following conditions are
338
- met:
339
-
340
- * Redistributions of source code must retain the above copyright
341
- notice, this list of conditions and the following disclaimer.
342
-
343
- * Redistributions in binary form must reproduce the above copyright
344
- notice, this list of conditions and the following disclaimer in
345
- the documentation and/or other materials provided with the
346
- distribution.
347
-
348
- * Neither the name of Google nor the names of its contributors may
349
- be used to endorse or promote products derived from this software
350
- without specific prior written permission.
351
-
352
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
353
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
354
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
355
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
356
- HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
357
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
358
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
359
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
360
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
361
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
362
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4
  Tags: image, compress, resize, optimize, optimization, lossless, lossy, seo, webp, wp-cli, scale, tinypng, tinyjpg
5
  Requires at least: 4.6
6
  Tested up to: 4.9
7
+ Requires PHP: 5.5
8
+ Stable tag: 4.4.0
9
  License: GPLv3
10
 
11
  Speed up your website and improve your visitors' experience by automatically compressing and resizing images and PDFs. Boost SEO and improve sales.
174
  * Feature requests can be submitted via https://ewww.io/contact-us/ and commented on here: https://trello.com/b/Fp81dWof/ewww-image-optimizer
175
  * If you would like to help translate this plugin in your language, get started here: https://translate.wordpress.org/projects/wp-plugins/ewww-image-optimizer/
176
 
177
+ = 4.4.0 =
178
+ * added: preserve animations in GIF images during resize operations
179
+ * added: ExactDN will fill in srcset/sizes attributes for all images based on detected width for better mobile support
180
+ * added: configuration options in the settings page for several "hidden" ExactDN options
181
+ * changed: Alt WebP still depends on jQuery, but jQuery can be loaded in async or defer mode
182
+ * changed: Remove Metadata option has been renamed, if you previously had it configured as an override (JPEGTRAN_COPY), please use the new name: EWWW_IMAGE_OPTIMIZER_METADATA_REMOVE
183
+ * changed: ExactDN uses premium compression by default
184
+ * fixed: regression with ExactDN and max-width style attributes
185
+ * fixed: WP esc_url mangles ExactDN urls
186
+ * fixed: WebP images missing from S3 when using WP Offload S3
187
+ * fixed: PDF uploads with S3 Uploads plugin
188
+ * deprecated: PHP 5.5 support will be removed in the next major release (version 4.5)
189
+ * removed: PHP 5.4 no longer supported
190
+
191
  = 4.3.2 =
192
  * changed: prevent dynamic JS/CSS urls within wp-admin/ from being rewritten by ExactDN
193
  * fixed: auto-convert PNG to JPG was running on images with transparency
224
  * fixed: PNGOUT installer confirmation notice was missing
225
  * deprecated: PHP 5.4 support will be removed in the next major release (version 4.4)
226
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227
  = Earlier versions =
228
  Please refer to the separate changelog.txt file.
229
 
248
 
249
  Written by [Shane Bishop](https://ewww.io). Based upon CW Image Optimizer, which was written by [Jacob Allred](http://www.jacoballred.com/) at [Corban Works, LLC](http://www.corbanworks.com/). CW Image Optimizer was based on WP Smush.it. Jpegtran is the work of the Independent JPEG Group. PEL is the work of Martin Geisler, Lars Olesen, and Erik Oskam. ExactDN class based upon the Photon module from Jetpack.
250
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tests/test-optimize.php CHANGED
@@ -128,10 +128,10 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
128
  * Test default JPG optimization with WebP.
129
  */
130
  function test_optimize_jpg_10() {
131
- update_option( 'ewww_image_optimizer_jpegtran_copy', true );
132
  update_option( 'ewww_image_optimizer_jpg_level', 10 );
133
  update_option( 'ewww_image_optimizer_webp', true );
134
- update_site_option( 'ewww_image_optimizer_jpegtran_copy', true );
135
  update_site_option( 'ewww_image_optimizer_jpg_level', 10 );
136
  update_site_option( 'ewww_image_optimizer_webp', true );
137
  $results = $this->optimize_jpg();
@@ -149,10 +149,10 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
149
  * Test lossless JPG and keeps meta with WebP and autorotation tests.
150
  */
151
  function test_optimize_jpg_10_keep_meta() {
152
- update_option( 'ewww_image_optimizer_jpegtran_copy', '' );
153
  update_option( 'ewww_image_optimizer_jpg_level', 10 );
154
  update_option( 'ewww_image_optimizer_webp', true );
155
- update_site_option( 'ewww_image_optimizer_jpegtran_copy', '' );
156
  update_site_option( 'ewww_image_optimizer_jpg_level', 10 );
157
  update_site_option( 'ewww_image_optimizer_webp', true );
158
  $results = $this->optimize_jpg();
@@ -176,11 +176,11 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
176
  * Test Max Lossless JPG optimization with WebP (API level 20).
177
  */
178
  function test_optimize_jpg_20() {
179
- update_option( 'ewww_image_optimizer_jpegtran_copy', true );
180
  update_option( 'ewww_image_optimizer_jpg_level', 20 );
181
  update_option( 'ewww_image_optimizer_webp', true );
182
  update_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
183
- update_site_option( 'ewww_image_optimizer_jpegtran_copy', true );
184
  update_site_option( 'ewww_image_optimizer_jpg_level', 20 );
185
  update_site_option( 'ewww_image_optimizer_webp', true );
186
  update_site_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
@@ -201,11 +201,11 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
201
  * Test lossless JPG via API and keeps meta with WebP and autorotation check.
202
  */
203
  function test_optimize_jpg_20_keep_meta() {
204
- update_option( 'ewww_image_optimizer_jpegtran_copy', '' );
205
  update_option( 'ewww_image_optimizer_jpg_level', 20 );
206
  update_option( 'ewww_image_optimizer_webp', true );
207
  update_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
208
- update_site_option( 'ewww_image_optimizer_jpegtran_copy', '' );
209
  update_site_option( 'ewww_image_optimizer_jpg_level', 20 );
210
  update_site_option( 'ewww_image_optimizer_webp', true );
211
  update_site_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
@@ -230,10 +230,10 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
230
  * Test Regular Lossy JPG optimization (API level 30).
231
  */
232
  function test_optimize_jpg_30() {
233
- update_option( 'ewww_image_optimizer_jpegtran_copy', true );
234
  update_option( 'ewww_image_optimizer_jpg_level', 30 );
235
  update_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
236
- update_site_option( 'ewww_image_optimizer_jpegtran_copy', true );
237
  update_site_option( 'ewww_image_optimizer_jpg_level', 30 );
238
  update_site_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
239
  $results = $this->optimize_jpg();
@@ -247,10 +247,10 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
247
  * Test Max Lossy JPG optimization (API level 40).
248
  */
249
  function test_optimize_jpg_40() {
250
- update_option( 'ewww_image_optimizer_jpegtran_copy', true );
251
  update_option( 'ewww_image_optimizer_jpg_level', 40 );
252
  update_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
253
- update_site_option( 'ewww_image_optimizer_jpegtran_copy', true );
254
  update_site_option( 'ewww_image_optimizer_jpg_level', 40 );
255
  update_site_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
256
  $results = $this->optimize_jpg();
@@ -267,12 +267,12 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
267
  update_option( 'ewww_image_optimizer_png_level', 10 );
268
  update_option( 'ewww_image_optimizer_disable_pngout', true );
269
  update_option( 'ewww_image_optimizer_optipng_level', 2 );
270
- update_option( 'ewww_image_optimizer_jpegtran_copy', true );
271
  update_option( 'ewww_image_optimizer_webp', true );
272
  update_site_option( 'ewww_image_optimizer_png_level', 10 );
273
  update_site_option( 'ewww_image_optimizer_disable_pngout', true );
274
  update_site_option( 'ewww_image_optimizer_optipng_level', 2 );
275
- update_site_option( 'ewww_image_optimizer_jpegtran_copy', true );
276
  update_site_option( 'ewww_image_optimizer_webp', true );
277
  $results = $this->optimize_png();
278
  update_option( 'ewww_image_optimizer_webp', '' );
@@ -292,11 +292,11 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
292
  update_option( 'ewww_image_optimizer_png_level', 10 );
293
  update_option( 'ewww_image_optimizer_disable_pngout', true );
294
  update_option( 'ewww_image_optimizer_optipng_level', 2 );
295
- update_option( 'ewww_image_optimizer_jpegtran_copy', '' );
296
  update_site_option( 'ewww_image_optimizer_png_level', 10 );
297
  update_site_option( 'ewww_image_optimizer_disable_pngout', true );
298
  update_site_option( 'ewww_image_optimizer_optipng_level', 2 );
299
- update_site_option( 'ewww_image_optimizer_jpegtran_copy', '' );
300
  $results = $this->optimize_png();
301
  $this->assertEquals( 190775, filesize( $results[0] ) );
302
  unlink( $results[0] );
@@ -310,12 +310,12 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
310
  update_option( 'ewww_image_optimizer_disable_pngout', '' );
311
  update_option( 'ewww_image_optimizer_optipng_level', 2 );
312
  update_option( 'ewww_image_optimizer_pngout_level', 1 );
313
- update_option( 'ewww_image_optimizer_jpegtran_copy', true );
314
  update_site_option( 'ewww_image_optimizer_png_level', 10 );
315
  update_site_option( 'ewww_image_optimizer_disable_pngout', '' );
316
  update_site_option( 'ewww_image_optimizer_optipng_level', 2 );
317
  update_site_option( 'ewww_image_optimizer_pngout_level', 1 );
318
- update_site_option( 'ewww_image_optimizer_jpegtran_copy', true );
319
  $results = $this->optimize_png();
320
  $this->assertEquals( 180779, filesize( $results[0] ) );
321
  unlink( $results[0] );
@@ -328,11 +328,11 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
328
  update_option( 'ewww_image_optimizer_png_level', 40 );
329
  update_option( 'ewww_image_optimizer_disable_pngout', true );
330
  update_option( 'ewww_image_optimizer_optipng_level', 2 );
331
- update_option( 'ewww_image_optimizer_jpegtran_copy', true );
332
  update_site_option( 'ewww_image_optimizer_png_level', 40 );
333
  update_site_option( 'ewww_image_optimizer_disable_pngout', true );
334
  update_site_option( 'ewww_image_optimizer_optipng_level', 2 );
335
- update_site_option( 'ewww_image_optimizer_jpegtran_copy', true );
336
  $results = $this->optimize_png();
337
  $this->assertEquals( 37428, filesize( $results[0] ) );
338
  unlink( $results[0] );
@@ -343,10 +343,10 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
343
  */
344
  function test_optimize_png_20() {
345
  update_option( 'ewww_image_optimizer_png_level', 20 );
346
- update_option( 'ewww_image_optimizer_jpegtran_copy', true );
347
  update_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
348
  update_site_option( 'ewww_image_optimizer_png_level', 20 );
349
- update_site_option( 'ewww_image_optimizer_jpegtran_copy', true );
350
  update_site_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
351
  $results = $this->optimize_png();
352
  update_option( 'ewww_image_optimizer_cloud_key', '' );
@@ -360,10 +360,10 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
360
  */
361
  function test_optimize_png_40() {
362
  update_option( 'ewww_image_optimizer_png_level', 40 );
363
- update_option( 'ewww_image_optimizer_jpegtran_copy', true );
364
  update_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
365
  update_site_option( 'ewww_image_optimizer_png_level', 40 );
366
- update_site_option( 'ewww_image_optimizer_jpegtran_copy', true );
367
  update_site_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
368
  $results = $this->optimize_png();
369
  update_option( 'ewww_image_optimizer_cloud_key', '' );
@@ -377,10 +377,10 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
377
  */
378
  function test_optimize_png_50() {
379
  update_option( 'ewww_image_optimizer_png_level', 50 );
380
- update_option( 'ewww_image_optimizer_jpegtran_copy', true );
381
  update_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
382
  update_site_option( 'ewww_image_optimizer_png_level', 50 );
383
- update_site_option( 'ewww_image_optimizer_jpegtran_copy', true );
384
  update_site_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
385
  $results = $this->optimize_png();
386
  update_option( 'ewww_image_optimizer_cloud_key', '' );
128
  * Test default JPG optimization with WebP.
129
  */
130
  function test_optimize_jpg_10() {
131
+ update_option( 'ewww_image_optimizer_metadata_remove', true );
132
  update_option( 'ewww_image_optimizer_jpg_level', 10 );
133
  update_option( 'ewww_image_optimizer_webp', true );
134
+ update_site_option( 'ewww_image_optimizer_metadata_remove', true );
135
  update_site_option( 'ewww_image_optimizer_jpg_level', 10 );
136
  update_site_option( 'ewww_image_optimizer_webp', true );
137
  $results = $this->optimize_jpg();
149
  * Test lossless JPG and keeps meta with WebP and autorotation tests.
150
  */
151
  function test_optimize_jpg_10_keep_meta() {
152
+ update_option( 'ewww_image_optimizer_metadata_remove', '' );
153
  update_option( 'ewww_image_optimizer_jpg_level', 10 );
154
  update_option( 'ewww_image_optimizer_webp', true );
155
+ update_site_option( 'ewww_image_optimizer_metadata_remove', '' );
156
  update_site_option( 'ewww_image_optimizer_jpg_level', 10 );
157
  update_site_option( 'ewww_image_optimizer_webp', true );
158
  $results = $this->optimize_jpg();
176
  * Test Max Lossless JPG optimization with WebP (API level 20).
177
  */
178
  function test_optimize_jpg_20() {
179
+ update_option( 'ewww_image_optimizer_metadata_remove', true );
180
  update_option( 'ewww_image_optimizer_jpg_level', 20 );
181
  update_option( 'ewww_image_optimizer_webp', true );
182
  update_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
183
+ update_site_option( 'ewww_image_optimizer_metadata_remove', true );
184
  update_site_option( 'ewww_image_optimizer_jpg_level', 20 );
185
  update_site_option( 'ewww_image_optimizer_webp', true );
186
  update_site_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
201
  * Test lossless JPG via API and keeps meta with WebP and autorotation check.
202
  */
203
  function test_optimize_jpg_20_keep_meta() {
204
+ update_option( 'ewww_image_optimizer_metadata_remove', '' );
205
  update_option( 'ewww_image_optimizer_jpg_level', 20 );
206
  update_option( 'ewww_image_optimizer_webp', true );
207
  update_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
208
+ update_site_option( 'ewww_image_optimizer_metadata_remove', '' );
209
  update_site_option( 'ewww_image_optimizer_jpg_level', 20 );
210
  update_site_option( 'ewww_image_optimizer_webp', true );
211
  update_site_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
230
  * Test Regular Lossy JPG optimization (API level 30).
231
  */
232
  function test_optimize_jpg_30() {
233
+ update_option( 'ewww_image_optimizer_metadata_remove', true );
234
  update_option( 'ewww_image_optimizer_jpg_level', 30 );
235
  update_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
236
+ update_site_option( 'ewww_image_optimizer_metadata_remove', true );
237
  update_site_option( 'ewww_image_optimizer_jpg_level', 30 );
238
  update_site_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
239
  $results = $this->optimize_jpg();
247
  * Test Max Lossy JPG optimization (API level 40).
248
  */
249
  function test_optimize_jpg_40() {
250
+ update_option( 'ewww_image_optimizer_metadata_remove', true );
251
  update_option( 'ewww_image_optimizer_jpg_level', 40 );
252
  update_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
253
+ update_site_option( 'ewww_image_optimizer_metadata_remove', true );
254
  update_site_option( 'ewww_image_optimizer_jpg_level', 40 );
255
  update_site_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
256
  $results = $this->optimize_jpg();
267
  update_option( 'ewww_image_optimizer_png_level', 10 );
268
  update_option( 'ewww_image_optimizer_disable_pngout', true );
269
  update_option( 'ewww_image_optimizer_optipng_level', 2 );
270
+ update_option( 'ewww_image_optimizer_metadata_remove', true );
271
  update_option( 'ewww_image_optimizer_webp', true );
272
  update_site_option( 'ewww_image_optimizer_png_level', 10 );
273
  update_site_option( 'ewww_image_optimizer_disable_pngout', true );
274
  update_site_option( 'ewww_image_optimizer_optipng_level', 2 );
275
+ update_site_option( 'ewww_image_optimizer_metadata_remove', true );
276
  update_site_option( 'ewww_image_optimizer_webp', true );
277
  $results = $this->optimize_png();
278
  update_option( 'ewww_image_optimizer_webp', '' );
292
  update_option( 'ewww_image_optimizer_png_level', 10 );
293
  update_option( 'ewww_image_optimizer_disable_pngout', true );
294
  update_option( 'ewww_image_optimizer_optipng_level', 2 );
295
+ update_option( 'ewww_image_optimizer_metadata_remove', '' );
296
  update_site_option( 'ewww_image_optimizer_png_level', 10 );
297
  update_site_option( 'ewww_image_optimizer_disable_pngout', true );
298
  update_site_option( 'ewww_image_optimizer_optipng_level', 2 );
299
+ update_site_option( 'ewww_image_optimizer_metadata_remove', '' );
300
  $results = $this->optimize_png();
301
  $this->assertEquals( 190775, filesize( $results[0] ) );
302
  unlink( $results[0] );
310
  update_option( 'ewww_image_optimizer_disable_pngout', '' );
311
  update_option( 'ewww_image_optimizer_optipng_level', 2 );
312
  update_option( 'ewww_image_optimizer_pngout_level', 1 );
313
+ update_option( 'ewww_image_optimizer_metadata_remove', true );
314
  update_site_option( 'ewww_image_optimizer_png_level', 10 );
315
  update_site_option( 'ewww_image_optimizer_disable_pngout', '' );
316
  update_site_option( 'ewww_image_optimizer_optipng_level', 2 );
317
  update_site_option( 'ewww_image_optimizer_pngout_level', 1 );
318
+ update_site_option( 'ewww_image_optimizer_metadata_remove', true );
319
  $results = $this->optimize_png();
320
  $this->assertEquals( 180779, filesize( $results[0] ) );
321
  unlink( $results[0] );
328
  update_option( 'ewww_image_optimizer_png_level', 40 );
329
  update_option( 'ewww_image_optimizer_disable_pngout', true );
330
  update_option( 'ewww_image_optimizer_optipng_level', 2 );
331
+ update_option( 'ewww_image_optimizer_metadata_remove', true );
332
  update_site_option( 'ewww_image_optimizer_png_level', 40 );
333
  update_site_option( 'ewww_image_optimizer_disable_pngout', true );
334
  update_site_option( 'ewww_image_optimizer_optipng_level', 2 );
335
+ update_site_option( 'ewww_image_optimizer_metadata_remove', true );
336
  $results = $this->optimize_png();
337
  $this->assertEquals( 37428, filesize( $results[0] ) );
338
  unlink( $results[0] );
343
  */
344
  function test_optimize_png_20() {
345
  update_option( 'ewww_image_optimizer_png_level', 20 );
346
+ update_option( 'ewww_image_optimizer_metadata_remove', true );
347
  update_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
348
  update_site_option( 'ewww_image_optimizer_png_level', 20 );
349
+ update_site_option( 'ewww_image_optimizer_metadata_remove', true );
350
  update_site_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
351
  $results = $this->optimize_png();
352
  update_option( 'ewww_image_optimizer_cloud_key', '' );
360
  */
361
  function test_optimize_png_40() {
362
  update_option( 'ewww_image_optimizer_png_level', 40 );
363
+ update_option( 'ewww_image_optimizer_metadata_remove', true );
364
  update_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
365
  update_site_option( 'ewww_image_optimizer_png_level', 40 );
366
+ update_site_option( 'ewww_image_optimizer_metadata_remove', true );
367
  update_site_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
368
  $results = $this->optimize_png();
369
  update_option( 'ewww_image_optimizer_cloud_key', '' );
377
  */
378
  function test_optimize_png_50() {
379
  update_option( 'ewww_image_optimizer_png_level', 50 );
380
+ update_option( 'ewww_image_optimizer_metadata_remove', true );
381
  update_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
382
  update_site_option( 'ewww_image_optimizer_png_level', 50 );
383
+ update_site_option( 'ewww_image_optimizer_metadata_remove', true );
384
  update_site_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
385
  $results = $this->optimize_png();
386
  update_option( 'ewww_image_optimizer_cloud_key', '' );
tests/test-resize.php CHANGED
@@ -58,9 +58,9 @@ class EWWWIO_Resize_Tests extends WP_UnitTestCase {
58
  * Creates a JPG attachment while resizing is enabled (no cropping) using jpegtran.
59
  */
60
  function test_scale_jpg_local() {
61
- update_option( 'ewww_image_optimizer_jpegtran_copy', true );
62
  update_option( 'ewww_image_optimizer_jpg_level', 10 );
63
- update_site_option( 'ewww_image_optimizer_jpegtran_copy', true );
64
  update_site_option( 'ewww_image_optimizer_jpg_level', 10 );
65
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_maxotherwidth', 1024 );
66
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_maxotherheight', 1024 );
@@ -76,9 +76,9 @@ class EWWWIO_Resize_Tests extends WP_UnitTestCase {
76
  * Creates a JPG attachment while resizing is enabled (crop-mode) using jpegtran.
77
  */
78
  function test_crop_jpg_local() {
79
- update_option( 'ewww_image_optimizer_jpegtran_copy', true );
80
  update_option( 'ewww_image_optimizer_jpg_level', 10 );
81
- update_site_option( 'ewww_image_optimizer_jpegtran_copy', true );
82
  update_site_option( 'ewww_image_optimizer_jpg_level', 10 );
83
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_maxotherwidth', 1024 );
84
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_maxotherheight', 1024 );
@@ -96,9 +96,9 @@ class EWWWIO_Resize_Tests extends WP_UnitTestCase {
96
  * Creates a JPG attachment while resizing is enabled (no cropping) using API.
97
  */
98
  function test_scale_jpg_cloud() {
99
- update_option( 'ewww_image_optimizer_jpegtran_copy', true );
100
  update_option( 'ewww_image_optimizer_jpg_level', 20 );
101
- update_site_option( 'ewww_image_optimizer_jpegtran_copy', true );
102
  update_site_option( 'ewww_image_optimizer_jpg_level', 20 );
103
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
104
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_maxotherwidth', 1024 );
@@ -115,9 +115,9 @@ class EWWWIO_Resize_Tests extends WP_UnitTestCase {
115
  * Creates a JPG attachment while resizing is enabled (crop-mode) using API.
116
  */
117
  function test_crop_jpg_cloud() {
118
- update_option( 'ewww_image_optimizer_jpegtran_copy', true );
119
  update_option( 'ewww_image_optimizer_jpg_level', 20 );
120
- update_site_option( 'ewww_image_optimizer_jpegtran_copy', true );
121
  update_site_option( 'ewww_image_optimizer_jpg_level', 20 );
122
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
123
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_maxotherwidth', 1024 );
58
  * Creates a JPG attachment while resizing is enabled (no cropping) using jpegtran.
59
  */
60
  function test_scale_jpg_local() {
61
+ update_option( 'ewww_image_optimizer_metadata_remove', true );
62
  update_option( 'ewww_image_optimizer_jpg_level', 10 );
63
+ update_site_option( 'ewww_image_optimizer_metadata_remove', true );
64
  update_site_option( 'ewww_image_optimizer_jpg_level', 10 );
65
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_maxotherwidth', 1024 );
66
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_maxotherheight', 1024 );
76
  * Creates a JPG attachment while resizing is enabled (crop-mode) using jpegtran.
77
  */
78
  function test_crop_jpg_local() {
79
+ update_option( 'ewww_image_optimizer_metadata_remove', true );
80
  update_option( 'ewww_image_optimizer_jpg_level', 10 );
81
+ update_site_option( 'ewww_image_optimizer_metadata_remove', true );
82
  update_site_option( 'ewww_image_optimizer_jpg_level', 10 );
83
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_maxotherwidth', 1024 );
84
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_maxotherheight', 1024 );
96
  * Creates a JPG attachment while resizing is enabled (no cropping) using API.
97
  */
98
  function test_scale_jpg_cloud() {
99
+ update_option( 'ewww_image_optimizer_metadata_remove', true );
100
  update_option( 'ewww_image_optimizer_jpg_level', 20 );
101
+ update_site_option( 'ewww_image_optimizer_metadata_remove', true );
102
  update_site_option( 'ewww_image_optimizer_jpg_level', 20 );
103
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
104
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_maxotherwidth', 1024 );
115
  * Creates a JPG attachment while resizing is enabled (crop-mode) using API.
116
  */
117
  function test_crop_jpg_cloud() {
118
+ update_option( 'ewww_image_optimizer_metadata_remove', true );
119
  update_option( 'ewww_image_optimizer_jpg_level', 20 );
120
+ update_site_option( 'ewww_image_optimizer_metadata_remove', true );
121
  update_site_option( 'ewww_image_optimizer_jpg_level', 20 );
122
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_cloud_key', 'abc123' );
123
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_maxotherwidth', 1024 );
unique.php CHANGED
@@ -115,7 +115,7 @@ function ewww_image_optimizer_set_defaults() {
115
  add_site_option( 'ewww_image_optimizer_disable_pngout', true );
116
  add_site_option( 'ewww_image_optimizer_optipng_level', 2 );
117
  add_site_option( 'ewww_image_optimizer_pngout_level', 2 );
118
- add_site_option( 'ewww_image_optimizer_jpegtran_copy', true );
119
  add_site_option( 'ewww_image_optimizer_jpg_level', '10' );
120
  add_site_option( 'ewww_image_optimizer_png_level', '10' );
121
  add_site_option( 'ewww_image_optimizer_gif_level', '10' );
@@ -1473,6 +1473,87 @@ function ewww_image_optimizer_find_nix_binary( $binary, $switch ) {
1473
  }
1474
  }
1475
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1476
  /**
1477
  * Automatically corrects JPG rotation using local jpegtran tool.
1478
  *
@@ -1842,8 +1923,8 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1842
  ewwwio_debug_message( 'attempting to optimize JPG...' );
1843
  // Generate temporary file-name.
1844
  $progfile = $file . '.prog';
1845
- // Check to see if we are supposed to strip metadata (badly named).
1846
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) && ! $keep_metadata ) {
1847
  // Don't copy metadata.
1848
  $copy_opt = 'none';
1849
  } else {
@@ -1934,7 +2015,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1934
  if ( $tools['OPTIPNG'] ) {
1935
  // Retrieve the optipng optimization level.
1936
  $optipng_level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_optipng_level' );
1937
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) && preg_match( '/0.7/', ewww_image_optimizer_tool_found( $tools['OPTIPNG'], 'o' ) ) && ! $keep_metadata ) {
1938
  $strip = '-strip all ';
1939
  } else {
1940
  $strip = '';
@@ -2133,7 +2214,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2133
  if ( $tools['OPTIPNG'] ) {
2134
  // Retrieve the optimization level for optipng.
2135
  $optipng_level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_optipng_level' );
2136
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) && preg_match( '/0.7/', ewww_image_optimizer_tool_found( $tools['OPTIPNG'], 'o' ) ) && ! $keep_metadata ) {
2137
  $strip = '-strip all ';
2138
  } else {
2139
  $strip = '';
@@ -2255,8 +2336,8 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2255
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) == 10 && file_exists( $jpgfile ) ) {
2256
  // Generate temporary file-name.
2257
  $progfile = $jpgfile . '.prog';
2258
- // Check to see if we are supposed to strip metadata (badly named).
2259
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) && ! $keep_metadata ) {
2260
  // Don't copy metadata.
2261
  $copy_opt = 'none';
2262
  } else {
@@ -2423,7 +2504,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2423
  if ( $tools['OPTIPNG'] ) {
2424
  // Retrieve the optipng optimization level.
2425
  $optipng_level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_optipng_level' );
2426
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) && preg_match( '/0.7/', ewww_image_optimizer_tool_found( $tools['OPTIPNG'], 'o' ) ) && ! $keep_metadata ) {
2427
  $strip = '-strip all ';
2428
  } else {
2429
  $strip = '';
@@ -2561,8 +2642,8 @@ function ewww_image_optimizer_webp_create( $file, $orig_size, $type, $tool, $rec
2561
  } else {
2562
  // Check to see if 'nice' exists.
2563
  $nice = ewww_image_optimizer_find_nix_binary( 'nice', 'n' );
2564
- // Check to see if we are supposed to strip metadata (badly named).
2565
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) ) {
2566
  // Don't copy metadata.
2567
  $copy_opt = 'none';
2568
  } else {
115
  add_site_option( 'ewww_image_optimizer_disable_pngout', true );
116
  add_site_option( 'ewww_image_optimizer_optipng_level', 2 );
117
  add_site_option( 'ewww_image_optimizer_pngout_level', 2 );
118
+ add_site_option( 'ewww_image_optimizer_metadata_remove', true );
119
  add_site_option( 'ewww_image_optimizer_jpg_level', '10' );
120
  add_site_option( 'ewww_image_optimizer_png_level', '10' );
121
  add_site_option( 'ewww_image_optimizer_gif_level', '10' );
1473
  }
1474
  }
1475
 
1476
+ /**
1477
+ * Resizes an image with gifsicle to preserve animations.
1478
+ *
1479
+ * @param string $file The file to resize.
1480
+ * @param int|null $max_w Desired image width.
1481
+ * @param int|null $max_h Desired image height.
1482
+ * @param bool $crop Optional. Scale by default, crop if true.
1483
+ * @return string|WP_Error The image contents or the error message.
1484
+ */
1485
+ function ewww_image_optimizer_gifsicle_resize( $file, $max_w, $max_h, $crop = false ) {
1486
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1487
+ $tools = ewww_image_optimizer_path_check(
1488
+ false,
1489
+ false,
1490
+ true,
1491
+ false,
1492
+ false,
1493
+ false
1494
+ );
1495
+ if ( empty( $tools['GIFSICLE'] ) ) {
1496
+ return new WP_Error(
1497
+ 'image_resize_error',
1498
+ /* translators: %s: name of a tool like jpegtran */
1499
+ sprintf( __( '%s is missing', 'ewww-image-optimizer' ), '<em>gifsicle</em>' )
1500
+ );
1501
+ }
1502
+ ewwwio_debug_message( "file: $file " );
1503
+ ewwwio_debug_message( "width: $max_w" );
1504
+ ewwwio_debug_message( "height: $max_h" );
1505
+ $orig_dimensions = getimagesize( $file );
1506
+ if ( empty( $orig_dimensions ) ) {
1507
+ return new WP_Error( 'image_resize_error', __( 'Invalid image dimensions.', 'ewww-image-optimizer' ) );
1508
+ }
1509
+ $orig_w = $orig_dimensions[0];
1510
+ $orig_h = $orig_dimensions[1];
1511
+
1512
+ $outfile = "$file.tmp";
1513
+ // Run gifsicle.
1514
+ if ( $crop ) {
1515
+ $dims = ewwwio_crop_dimensions( $orig_w, $orig_h, $max_w, $max_h );
1516
+ if ( ! $dims ) {
1517
+ return new WP_Error( 'error_getting_dimensions', __( 'Could not calculate resized image dimensions' ), $file );
1518
+ }
1519
+ ewwwio_debug_message( implode( ',', $dims ) );
1520
+ list( $src_x, $src_y, $dst_w, $dst_h ) = $dims;
1521
+
1522
+ list( $new_w, $new_h ) = wp_constrain_dimensions( $dst_w, $dst_h, $max_w, $max_h );
1523
+
1524
+ $dim_string = $new_w . 'x' . $new_h;
1525
+ $crop_string = $src_x . ',' . $src_y . '+' . $dst_w . 'x' . $dst_h;
1526
+ ewwwio_debug_message( "resize to $dim_string" );
1527
+ ewwwio_debug_message( "crop to $crop_string" );
1528
+ exec( "{$tools['GIFSICLE']} --crop $crop_string -o " . ewww_image_optimizer_escapeshellarg( $outfile ) . ' ' . ewww_image_optimizer_escapeshellarg( $file ) );
1529
+ exec( "{$tools['GIFSICLE']} --resize-fit $dim_string -b " . ewww_image_optimizer_escapeshellarg( $outfile ) );
1530
+ } else {
1531
+ list( $new_w, $new_h ) = wp_constrain_dimensions( $orig_w, $orig_h, $max_w, $max_h );
1532
+
1533
+ $dim_string = $new_w . 'x' . $new_h;
1534
+ exec( "{$tools['GIFSICLE']} --resize-fit $dim_string -o " . ewww_image_optimizer_escapeshellarg( $outfile ) . ' ' . ewww_image_optimizer_escapeshellarg( $file ) );
1535
+ }
1536
+ ewwwio_debug_message( "$file resized to $outfile" );
1537
+
1538
+ if ( file_exists( $outfile ) ) {
1539
+ $new_type = ewww_image_optimizer_mimetype( $outfile, 'i' );
1540
+ // Check the filesize of the new JPG.
1541
+ $new_size = filesize( $outfile );
1542
+ ewwwio_debug_message( "$outfile exists, testing type and size" );
1543
+ } else {
1544
+ return new WP_Error( 'image_resize_error', 'file does not exist' );
1545
+ }
1546
+
1547
+ if ( 0 == $new_size || 'image/gif' != $new_type ) {
1548
+ unlink( $outfile );
1549
+ return new WP_Error( 'image_resize_error', 'wrong type or zero bytes' );
1550
+ }
1551
+ ewwwio_debug_message( 'resize success' );
1552
+ $image = file_get_contents( $outfile );
1553
+ unlink( $outfile );
1554
+ return $image;
1555
+ }
1556
+
1557
  /**
1558
  * Automatically corrects JPG rotation using local jpegtran tool.
1559
  *
1923
  ewwwio_debug_message( 'attempting to optimize JPG...' );
1924
  // Generate temporary file-name.
1925
  $progfile = $file . '.prog';
1926
+ // Check to see if we are supposed to strip metadata.
1927
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) && ! $keep_metadata ) {
1928
  // Don't copy metadata.
1929
  $copy_opt = 'none';
1930
  } else {
2015
  if ( $tools['OPTIPNG'] ) {
2016
  // Retrieve the optipng optimization level.
2017
  $optipng_level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_optipng_level' );
2018
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) && preg_match( '/0.7/', ewww_image_optimizer_tool_found( $tools['OPTIPNG'], 'o' ) ) && ! $keep_metadata ) {
2019
  $strip = '-strip all ';
2020
  } else {
2021
  $strip = '';
2214
  if ( $tools['OPTIPNG'] ) {
2215
  // Retrieve the optimization level for optipng.
2216
  $optipng_level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_optipng_level' );
2217
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) && preg_match( '/0.7/', ewww_image_optimizer_tool_found( $tools['OPTIPNG'], 'o' ) ) && ! $keep_metadata ) {
2218
  $strip = '-strip all ';
2219
  } else {
2220
  $strip = '';
2336
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) == 10 && file_exists( $jpgfile ) ) {
2337
  // Generate temporary file-name.
2338
  $progfile = $jpgfile . '.prog';
2339
+ // Check to see if we are supposed to strip metadata.
2340
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) && ! $keep_metadata ) {
2341
  // Don't copy metadata.
2342
  $copy_opt = 'none';
2343
  } else {
2504
  if ( $tools['OPTIPNG'] ) {
2505
  // Retrieve the optipng optimization level.
2506
  $optipng_level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_optipng_level' );
2507
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) && preg_match( '/0.7/', ewww_image_optimizer_tool_found( $tools['OPTIPNG'], 'o' ) ) && ! $keep_metadata ) {
2508
  $strip = '-strip all ';
2509
  } else {
2510
  $strip = '';
2642
  } else {
2643
  // Check to see if 'nice' exists.
2644
  $nice = ewww_image_optimizer_find_nix_binary( 'nice', 'n' );
2645
+ // Check to see if we are supposed to strip metadata.
2646
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) ) {
2647
  // Don't copy metadata.
2648
  $copy_opt = 'none';
2649
  } else {