EWWW Image Optimizer - Version 4.0.6

Version Description

  • changed: dummy images have no args appended with exactdn except for ssl flag
  • fixed: resize_detection.js being combined with other scripts by Autoptimize
  • fixed: retina optimization not deferred in async mode
  • fixed: PDF files could trigger license exceeded message
  • fixed: binary detection not fully functional with MacOS and PHP 7.2
  • fixed: compatibility with Regenerate Thumbnails version 3
Download this release

Release Info

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

Code changes from version 3.6.1 to 4.0.6

Files changed (52) hide show
  1. .travis.yml +8 -3
  2. aux-optimize.php +57 -47
  3. bulk.php +143 -119
  4. changelog.txt +66 -0
  5. classes/class-ewww-flag.php +72 -61
  6. classes/class-ewww-image.php +49 -47
  7. classes/class-ewww-nextcellent.php +61 -51
  8. classes/class-ewww-nextgen.php +67 -54
  9. classes/class-ewwwdb.php +6 -6
  10. vendor/wp-background-process.php → classes/class-ewwwio-background-process.php +59 -55
  11. classes/class-ewwwio-cli.php +3 -3
  12. classes/class-ewwwio-gd-editor.php +17 -17
  13. classes/class-ewwwio-gmagick-editor.php +4 -4
  14. classes/class-ewwwio-hs-beacon.php +1 -1
  15. classes/class-ewwwio-imagick-editor.php +18 -18
  16. classes/class-ewwwio-media-background-process.php +27 -23
  17. classes/class-ewwwio-tracking.php +71 -67
  18. classes/class-exactdn.php +1759 -0
  19. common.php +787 -438
  20. ewww-image-optimizer.php +14 -2
  21. includes/eio.js +23 -7
  22. includes/exactdn.js +55 -0
  23. includes/load_webp.js +63 -4
  24. includes/load_webp.min.js +1 -1
  25. includes/resize_detection.js +4 -4
  26. mwebp.php +30 -27
  27. phpcs.ruleset.xml +3 -3
  28. readme.txt +75 -99
  29. tests/test-optimize.php +1 -1
  30. unique.php +248 -243
  31. vendor/pel/AUTHORS +53 -0
  32. vendor/pel/src/PelCanonMakerNotes.php +336 -0
  33. vendor/pel/src/PelConvert.php +10 -10
  34. vendor/pel/src/PelDataWindow.php +3 -3
  35. vendor/pel/src/PelEntry.php +4 -4
  36. vendor/pel/src/PelEntryByte.php +1 -1
  37. vendor/pel/src/PelEntryException.php +2 -2
  38. vendor/pel/src/PelEntryLong.php +1 -1
  39. vendor/pel/src/PelEntryRational.php +1 -1
  40. vendor/pel/src/PelEntrySByte.php +1 -1
  41. vendor/pel/src/PelEntrySLong.php +1 -1
  42. vendor/pel/src/PelEntrySRational.php +1 -1
  43. vendor/pel/src/PelEntrySShort.php +1475 -2
  44. vendor/pel/src/PelEntryShort.php +175 -2
  45. vendor/pel/src/PelIfd.php +439 -50
  46. vendor/pel/src/PelJpeg.php +21 -19
  47. vendor/pel/src/PelMakerNotes.php +73 -0
  48. vendor/pel/src/PelMakerNotesMalformedException.php +50 -0
  49. vendor/pel/src/PelTag.php +760 -3
  50. vendor/pel/src/PelTiff.php +1 -1
  51. vendor/pel/src/PelWrongComponentCountException.php +1 -1
  52. vendor/wp-async-request.php +2 -0
.travis.yml CHANGED
@@ -12,26 +12,31 @@ branches:
12
  - master
13
 
14
  php:
15
- - 5.3
16
  - 5.4
17
  - 5.5
18
  - 5.6
19
  - 7.0
20
  - 7.1
 
21
 
22
  env:
23
  - WP_VERSION=latest WP_MULTISITE=0
24
- - WP_VERSION=4.4 WP_MULTISITE=0
25
 
26
  matrix:
27
  include:
 
 
 
28
  - php: 5.3
29
  env: WP_VERSION=latest WP_MULTISITE=1
 
30
  - php: 7.0
31
  env: WP_VERSION=latest WP_MULTISITE=1
32
 
33
  before_script:
34
  - bash bin/install-wp-tests.sh wordpress_test root '' localhost $WP_VERSION
 
35
  - export PATH="$HOME/.composer/vendor/bin:$PATH"
36
  - |
37
  if [[ ${TRAVIS_PHP_VERSION:0:2} == "7." ]]; then
@@ -44,5 +49,5 @@ before_script:
44
  phpcs --config-set installed_paths $HOME/.composer/vendor/wp-coding-standards/wpcs
45
 
46
  script:
47
- - phpcs --standard=phpcs.ruleset.xml $(find . -name '*.php')
48
  - phpunit
12
  - master
13
 
14
  php:
 
15
  - 5.4
16
  - 5.5
17
  - 5.6
18
  - 7.0
19
  - 7.1
20
+ - 7.2
21
 
22
  env:
23
  - WP_VERSION=latest WP_MULTISITE=0
24
+ - WP_VERSION=4.6 WP_MULTISITE=0
25
 
26
  matrix:
27
  include:
28
+ - php: 5.3
29
+ env: WP_VERSION=latest WP_MULTISITE=0
30
+ dist: precise
31
  - php: 5.3
32
  env: WP_VERSION=latest WP_MULTISITE=1
33
+ dist: precise
34
  - php: 7.0
35
  env: WP_VERSION=latest WP_MULTISITE=1
36
 
37
  before_script:
38
  - bash bin/install-wp-tests.sh wordpress_test root '' localhost $WP_VERSION
39
+ - phpenv config-rm xdebug.ini
40
  - export PATH="$HOME/.composer/vendor/bin:$PATH"
41
  - |
42
  if [[ ${TRAVIS_PHP_VERSION:0:2} == "7." ]]; then
49
  phpcs --config-set installed_paths $HOME/.composer/vendor/wp-coding-standards/wpcs
50
 
51
  script:
52
+ - phpcs --standard=phpcs.ruleset.xml --extensions=php .
53
  - phpunit
aux-optimize.php CHANGED
@@ -69,6 +69,7 @@ function ewww_image_optimizer_aux_images() {
69
  '<span id="ewww-pointer" style="display:none">0</span>' .
70
  '</div>' .
71
  '</div>';
 
72
  $help_instructions = esc_html__( 'Enable the Debugging option and refresh this page to include debugging information with your question.', 'ewww-image-optimizer' ) . ' ' .
73
  esc_html__( 'This will allow us to assist you more quickly.', 'ewww-image-optimizer' );
74
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
@@ -91,10 +92,10 @@ function ewww_image_optimizer_aux_images() {
91
  $output .= '<p style="clear:both"><b>' . esc_html__( 'Debugging Information', 'ewww-image-optimizer' ) . ':</b> <button onclick="selectText(' . "'ewww-debug-info'" . ')">' . esc_html__( 'Select All', 'ewww-image-optimizer' ) . '</button>';
92
  if ( is_file( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'debug.log' ) ) {
93
  $debug_log_url = plugins_url( '/debug.log', __FILE__ );
94
- $output .= "&emsp;<a href='$debug_log_url'>" . esc_html( 'View Debug Log', 'ewww-image-optimizer' ) . "</a> - <a href='admin.php?action=ewww_image_optimizer_delete_debug_log'>" . esc_html( 'Remove Debug Log', 'ewww-image-optimizer' ) . '</a>';
95
  }
96
- $output .= '</p>';
97
- $output .= '<div id="ewww-debug-info" style="background:#ffff99;margin-left:-20px;padding:10px" contenteditable="true">' . $ewww_debug . '</div>';
98
  $help_instructions = esc_html__( 'Debugging information will be included with your message automatically.', 'ewww-image-optimizer' ) . ' ' .
99
  esc_html__( 'This will allow us to assist you more quickly.', 'ewww-image-optimizer' );
100
  }
@@ -102,23 +103,23 @@ function ewww_image_optimizer_aux_images() {
102
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_help' ) ) {
103
  /* $help_instructions = esc_html__( 'Please turn on the Debugging option. Then copy and paste the Debug Information from the bottom of the settings page. This will allow us to assist you more quickly.', 'ewww-image-optimizer' ); */
104
  $current_user = wp_get_current_user();
105
- $help_email = $current_user->user_email;
106
- $hs_config = array(
107
- 'color' => '#3eadc9',
108
- 'icon' => 'buoy',
109
- 'instructions' => $help_instructions,
110
- 'poweredBy' => false,
111
  'showContactFields' => true,
112
- 'showSubject' => true,
113
- 'topArticles' => true,
114
- 'zIndex' => 100000,
115
  );
116
- $hs_identify = array(
117
  'email' => $help_email,
118
  );
119
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
120
  $ewww_debug_array = explode( '<br>', $ewww_debug );
121
- $ewww_debug_i = 0;
122
  foreach ( $ewww_debug_array as $ewww_debug_line ) {
123
  $hs_identify[ 'debug_info_' . $ewww_debug_i ] = $ewww_debug_line;
124
  $ewww_debug_i++;
@@ -150,7 +151,8 @@ function ewww_image_optimizer_aux_images() {
150
  function ewww_image_optimizer_aux_images_table() {
151
  // Verify that an authorized user has called function.
152
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) ) {
153
- wp_die( esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) );
 
154
  }
155
  global $wpdb;
156
  if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
@@ -159,24 +161,24 @@ function ewww_image_optimizer_aux_images_table() {
159
  } else {
160
  $ewwwdb = $wpdb;
161
  }
162
- $offset = 50 * (int) $_POST['ewww_offset'];
163
- $query = "SELECT path,orig_size,image_size,id,backup,updated FROM $ewwwdb->ewwwio_images WHERE pending=0 AND image_size > 0 ORDER BY id DESC LIMIT $offset,50";
164
  $already_optimized = $ewwwdb->get_results( $query, ARRAY_A );
165
- $upload_info = wp_upload_dir();
166
- $upload_path = $upload_info['basedir'];
167
  echo '<br /><table class="wp-list-table widefat media" cellspacing="0"><thead><tr><th>&nbsp;</th><th>' . esc_html__( 'Filename', 'ewww-image-optimizer' ) . '</th><th>' . esc_html__( 'Image Type', 'ewww-image-optimizer' ) . '</th><th>' . esc_html__( 'Image Optimizer', 'ewww-image-optimizer' ) . '</th></tr></thead>';
168
  $alternate = true;
169
  foreach ( $already_optimized as $optimized_image ) {
170
- $image_name = str_replace( ABSPATH, '', ewww_image_optimizer_relative_path_replace( $optimized_image['path'] ) );
171
- $image_url = esc_url( trailingslashit( get_site_url() ) . $image_name );
172
- $savings = esc_html( ewww_image_optimizer_image_results( $optimized_image['orig_size'], $optimized_image['image_size'] ) );
173
  $updated_time = strtotime( $optimized_image['updated'] );
174
  if ( DAY_IN_SECONDS * 30 + $updated_time < time() ) {
175
  $optimized_image['backup'] = '';
176
  }
177
  if ( strpos( $optimized_image['path'], 's3' ) === 0 ) {
178
  // Retrieve the mimetype of the attachment.
179
- $type = esc_html__( 'Amazon S3 image', 'ewww-image-optimizer' );
180
  $file_size = ewww_image_optimizer_size_format( $optimized_image['image_size'] );
181
  /* translators: %s: human-readable filesize */
182
  $size_string = sprintf( esc_html__( 'Image Size: %s', 'ewww-image-optimizer' ), $file_size );
@@ -248,8 +250,10 @@ function ewww_image_optimizer_aux_images_table() {
248
  function ewww_image_optimizer_aux_images_remove() {
249
  // Verify that an authorized user has called function.
250
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) ) {
251
- wp_die( esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) );
 
252
  }
 
253
  global $wpdb;
254
  if ( $wpdb->delete(
255
  $wpdb->ewwwio_images,
@@ -274,6 +278,7 @@ function ewww_image_optimizer_aux_images_table_count() {
274
  global $wpdb;
275
  $count = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->ewwwio_images WHERE pending=0 AND image_size > 0" );
276
  if ( ! empty( $_REQUEST['ewww_inline'] ) ) {
 
277
  echo $count;
278
  ewwwio_memory( __FUNCTION__ );
279
  die();
@@ -350,19 +355,19 @@ function ewww_image_optimizer_image_scan( $dir, $started = 0 ) {
350
  }
351
  global $wpdb;
352
  global $optimized_list;
353
- $images = array();
354
  $reset_images = array();
355
  if ( ! is_dir( $dir ) ) {
356
  return;
357
  }
358
  ewwwio_debug_message( "scanning folder for images: $dir" );
359
  $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir ), RecursiveIteratorIterator::CHILD_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD );
360
- $start = microtime( true );
361
  if ( empty( $optimized_list ) || ! is_array( $optimized_list ) ) {
362
  ewww_image_optimizer_optimized_list();
363
  }
364
  $file_counter = 0; // Used to track total files overall.
365
- $image_count = 0; // Used to track number of files since last queue update.
366
  if ( ewww_image_optimizer_stl_check() ) {
367
  set_time_limit( 0 );
368
  }
@@ -393,14 +398,16 @@ function ewww_image_optimizer_image_scan( $dir, $started = 0 ) {
393
  }
394
  set_transient( 'ewww_image_optimizer_aux_iterator', $file_counter - 20, 300 ); // Keep track of where we left off, minus 20 to be safe.
395
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
 
396
  die( json_encode( array(
397
  'remaining' => '<p>' . esc_html__( 'Stage 2, please wait.', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' /></p>",
398
- 'notice' => '',
399
  ) ) );
400
  }
401
  // TODO: can we tailor this for scheduled opt also?
402
  if ( ! empty( $_REQUEST['ewww_scan'] ) && 0 === $file_counter % 100 && ! ewwwio_check_memory_available( 2097000 ) ) {
403
  if ( $file_counter < 100 ) {
 
404
  die( json_encode( array(
405
  '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' ),
406
  ) ) );
@@ -414,9 +421,10 @@ function ewww_image_optimizer_image_scan( $dir, $started = 0 ) {
414
  }
415
  set_transient( 'ewww_image_optimizer_aux_iterator', $file_counter - 20, 300 ); // Keep track of where we left off, minus 20 to be safe.
416
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
 
417
  die( 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++;
@@ -435,14 +443,13 @@ function ewww_image_optimizer_image_scan( $dir, $started = 0 ) {
435
  }
436
 
437
  $already_optimized = false;
438
- if ( is_string( $optimized_list ) ) {
439
  $already_optimized = ewww_image_optimizer_find_already_optimized( $path );
 
 
440
  }
441
 
442
- if ( $already_optimized || isset( $optimized_list[ $path ] ) ) {
443
- if ( ! $already_optimized ) {
444
- $already_optimized = $optimized_list[ $path ];
445
- }
446
  if ( ! empty( $already_optimized['pending'] ) ) {
447
  ewwwio_debug_message( "pending record for $path" );
448
  continue;
@@ -481,9 +488,9 @@ function ewww_image_optimizer_image_scan( $dir, $started = 0 ) {
481
  $utf8_file_path = utf8_encode( $path );
482
  }
483
  $images[] = array(
484
- 'path' => $utf8_file_path,
485
  'orig_size' => $image_size,
486
- 'pending' => 1,
487
  );
488
  $image_count++;
489
  } // End if().
@@ -524,12 +531,12 @@ function ewww_image_optimizer_aux_images_convert() {
524
  continue;
525
  }
526
  $record['path'] = ewww_image_optimizer_relative_path_replace( $record['path'] );
527
- $image_md5 = md5_file( $record['path'] );
528
  if ( $image_md5 === $record['image_md5'] ) {
529
  $filesize = filesize( $record['path'] );
530
  $wpdb->update( $wpdb->ewwwio_images,
531
  array(
532
- 'image_md5' => null,
533
  'image_size' => $filesize,
534
  ),
535
  array(
@@ -572,7 +579,7 @@ function ewww_image_optimizer_aux_images_script( $hook = '' ) {
572
  update_option( 'ewww_image_optimizer_aux_resume', 'scanning' );
573
  ewwwio_debug_message( 'getting fresh list of files to optimize' );
574
  // Collect a list of images from the current theme (and parent theme if applicable).
575
- $child_path = get_stylesheet_directory();
576
  $parent_path = get_template_directory();
577
  ewww_image_optimizer_image_scan( $child_path, $started );
578
  if ( $child_path !== $parent_path ) {
@@ -604,7 +611,7 @@ function ewww_image_optimizer_aux_images_script( $hook = '' ) {
604
  if ( is_plugin_active( 'ml-slider/ml-slider.php' ) || is_plugin_active_for_network( 'ml-slider/ml-slider.php' ) ) {
605
  global $wpdb;
606
  $slide_paths = array();
607
- $slides = $wpdb->get_col(
608
  "
609
  SELECT wpposts.ID
610
  FROM $wpdb->posts wpposts
@@ -629,7 +636,7 @@ function ewww_image_optimizer_aux_images_script( $hook = '' ) {
629
  if ( ewww_image_optimizer_iterable( $backup_sizes ) ) {
630
  foreach ( $backup_sizes as $backup_size => $meta ) {
631
  if ( preg_match( '/resized-/', $backup_size ) ) {
632
- $path = $meta['path'];
633
  $image_size = ewww_image_optimizer_filesize( $path );
634
  if ( ! $image_size ) {
635
  continue;
@@ -643,7 +650,7 @@ function ewww_image_optimizer_aux_images_script( $hook = '' ) {
643
  // This is a brand new image.
644
  if ( preg_match( '/^image\/(jpeg|png|gif)/', $mimetype ) && empty( $already_optimized ) ) {
645
  $slide_paths[] = array(
646
- 'path' => ewww_image_optimizer_relative_path_remove( $path ),
647
  'orig_size' => $image_size,
648
  );
649
  // This is a changed image.
@@ -674,13 +681,13 @@ function ewww_image_optimizer_aux_images_script( $hook = '' ) {
674
  $upload_dir = wp_upload_dir();
675
  // Retrieve the path of the upload folder.
676
  $upload_path = $upload_dir['basedir'];
677
- $this_month = date( 'm' );
678
- $this_year = date( 'Y' );
679
  ewww_image_optimizer_image_scan( "$upload_path/$this_year/$this_month/", $started );
680
  if ( class_exists( 'DateTime' ) ) {
681
  $date = new DateTime();
682
  $date->sub( new DateInterval( 'P1M' ) );
683
- $last_year = $date->format( 'Y' );
684
  $last_month = $date->format( 'm' );
685
  ewww_image_optimizer_image_scan( "$upload_path/$last_year/$last_month/", $started );
686
  }
@@ -697,8 +704,9 @@ function ewww_image_optimizer_aux_images_script( $hook = '' ) {
697
  /* translators: %d: number of images */
698
  $ready_msg = sprintf( esc_html( _n( 'There is %d image ready to optimize.', 'There are %d images ready to optimize.', $image_count, 'ewww-image-optimizer' ) ), $image_count )
699
  . ' <a href="http://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>';
 
700
  die( json_encode( array(
701
- 'ready' => $image_count,
702
  'message' => $ready_msg,
703
  ) ) );
704
  }
@@ -716,13 +724,15 @@ function ewww_image_optimizer_aux_images_cleanup( $auto = false ) {
716
  // Verify that an authorized user has started the optimizer.
717
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
718
  if ( ! $auto && ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) ) {
719
- wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
 
720
  }
721
  $stored_last = get_option( 'ewww_image_optimizer_aux_last' );
722
  update_option( 'ewww_image_optimizer_aux_last', array( time(), $stored_last[1] ) );
723
  // All done, so we can update the bulk options with empty values.
724
  update_option( 'ewww_image_optimizer_aux_resume', '' );
725
  if ( ! $auto ) {
 
726
  // And let the user know we are done.
727
  echo '<p><b>' . esc_html__( 'Finished', 'ewww-image-optimizer' ) . '</b></p>';
728
  ewwwio_memory( __FUNCTION__ );
69
  '<span id="ewww-pointer" style="display:none">0</span>' .
70
  '</div>' .
71
  '</div>';
72
+
73
  $help_instructions = esc_html__( 'Enable the Debugging option and refresh this page to include debugging information with your question.', 'ewww-image-optimizer' ) . ' ' .
74
  esc_html__( 'This will allow us to assist you more quickly.', 'ewww-image-optimizer' );
75
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
92
  $output .= '<p style="clear:both"><b>' . esc_html__( 'Debugging Information', 'ewww-image-optimizer' ) . ':</b> <button onclick="selectText(' . "'ewww-debug-info'" . ')">' . esc_html__( 'Select All', 'ewww-image-optimizer' ) . '</button>';
93
  if ( is_file( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'debug.log' ) ) {
94
  $debug_log_url = plugins_url( '/debug.log', __FILE__ );
95
+ $output .= "&emsp;<a href='$debug_log_url'>" . esc_html( 'View Debug Log', 'ewww-image-optimizer' ) . "</a> - <a href='admin.php?action=ewww_image_optimizer_delete_debug_log'>" . esc_html( 'Remove Debug Log', 'ewww-image-optimizer' ) . '</a>';
96
  }
97
+ $output .= '</p>';
98
+ $output .= '<div id="ewww-debug-info" style="background:#ffff99;margin-left:-20px;padding:10px" contenteditable="true">' . $ewww_debug . '</div>';
99
  $help_instructions = esc_html__( 'Debugging information will be included with your message automatically.', 'ewww-image-optimizer' ) . ' ' .
100
  esc_html__( 'This will allow us to assist you more quickly.', 'ewww-image-optimizer' );
101
  }
103
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_help' ) ) {
104
  /* $help_instructions = esc_html__( 'Please turn on the Debugging option. Then copy and paste the Debug Information from the bottom of the settings page. This will allow us to assist you more quickly.', 'ewww-image-optimizer' ); */
105
  $current_user = wp_get_current_user();
106
+ $help_email = $current_user->user_email;
107
+ $hs_config = array(
108
+ 'color' => '#3eadc9',
109
+ 'icon' => 'buoy',
110
+ 'instructions' => $help_instructions,
111
+ 'poweredBy' => false,
112
  'showContactFields' => true,
113
+ 'showSubject' => true,
114
+ 'topArticles' => true,
115
+ 'zIndex' => 100000,
116
  );
117
+ $hs_identify = array(
118
  'email' => $help_email,
119
  );
120
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
121
  $ewww_debug_array = explode( '<br>', $ewww_debug );
122
+ $ewww_debug_i = 0;
123
  foreach ( $ewww_debug_array as $ewww_debug_line ) {
124
  $hs_identify[ 'debug_info_' . $ewww_debug_i ] = $ewww_debug_line;
125
  $ewww_debug_i++;
151
  function ewww_image_optimizer_aux_images_table() {
152
  // Verify that an authorized user has called function.
153
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) ) {
154
+ ewwwio_ob_clean();
155
+ die( esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) );
156
  }
157
  global $wpdb;
158
  if ( strpos( $wpdb->charset, 'utf8' ) === false ) {
161
  } else {
162
  $ewwwdb = $wpdb;
163
  }
164
+ $offset = 50 * (int) $_POST['ewww_offset'];
165
+ $query = "SELECT path,orig_size,image_size,id,backup,updated FROM $ewwwdb->ewwwio_images WHERE pending=0 AND image_size > 0 ORDER BY id DESC LIMIT $offset,50";
166
  $already_optimized = $ewwwdb->get_results( $query, ARRAY_A );
167
+ $upload_info = wp_upload_dir();
168
+ $upload_path = $upload_info['basedir'];
169
  echo '<br /><table class="wp-list-table widefat media" cellspacing="0"><thead><tr><th>&nbsp;</th><th>' . esc_html__( 'Filename', 'ewww-image-optimizer' ) . '</th><th>' . esc_html__( 'Image Type', 'ewww-image-optimizer' ) . '</th><th>' . esc_html__( 'Image Optimizer', 'ewww-image-optimizer' ) . '</th></tr></thead>';
170
  $alternate = true;
171
  foreach ( $already_optimized as $optimized_image ) {
172
+ $image_name = str_replace( ABSPATH, '', ewww_image_optimizer_relative_path_replace( $optimized_image['path'] ) );
173
+ $image_url = esc_url( trailingslashit( get_site_url() ) . $image_name );
174
+ $savings = esc_html( ewww_image_optimizer_image_results( $optimized_image['orig_size'], $optimized_image['image_size'] ) );
175
  $updated_time = strtotime( $optimized_image['updated'] );
176
  if ( DAY_IN_SECONDS * 30 + $updated_time < time() ) {
177
  $optimized_image['backup'] = '';
178
  }
179
  if ( strpos( $optimized_image['path'], 's3' ) === 0 ) {
180
  // Retrieve the mimetype of the attachment.
181
+ $type = esc_html__( 'Amazon S3 image', 'ewww-image-optimizer' );
182
  $file_size = ewww_image_optimizer_size_format( $optimized_image['image_size'] );
183
  /* translators: %s: human-readable filesize */
184
  $size_string = sprintf( esc_html__( 'Image Size: %s', 'ewww-image-optimizer' ), $file_size );
250
  function ewww_image_optimizer_aux_images_remove() {
251
  // Verify that an authorized user has called function.
252
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) ) {
253
+ ewwwio_ob_clean();
254
+ die( esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) );
255
  }
256
+ ewwwio_ob_clean();
257
  global $wpdb;
258
  if ( $wpdb->delete(
259
  $wpdb->ewwwio_images,
278
  global $wpdb;
279
  $count = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->ewwwio_images WHERE pending=0 AND image_size > 0" );
280
  if ( ! empty( $_REQUEST['ewww_inline'] ) ) {
281
+ ewwwio_ob_clean();
282
  echo $count;
283
  ewwwio_memory( __FUNCTION__ );
284
  die();
355
  }
356
  global $wpdb;
357
  global $optimized_list;
358
+ $images = array();
359
  $reset_images = array();
360
  if ( ! is_dir( $dir ) ) {
361
  return;
362
  }
363
  ewwwio_debug_message( "scanning folder for images: $dir" );
364
  $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir ), RecursiveIteratorIterator::CHILD_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD );
365
+ $start = microtime( true );
366
  if ( empty( $optimized_list ) || ! is_array( $optimized_list ) ) {
367
  ewww_image_optimizer_optimized_list();
368
  }
369
  $file_counter = 0; // Used to track total files overall.
370
+ $image_count = 0; // Used to track number of files since last queue update.
371
  if ( ewww_image_optimizer_stl_check() ) {
372
  set_time_limit( 0 );
373
  }
398
  }
399
  set_transient( 'ewww_image_optimizer_aux_iterator', $file_counter - 20, 300 ); // Keep track of where we left off, minus 20 to be safe.
400
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
401
+ ewwwio_ob_clean();
402
  die( json_encode( array(
403
  'remaining' => '<p>' . esc_html__( 'Stage 2, please wait.', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' /></p>",
404
+ 'notice' => '',
405
  ) ) );
406
  }
407
  // TODO: can we tailor this for scheduled opt also?
408
  if ( ! empty( $_REQUEST['ewww_scan'] ) && 0 === $file_counter % 100 && ! ewwwio_check_memory_available( 2097000 ) ) {
409
  if ( $file_counter < 100 ) {
410
+ ewwwio_ob_clean();
411
  die( json_encode( array(
412
  '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' ),
413
  ) ) );
421
  }
422
  set_transient( 'ewww_image_optimizer_aux_iterator', $file_counter - 20, 300 ); // Keep track of where we left off, minus 20 to be safe.
423
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
424
+ ewwwio_ob_clean();
425
  die( json_encode( array(
426
  'remaining' => '<p>' . esc_html__( 'Stage 2, please wait.', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' /></p>",
427
+ 'notice' => '',
428
  ) ) );
429
  }
430
  $file_counter++;
443
  }
444
 
445
  $already_optimized = false;
446
+ if ( ! is_array( $optimized_list ) && is_string( $optimized_list ) ) {
447
  $already_optimized = ewww_image_optimizer_find_already_optimized( $path );
448
+ } elseif ( is_array( $optimized_list ) && isset( $optimized_list[ $path ] ) && ! empty( $optimized_list[ $path ] ) ) {
449
+ $already_optimized = $optimized_list[ $path ];
450
  }
451
 
452
+ if ( is_array( $already_optimized ) && ! empty( $already_optimized ) ) {
 
 
 
453
  if ( ! empty( $already_optimized['pending'] ) ) {
454
  ewwwio_debug_message( "pending record for $path" );
455
  continue;
488
  $utf8_file_path = utf8_encode( $path );
489
  }
490
  $images[] = array(
491
+ 'path' => $utf8_file_path,
492
  'orig_size' => $image_size,
493
+ 'pending' => 1,
494
  );
495
  $image_count++;
496
  } // End if().
531
  continue;
532
  }
533
  $record['path'] = ewww_image_optimizer_relative_path_replace( $record['path'] );
534
+ $image_md5 = md5_file( $record['path'] );
535
  if ( $image_md5 === $record['image_md5'] ) {
536
  $filesize = filesize( $record['path'] );
537
  $wpdb->update( $wpdb->ewwwio_images,
538
  array(
539
+ 'image_md5' => null,
540
  'image_size' => $filesize,
541
  ),
542
  array(
579
  update_option( 'ewww_image_optimizer_aux_resume', 'scanning' );
580
  ewwwio_debug_message( 'getting fresh list of files to optimize' );
581
  // Collect a list of images from the current theme (and parent theme if applicable).
582
+ $child_path = get_stylesheet_directory();
583
  $parent_path = get_template_directory();
584
  ewww_image_optimizer_image_scan( $child_path, $started );
585
  if ( $child_path !== $parent_path ) {
611
  if ( is_plugin_active( 'ml-slider/ml-slider.php' ) || is_plugin_active_for_network( 'ml-slider/ml-slider.php' ) ) {
612
  global $wpdb;
613
  $slide_paths = array();
614
+ $slides = $wpdb->get_col(
615
  "
616
  SELECT wpposts.ID
617
  FROM $wpdb->posts wpposts
636
  if ( ewww_image_optimizer_iterable( $backup_sizes ) ) {
637
  foreach ( $backup_sizes as $backup_size => $meta ) {
638
  if ( preg_match( '/resized-/', $backup_size ) ) {
639
+ $path = $meta['path'];
640
  $image_size = ewww_image_optimizer_filesize( $path );
641
  if ( ! $image_size ) {
642
  continue;
650
  // This is a brand new image.
651
  if ( preg_match( '/^image\/(jpeg|png|gif)/', $mimetype ) && empty( $already_optimized ) ) {
652
  $slide_paths[] = array(
653
+ 'path' => ewww_image_optimizer_relative_path_remove( $path ),
654
  'orig_size' => $image_size,
655
  );
656
  // This is a changed image.
681
  $upload_dir = wp_upload_dir();
682
  // Retrieve the path of the upload folder.
683
  $upload_path = $upload_dir['basedir'];
684
+ $this_month = date( 'm' );
685
+ $this_year = date( 'Y' );
686
  ewww_image_optimizer_image_scan( "$upload_path/$this_year/$this_month/", $started );
687
  if ( class_exists( 'DateTime' ) ) {
688
  $date = new DateTime();
689
  $date->sub( new DateInterval( 'P1M' ) );
690
+ $last_year = $date->format( 'Y' );
691
  $last_month = $date->format( 'm' );
692
  ewww_image_optimizer_image_scan( "$upload_path/$last_year/$last_month/", $started );
693
  }
704
  /* translators: %d: number of images */
705
  $ready_msg = sprintf( esc_html( _n( 'There is %d image ready to optimize.', 'There are %d images ready to optimize.', $image_count, 'ewww-image-optimizer' ) ), $image_count )
706
  . ' <a href="http://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>';
707
+ ewwwio_ob_clean();
708
  die( json_encode( array(
709
+ 'ready' => $image_count,
710
  'message' => $ready_msg,
711
  ) ) );
712
  }
724
  // Verify that an authorized user has started the optimizer.
725
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
726
  if ( ! $auto && ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) ) {
727
+ ewwwio_ob_clean();
728
+ die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
729
  }
730
  $stored_last = get_option( 'ewww_image_optimizer_aux_last' );
731
  update_option( 'ewww_image_optimizer_aux_last', array( time(), $stored_last[1] ) );
732
  // All done, so we can update the bulk options with empty values.
733
  update_option( 'ewww_image_optimizer_aux_resume', '' );
734
  if ( ! $auto ) {
735
+ ewwwio_ob_clean();
736
  // And let the user know we are done.
737
  echo '<p><b>' . esc_html__( 'Finished', 'ewww-image-optimizer' ) . '</b></p>';
738
  ewwwio_memory( __FUNCTION__ );
bulk.php CHANGED
@@ -31,13 +31,13 @@ function ewww_image_optimizer_bulk_preview() {
31
  $resume = get_option( 'ewww_image_optimizer_bulk_resume' );
32
  if ( empty( $resume ) ) {
33
  $fullsize_count = ewww_image_optimizer_count_optimized( 'media' );
34
- $button_text = esc_attr__( 'Start optimizing', 'ewww-image-optimizer' );
35
  } elseif ( 'scanning' == $resume ) {
36
  $fullsize_count = ewww_image_optimizer_count_optimized( 'media' );
37
- $button_text = esc_attr__( 'Start optimizing', 'ewww-image-optimizer' );
38
  } else {
39
  $fullsize_count = ewww_image_optimizer_aux_images_table_count_pending();
40
- $button_text = esc_attr__( 'Resume previous optimization', 'ewww-image-optimizer' );
41
  }
42
  // Create the html for the bulk optimize form and status divs.
43
  ewww_image_optimizer_bulk_head_output();
@@ -49,9 +49,14 @@ function ewww_image_optimizer_bulk_preview() {
49
  /* translators: %d: number of images */
50
  echo '<p class="ewww-media-info ewww-bulk-info">' . sprintf( esc_html( _n( 'There is %d image ready to optimize.', 'There are %d images ready to optimize.', $fullsize_count, 'ewww-image-optimizer' ) ), $fullsize_count ) . '</p>';
51
  } else {
52
- /* translators: %d: number of images */
53
- echo '<p class="ewww-media-info ewww-bulk-info">' . sprintf( esc_html( _n( '%1$d image in the Media Library has been selected.', '%1$d images in the Media Library have been selected.', $fullsize_count, 'ewww-image-optimizer' ) ), $fullsize_count ) . '<br />' .
54
- esc_html__( 'The active theme, BuddyPress, WP Symposium, and folders that you have configured will also be scanned for unoptimized images.', 'ewww-image-optimizer' ) . '</p>';
 
 
 
 
 
55
  }
56
  ewww_image_optimizer_bulk_action_output( $button_text, $fullsize_count, $resume );
57
  }
@@ -69,7 +74,7 @@ function ewww_image_optimizer_bulk_preview() {
69
  */
70
  function ewww_image_optimizer_bulk_head_output() {
71
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
72
- $delay = ewww_image_optimizer_get_option( 'ewww_image_optimizer_delay' ) ? (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_delay' ) : 0;
73
  ?>
74
  <div id="ewww-bulk-loading">
75
  <p id="ewww-loading" class="ewww-bulk-info" style="display:none"><?php esc_html_e( 'Importing', 'ewww-image-optimizer' ); ?>&nbsp;<img src='<?php echo $loading_image; ?>' /></p>
@@ -103,8 +108,8 @@ function ewww_image_optimizer_bulk_head_output() {
103
  </div>
104
  </div>
105
  <form class="ewww-bulk-form">
106
- <p><?php esc_html_e( 'Previously optimized images will be skipped by default.', 'ewww-image-optimizer' ); ?></p>
107
- <p><label for="ewww-force" style="font-weight: bold"><?php esc_html_e( 'Force re-optimize', 'ewww-image-optimizer' ); ?></label>&emsp;<input type="checkbox" id="ewww-force" name="ewww-force"></p>
108
  <p><label for="ewww-delay" style="font-weight: bold"><?php esc_html_e( 'Choose how long to pause between images (in seconds, 0 = disabled)', 'ewww-image-optimizer' ); ?></label>&emsp;<input type="text" id="ewww-delay" name="ewww-delay" value="<?php echo $delay; ?>"></p>
109
  <div id="ewww-delay-slider" style="width:50%"></div>
110
  </form>
@@ -124,11 +129,11 @@ function ewww_image_optimizer_bulk_action_output( $button_text, $fullsize_count,
124
  /* translators: %d: number of images */
125
  $scanning_starter_message = sprintf( esc_html__( 'Stage 1, %d images left to scan.', 'ewww-image-optimizer' ), $fullsize_count );
126
  if ( 'true' == $resume ) {
127
- $scan_hide = 'style="display:none"';
128
  $start_hide = '';
129
  } else {
130
  $start_hide = 'style="display:none"';
131
- $scan_hide = '';
132
 
133
  }
134
  ?>
@@ -197,29 +202,28 @@ function ewww_image_optimizer_reduce_query_count( $max_query ) {
197
  */
198
  function ewww_image_optimizer_count_optimized( $gallery ) {
199
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
200
- global $wpdb;
201
- $full_count = 0;
202
- $unoptimized_full = 0;
203
- $unoptimized_re = 0;
204
- $resize_count = 0;
205
- $attachment_query = '';
206
  ewwwio_debug_message( "scanning for $gallery" );
207
- // Retrieve the time when the counting starts.
208
- $started = microtime( true );
209
- $max_query = apply_filters( 'ewww_image_optimizer_count_optimized_queries', 4000 );
210
- $max_query = (int) $max_query;
 
 
 
 
 
211
  $attachment_query_count = 0;
212
  switch ( $gallery ) {
213
  case 'media':
214
- $ids = array();
215
  $resume = get_option( 'ewww_image_optimizer_bulk_resume' );
216
  // See if we were given attachment IDs to work with via GET/POST.
217
  if ( ! empty( $_REQUEST['ids'] ) || $resume ) {
218
  ewwwio_debug_message( 'we have received attachment ids via $_REQUEST' );
219
  // Retrieve the attachment IDs that were pre-loaded in the database.
220
  if ( 'scanning' == $resume ) {
221
- $finished = (array) get_option( 'ewww_image_optimizer_bulk_attachments' );
222
- $remaining = (array) get_option( 'ewww_image_optimizer_scanning_attachments' );
223
  $attachment_ids = array_merge( $finished, $remaining );
224
  } elseif ( $resume ) {
225
  // This shouldn't ever happen, but doesn't hurt to account for the use case, just in case something changes in the future.
@@ -250,15 +254,15 @@ function ewww_image_optimizer_count_optimized( $gallery ) {
250
  // Creating the 'registry' object for working with nextgen.
251
  $registry = C_Component_Registry::get_instance();
252
  // Creating a database storage object from the 'registry' object.
253
- $storage = $registry->get_utility( 'I_Gallery_Storage' );
254
  // Get an array of sizes available for the $image.
255
- $sizes = $storage->get_image_sizes();
256
  $offset = 0;
257
  while ( $attachments = $wpdb->get_col( "SELECT meta_data FROM $wpdb->nggpictures $attachment_query LIMIT $offset, $max_query" ) ) { // WPCS: unprepared SQL ok.
258
  foreach ( $attachments as $attachment ) {
259
  if ( class_exists( 'Ngg_Serializable' ) ) {
260
  $serializer = new Ngg_Serializable();
261
- $meta = $serializer->unserialize( $attachment );
262
  } else {
263
  $meta = unserialize( $attachment );
264
  }
@@ -280,11 +284,11 @@ function ewww_image_optimizer_count_optimized( $gallery ) {
280
  }
281
  }
282
  $full_count += count( $attachments );
283
- $offset += $max_query;
284
  if ( ! empty( $attachment_ids ) ) {
285
- $attachment_query = '';
286
  $attachment_query_count = 0;
287
- $offset = 0;
288
  while ( $attachment_ids && $attachment_query_count < $max_query ) {
289
  $attachment_query .= "'" . array_pop( $attachment_ids ) . "',";
290
  $attachment_query_count++;
@@ -328,11 +332,11 @@ function ewww_image_optimizer_count_optimized( $gallery ) {
328
  }
329
  }
330
  $full_count += count( $attachments );
331
- $offset += $max_query;
332
  if ( ! empty( $attachment_ids ) ) {
333
- $attachment_query = '';
334
  $attachment_query_count = 0;
335
- $offset = 0;
336
  while ( $attachment_ids && $attachment_query_count < $max_query ) {
337
  $attachment_query .= "'" . array_pop( $attachment_ids ) . "',";
338
  $attachment_query_count++;
@@ -393,7 +397,7 @@ function ewww_image_optimizer_bulk_script( $hook ) {
393
  ewww_image_optimizer_aux_images_convert();
394
  }
395
  // Check the 'bulk resume' option.
396
- $resume = get_option( 'ewww_image_optimizer_bulk_resume' );
397
  $scanning = get_option( 'ewww_image_optimizer_aux_resume' );
398
  if ( ! $resume && ! $scanning ) {
399
  update_option( 'ewww_image_optimizer_scanning_attachments', '', false );
@@ -418,7 +422,7 @@ function ewww_image_optimizer_bulk_script( $hook ) {
418
  $attachments = array();
419
  foreach ( $ids as $gid ) {
420
  ewwwio_debug_message( "gallery id: $gid" );
421
- $ims_images = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type = 'ims_image' AND post_mime_type LIKE '%%image%%' AND post_parent = %d ORDER BY ID DESC", $gid ) );
422
  $attachments = array_merge( $attachments, $ims_images );
423
  }
424
  } else {
@@ -450,26 +454,26 @@ function ewww_image_optimizer_bulk_script( $hook ) {
450
  // Submit a couple variables for our javascript to work with.
451
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
452
  wp_localize_script('ewwwbulkscript', 'ewww_vars', array(
453
- '_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-bulk' ),
454
- 'attachments' => ewww_image_optimizer_aux_images_table_count_pending(),
455
- 'image_count' => $image_count,
456
  /* translators: %d: number of images */
457
- 'count_string' => sprintf( esc_html__( '%d images', 'ewww-image-optimizer' ), $image_count ),
458
- 'scan_fail' => esc_html__( 'Operation timed out, you may need to increase the max_execution_time or memory_limit for PHP', 'ewww-image-optimizer' ),
459
- 'scan_incomplete' => esc_html__( 'Scan did not complete, will try again', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' />",
460
- 'operation_stopped' => esc_html__( 'Optimization stopped, reload page to resume.', 'ewww-image-optimizer' ),
461
  'operation_interrupted' => esc_html__( 'Operation Interrupted', 'ewww-image-optimizer' ),
462
- 'temporary_failure' => esc_html__( 'Temporary failure, attempts remaining:', 'ewww-image-optimizer' ),
463
- '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' ),
464
- 'bad_attachment' => esc_html__( 'Previous failure due to broken/missing metadata, skipped resizes for attachment:', 'ewww-image-optimizer' ),
465
- 'remove_failed' => esc_html__( 'Could not remove image from table.', 'ewww-image-optimizer' ),
466
  /* translators: used for Bulk Optimize progress bar, like so: Optimized 32/346 */
467
- 'optimized' => esc_html__( 'Optimized', 'ewww-image-optimizer' ),
468
- 'last_image_header' => esc_html__( 'Last Image Optimized', 'ewww-image-optimizer' ),
469
- 'time_remaining' => esc_html__( 'remaining', 'ewww-image-optimizer' ),
470
- 'original_restored' => esc_html__( 'Original Restored', 'ewww-image-optimizer' ),
471
- 'restoring' => '<p>' . esc_html__( 'Restoring', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' /></p>",
472
- 'bulk_fail_more' => '<a href="http://docs.ewww.io/article/39-bulk-optimizer-failure" target="_blank" data-beacon-article="596f84f72c7d3a73488b3ca7">' . esc_html__( 'more...', 'ewww-image-optimizer' ) . '</a>',
473
  ) );
474
  // Load the stylesheet for the jquery progressbar.
475
  wp_enqueue_style( 'jquery-ui-progressbar', plugins_url( '/includes/jquery-ui-1.10.1.custom.css', __FILE__ ) );
@@ -498,8 +502,8 @@ function ewww_image_optimizer_optimized_list() {
498
  } else {
499
  $ewwwdb = $wpdb;
500
  }
501
- $offset = 0;
502
- $max_query = (int) apply_filters( 'ewww_image_optimizer_count_optimized_queries', 4000 );
503
  $optimized_list = array();
504
  if ( defined( 'EWWW_IMAGE_OPTIMIZER_SCAN_MODE_B' ) && EWWW_IMAGE_OPTIMIZER_SCAN_MODE_B ) { // User manually enabled Plan B.
505
  ewwwio_debug_message( 'user chose low memory mode' );
@@ -521,11 +525,11 @@ function ewww_image_optimizer_optimized_list() {
521
  if ( ! empty( $optimized_list[ $optimized_path ] ) && ! empty( $optimized_list[ $optimized_path ]['id'] ) ) {
522
  $optimized = ewww_image_optimizer_remove_duplicate_records( array( $optimized_list[ $optimized_path ]['id'], $optimized['id'] ) );
523
  }
524
- $optimized_list[ $optimized_path ]['image_size'] = $optimized['image_size'];
525
- $optimized_list[ $optimized_path ]['id'] = $optimized['id'];
526
- $optimized_list[ $optimized_path ]['pending'] = $optimized['pending'];
527
  $optimized_list[ $optimized_path ]['attachment_id'] = $optimized['attachment_id'];
528
- $optimized_list[ $optimized_path ]['updated'] = $optimized['updated'];
529
  }
530
  ewwwio_memory( 'removed original records' );
531
  $offset += $max_query;
@@ -564,10 +568,11 @@ function ewww_image_optimizer_optimized_list() {
564
  */
565
  function ewww_image_optimizer_fetch_metadata_batch( $attachments_in ) {
566
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
567
- if ( ! preg_match( "/^[\d,']+$/", $attachments_in ) ) {
568
  ewwwio_debug_message( 'invalid attachments string' );
569
  return array();
570
  }
 
571
  global $wpdb;
572
  // Retrieve image attachment metadata from the database (in batches).
573
  $attachments = $wpdb->get_results( "SELECT metas.post_id,metas.meta_key,metas.meta_value,posts.post_mime_type FROM $wpdb->postmeta metas INNER JOIN $wpdb->posts posts ON posts.ID = metas.post_id WHERE (posts.post_mime_type LIKE '%%image%%' OR posts.post_mime_type LIKE '%%pdf%%') AND metas.post_id IN ($attachments_in)", ARRAY_A ); // WPCS: unprepared SQL ok.
@@ -619,6 +624,7 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
619
  if ( 'ewww-image-optimizer-cli' !== $hook && empty( $_REQUEST['ewww_scan'] ) ) {
620
  ewwwio_debug_message( 'bailing no cli' );
621
  ewww_image_optimizer_debug_log();
 
622
  die( json_encode( array(
623
  'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
624
  ) ) );
@@ -626,6 +632,7 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
626
  if ( ! empty( $_REQUEST['ewww_scan'] ) && ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) ) {
627
  ewwwio_debug_message( 'bailing no nonce' );
628
  ewww_image_optimizer_debug_log();
 
629
  die( json_encode( array(
630
  'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ),
631
  ) ) );
@@ -638,19 +645,19 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
638
  $ewwwdb = $wpdb;
639
  }
640
  global $optimized_list;
641
- $image_count = 0;
642
  $attachments_processed = 0;
643
- $attachment_query = '';
644
- $images = array();
645
- $attachment_images = array();
646
- $reset_images = array();
647
- $queued_ids = array();
648
- $field_formats = array(
649
- '%s', // path
650
- '%s', // gallery
651
- '%d', // orig_size
652
- '%d', // attachment_id
653
- '%s', // resize
654
  '%d', // pending.
655
  );
656
  ewwwio_debug_message( 'scanning for media attachments' );
@@ -658,7 +665,7 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
658
  set_transient( 'ewww_image_optimizer_no_scheduled_optimization', true, 60 * MINUTE_IN_SECONDS );
659
 
660
  // Retrieve the time when the scan starts.
661
- $started = microtime( true );
662
  $attachment_ids = get_option( 'ewww_image_optimizer_scanning_attachments' );
663
 
664
  if ( ! empty( $attachment_ids ) && count( $attachment_ids ) > 300 ) {
@@ -717,9 +724,10 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
717
  $selected_ids = array_splice( $attachment_ids, 0, $max_query );
718
  array_walk( $selected_ids, 'intval' );
719
  ewwwio_debug_message( 'selected items: ' . count( $selected_ids ) );
720
- $attachments_in = "'" . implode( "','", $selected_ids ) . "'";
721
  } else {
722
  ewwwio_debug_message( 'no array found' );
 
723
  die( json_encode( array(
724
  'error' => esc_html__( 'List of attachment IDs not found.', 'ewww-image-optimizer' ),
725
  ) ) );
@@ -728,7 +736,7 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
728
  $failsafe_selected_ids = $selected_ids;
729
 
730
  $attachment_meta = ewww_image_optimizer_fetch_metadata_batch( $attachments_in );
731
- $attachments_in = null;
732
 
733
  // If we just completed the first batch, check how much the memory usage increased.
734
  if ( empty( $estimated_batch_memory ) ) {
@@ -760,7 +768,7 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
760
  ewww_image_optimizer_debug_log();
761
  array_shift( $failsafe_selected_ids );
762
  clearstatcache();
763
- $pending = false;
764
  $remote_file = false;
765
  if ( ! empty( $attachment_meta[ $selected_id ]['tinypng'] ) ) {
766
  ewwwio_debug_message( "TinyPNG already compressed $selected_id" );
@@ -813,7 +821,9 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
813
  ewwwio_debug_message( "id: $selected_id and type: $mime" );
814
  ewww_image_optimizer_debug_log();
815
  $attached_file = ( ! empty( $attachment_meta[ $selected_id ]['_wp_attached_file'] ) ? $attachment_meta[ $selected_id ]['_wp_attached_file'] : '' );
 
816
  list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $selected_id, $attached_file, false );
 
817
  // Run a quick fix for as3cf files.
818
  if ( class_exists( 'Amazon_S3_And_CloudFront' ) && strpos( $file_path, 's3' ) === 0 ) {
819
  ewww_image_optimizer_check_table_as3cf( $meta, $selected_id, $file_path );
@@ -838,7 +848,7 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
838
  }
839
  ewww_image_optimizer_debug_log();
840
  $attachment_images['full'] = $file_path;
841
- $retina_path = ewww_image_optimizer_hidpi_optimize( $file_path, true );
842
  if ( $retina_path ) {
843
  $attachment_images['full-retina'] = $retina_path;
844
  }
@@ -847,7 +857,7 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
847
  if ( isset( $meta['sizes'] ) && ewww_image_optimizer_iterable( $meta['sizes'] ) ) {
848
  // Meta sizes don't contain a full path, so we calculate one.
849
  $base_ims_dir = trailingslashit( dirname( $file_path ) ) . '_resized/';
850
- $base_dir = trailingslashit( dirname( $file_path ) );
851
  // To keep track of the ones we have already processed.
852
  $processed = array();
853
  foreach ( $meta['sizes'] as $size => $data ) {
@@ -870,7 +880,7 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
870
  $ims_path = $base_ims_dir . $data['file'];
871
  if ( file_exists( $ims_path ) ) {
872
  // We reset base_dir, because base_dir potentially gets overwritten with base_ims_dir.
873
- $base_dir = trailingslashit( dirname( $file_path ) );
874
  $ims_temp_path = $base_dir . $data['file'];
875
  ewwwio_debug_message( "ims path: $ims_path" );
876
  if ( $file_path != $ims_temp_path && is_array( $optimized_list ) && isset( $optimized_list[ $ims_temp_path ] ) ) {
@@ -879,7 +889,7 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
879
  // Update our records so that we have the correct path going forward.
880
  $ewwwdb->update( $ewwwdb->ewwwio_images,
881
  array(
882
- 'path' => ewww_image_optimizer_relative_path_remove( $ims_path ),
883
  'updated' => $optimized_list[ $ims_temp_path ]['updated'],
884
  ),
885
  array(
@@ -921,7 +931,7 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
921
  }
922
  }
923
  // Store info on the sizes we've processed, so we can check the list for duplicate sizes.
924
- $processed[ $size ]['width'] = $data['width'];
925
  $processed[ $size ]['height'] = $data['height'];
926
  } // End foreach().
927
  } // End if().
@@ -930,7 +940,7 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
930
  // Queue sizes from a custom theme.
931
  if ( isset( $meta['image_meta']['resized_images'] ) && ewww_image_optimizer_iterable( $meta['image_meta']['resized_images'] ) ) {
932
  $imagemeta_resize_pathinfo = pathinfo( $file_path );
933
- $imagemeta_resize_path = '';
934
  foreach ( $meta['image_meta']['resized_images'] as $index => $imagemeta_resize ) {
935
  $imagemeta_resize_path = $imagemeta_resize_pathinfo['dirname'] . '/' . $imagemeta_resize_pathinfo['filename'] . '-' . $imagemeta_resize . '.' . $imagemeta_resize_pathinfo['extension'];
936
  if ( is_file( $imagemeta_resize_path ) ) {
@@ -943,7 +953,7 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
943
  // Queue size from another custom theme.
944
  if ( isset( $meta['custom_sizes'] ) && ewww_image_optimizer_iterable( $meta['custom_sizes'] ) ) {
945
  $custom_sizes_pathinfo = pathinfo( $file_path );
946
- $custom_size_path = '';
947
  foreach ( $meta['custom_sizes'] as $dimensions => $custom_size ) {
948
  $custom_size_path = $custom_sizes_pathinfo['dirname'] . '/' . $custom_size['file'];
949
  if ( is_file( $custom_size_path ) ) {
@@ -977,7 +987,7 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
977
  } elseif ( is_array( $optimized_list ) && isset( $optimized_list[ $file_path ] ) ) {
978
  $already_optimized = $optimized_list[ $file_path ];
979
  }
980
- if ( $already_optimized && ( ! $remote_file || ! empty( $_REQUEST['ewww_force'] ) ) ) {
981
  ewwwio_debug_message( 'potential match found' );
982
  ewww_image_optimizer_debug_log();
983
  if ( ! empty( $already_optimized['pending'] ) ) {
@@ -1022,11 +1032,11 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
1022
  $ewwwdb->update(
1023
  $ewwwdb->ewwwio_images,
1024
  array(
1025
- 'pending' => 1,
1026
  'attachment_id' => $selected_id,
1027
- 'gallery' => 'media',
1028
- 'resize' => $size,
1029
- 'updated' => $already_optimized['updated'],
1030
  ),
1031
  array(
1032
  'id' => $already_optimized['id'],
@@ -1077,12 +1087,12 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
1077
  }
1078
  ewww_image_optimizer_debug_log();
1079
  $images[ $file_path ] = array(
1080
- 'path' => ewww_image_optimizer_relative_path_remove( $utf8_file_path ),
1081
- 'gallery' => 'media',
1082
- 'orig_size' => $image_size,
1083
  'attachment_id' => $selected_id,
1084
- 'resize' => $size,
1085
- 'pending' => 1,
1086
  );
1087
  $image_count++;
1088
  ewwwio_debug_message( 'image added to $images queue' );
@@ -1178,18 +1188,20 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
1178
  return;
1179
  }
1180
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
1181
- $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' ) : '' );
1182
  if ( count( $attachment_ids ) ) {
 
1183
  die( json_encode( array(
1184
  /* translators: %d: number of images */
1185
- 'remaining' => sprintf( esc_html__( 'Stage 1, %d images left to scan.', 'ewww-image-optimizer' ), count( $attachment_ids ) ) . "&nbsp;<img src='$loading_image' />",
1186
- 'notice' => $notice,
1187
  'bad_attachment' => $bad_attachment,
1188
  ) ) );
1189
  } else {
 
1190
  die( json_encode( array(
1191
- 'remaining' => esc_html__( 'Stage 2, please wait.', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' />",
1192
- 'notice' => $notice,
1193
  'bad_attachment' => $bad_attachment,
1194
  ) ) );
1195
  }
@@ -1202,8 +1214,10 @@ function ewww_image_optimizer_bulk_quota_update() {
1202
  // Verify that an authorized user has made the request.
1203
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
1204
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
 
1205
  die( esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) );
1206
  }
 
1207
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
1208
  echo esc_html__( 'Image credits available:', 'ewww-image-optimizer' ) . ' ' . ewww_image_optimizer_cloud_quota();
1209
  }
@@ -1218,12 +1232,13 @@ function ewww_image_optimizer_bulk_initialize() {
1218
  // Verify that an authorized user has made the request.
1219
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
1220
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
 
1221
  die( json_encode( array(
1222
  'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ),
1223
  ) ) );
1224
  }
1225
  session_write_close();
1226
- $output = array();
1227
  $attachments = get_option( 'ewww_image_optimizer_bulk_attachments' );
1228
  if ( ! is_array( $attachments ) && ! empty( $attachments ) ) {
1229
  $attachments = unserialize( $attachments );
@@ -1240,14 +1255,16 @@ function ewww_image_optimizer_bulk_initialize() {
1240
  ewww_image_optimizer_aux_images_table_count_pending_media()
1241
  ) {
1242
  if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
 
1243
  die( json_encode( array(
1244
  'error' => esc_html__( 'Error retrieving list of images', 'ewww-image-optimizer' ),
1245
- 'data' => print_r( $attachments, true ),
1246
  ) ) );
1247
  } else {
 
1248
  die( json_encode( array(
1249
  'error' => esc_html__( 'Error retrieving list of images', 'ewww-image-optimizer' ),
1250
- 'data' => 'print_r disabled',
1251
  ) ) );
1252
  }
1253
  }
@@ -1257,7 +1274,7 @@ function ewww_image_optimizer_bulk_initialize() {
1257
  $attachment = (int) array_shift( $attachments );
1258
  ewwwio_debug_message( "first image: $attachment" );
1259
  $first_image = new EWWW_Image( $attachment, 'media' );
1260
- $file = $first_image->file;
1261
  // Generate the WP spinner image for display.
1262
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
1263
  // Let the user know that we are beginning.
@@ -1268,6 +1285,7 @@ function ewww_image_optimizer_bulk_initialize() {
1268
  }
1269
  $output['start_time'] = time();
1270
  ewwwio_memory( __FUNCTION__ );
 
1271
  die( json_encode( $output ) );
1272
  }
1273
 
@@ -1291,21 +1309,21 @@ function ewww_image_optimizer_bulk_counter_measures( $image ) {
1291
  if ( ! empty( $_REQUEST['ewww_error_counter'] ) ) {
1292
  $error_counter = (int) $_REQUEST['ewww_error_counter'];
1293
  if ( 30 != $error_counter ) {
1294
- $failed_file = get_transient( 'ewww_image_optimizer_failed_file' );
1295
  $previous_incomplete_file = get_transient( 'ewww_image_optimizer_bulk_current_image' );
1296
  if ( is_array( get_transient( 'ewww_image_optimizer_bulk_counter_measures' ) ) ) {
1297
  $previous_countermeasures = get_transient( 'ewww_image_optimizer_bulk_counter_measures' );
1298
  } else {
1299
  $previous_countermeasures = array(
1300
  'resize_existing' => false,
1301
- 'png50' => false,
1302
- 'png40' => false,
1303
- 'png2jpg' => false,
1304
- 'pngdefaults' => false,
1305
- 'jpg2png' => false,
1306
- 'jpg40' => false,
1307
- 'gif2png' => false,
1308
- 'pdf20' => false,
1309
  );
1310
  }
1311
  if ( $failed_file == $image->file || $previous_incomplete_file == $image->file ) {
@@ -1443,12 +1461,13 @@ function ewww_image_optimizer_bulk_counter_measures( $image ) {
1443
  function ewww_image_optimizer_bulk_loop( $hook = '', $delay = 0 ) {
1444
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1445
  global $ewww_defer;
1446
- $ewww_defer = false;
1447
- $output = array();
1448
  $time_adjustment = 0;
1449
  // Verify that an authorized user has started the optimizer.
1450
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
1451
  if ( 'ewww-image-optimizer-cli' !== $hook && ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) ) {
 
1452
  die( json_encode( array(
1453
  'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ),
1454
  ) ) );
@@ -1477,20 +1496,21 @@ function ewww_image_optimizer_bulk_loop( $hook = '', $delay = 0 ) {
1477
  }
1478
  $image = new EWWW_Image( $attachment, 'media' );
1479
  if ( ! $image->file ) {
 
1480
  die( json_encode( array(
1481
- 'done' => 1,
1482
  'completed' => 0,
1483
  ) ) );
1484
  }
1485
 
1486
- $output['results'] = '';
1487
  $output['completed'] = 0;
1488
  while ( $output['completed'] < $batch_image_limit && $image->file && microtime( true ) - $started + $time_adjustment < apply_filters( 'ewww_image_optimizer_timeout', 15 ) ) {
1489
  $output['completed']++;
1490
  $meta = false;
1491
  // See if the image needs fetching from a CDN.
1492
  if ( ! is_file( $image->file ) ) {
1493
- $meta = wp_get_attachment_metadata( $image->attachment_id );
1494
  $file_path = ewww_image_optimizer_remote_fetch( $image->attachment_id, $meta );
1495
  unset( $meta );
1496
  if ( ! $file_path ) {
@@ -1517,7 +1537,7 @@ function ewww_image_optimizer_bulk_loop( $hook = '', $delay = 0 ) {
1517
  }
1518
  $new_dimensions = ewww_image_optimizer_resize_upload( $image->file );
1519
  if ( is_array( $new_dimensions ) ) {
1520
- $meta['width'] = $new_dimensions[0];
1521
  $meta['height'] = $new_dimensions[1];
1522
  }
1523
  }
@@ -1528,6 +1548,7 @@ function ewww_image_optimizer_bulk_loop( $hook = '', $delay = 0 ) {
1528
  $output['error'] = esc_html__( 'License Exceeded', 'ewww-image-optimizer' );
1529
  delete_transient( 'ewww_image_optimizer_bulk_counter_measures' );
1530
  delete_transient( 'ewww_image_optimizer_bulk_current_image' );
 
1531
  die( json_encode( $output ) );
1532
  }
1533
  // Delete a pending record if the optimization failed for whatever reason.
@@ -1549,9 +1570,9 @@ function ewww_image_optimizer_bulk_loop( $hook = '', $delay = 0 ) {
1549
  if ( $converted ) {
1550
  $image->increment = $converted;
1551
  }
1552
- $image->file = $file;
1553
  $image->converted = $original;
1554
- $meta['file'] = trailingslashit( dirname( $meta['file'] ) ) . basename( $file );
1555
  $image->update_converted_attachment( $meta );
1556
  $meta = $image->convert_sizes( $meta );
1557
  }
@@ -1590,7 +1611,7 @@ function ewww_image_optimizer_bulk_loop( $hook = '', $delay = 0 ) {
1590
  }
1591
  $next_image = new EWWW_Image( $attachment, 'media' );
1592
  }
1593
- $image = $next_image;
1594
  $time_adjustment = $image->time_estimate();
1595
  } // End while().
1596
 
@@ -1637,6 +1658,7 @@ function ewww_image_optimizer_bulk_loop( $hook = '', $delay = 0 ) {
1637
  return true;
1638
  }
1639
  $output['current_time'] = time();
 
1640
  die( json_encode( $output ) );
1641
  }
1642
 
@@ -1647,6 +1669,7 @@ function ewww_image_optimizer_bulk_cleanup() {
1647
  // Verify that an authorized user has started the optimizer.
1648
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
1649
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
 
1650
  die( '<p><b>' . esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) . '</b></p>' );
1651
  }
1652
  // All done, so we can update the bulk options with empty values.
@@ -1656,6 +1679,7 @@ function ewww_image_optimizer_bulk_cleanup() {
1656
  delete_transient( 'ewww_image_optimizer_skip_aux' );
1657
  // Let the user know we are done.
1658
  ewwwio_memory( __FUNCTION__ );
 
1659
  die( '<p><b>' . esc_html__( 'Finished', 'ewww-image-optimizer' ) . '</b> - <a href="upload.php">' . esc_html__( 'Return to Media Library', 'ewww-image-optimizer' ) . '</a></p>' );
1660
  }
1661
 
31
  $resume = get_option( 'ewww_image_optimizer_bulk_resume' );
32
  if ( empty( $resume ) ) {
33
  $fullsize_count = ewww_image_optimizer_count_optimized( 'media' );
34
+ $button_text = esc_attr__( 'Start optimizing', 'ewww-image-optimizer' );
35
  } elseif ( 'scanning' == $resume ) {
36
  $fullsize_count = ewww_image_optimizer_count_optimized( 'media' );
37
+ $button_text = esc_attr__( 'Start optimizing', 'ewww-image-optimizer' );
38
  } else {
39
  $fullsize_count = ewww_image_optimizer_aux_images_table_count_pending();
40
+ $button_text = esc_attr__( 'Resume previous optimization', 'ewww-image-optimizer' );
41
  }
42
  // Create the html for the bulk optimize form and status divs.
43
  ewww_image_optimizer_bulk_head_output();
49
  /* translators: %d: number of images */
50
  echo '<p class="ewww-media-info ewww-bulk-info">' . sprintf( esc_html( _n( 'There is %d image ready to optimize.', 'There are %d images ready to optimize.', $fullsize_count, 'ewww-image-optimizer' ) ), $fullsize_count ) . '</p>';
51
  } else {
52
+ if ( ! empty( $_REQUEST['ids'] ) && ( preg_match( '/^[\d,]+$/', $_REQUEST['ids'] ) || is_numeric( $_REQUEST['ids'] ) ) ) {
53
+ /* translators: %d: number of images */
54
+ echo '<p class="ewww-media-info ewww-bulk-info">' . sprintf( esc_html( _n( '%1$d image in the Media Library has been selected.', '%1$d images in the Media Library have been selected.', $fullsize_count, 'ewww-image-optimizer' ) ), $fullsize_count ) . '</p>';
55
+ } else {
56
+ /* translators: %d: number of images */
57
+ echo '<p class="ewww-media-info ewww-bulk-info">' . sprintf( esc_html( _n( '%1$d image in the Media Library has been selected.', '%1$d images in the Media Library have been selected.', $fullsize_count, 'ewww-image-optimizer' ) ), $fullsize_count ) . '<br />' .
58
+ esc_html__( 'The active theme, BuddyPress, WP Symposium, and folders that you have configured will also be scanned for unoptimized images.', 'ewww-image-optimizer' ) . '</p>';
59
+ }
60
  }
61
  ewww_image_optimizer_bulk_action_output( $button_text, $fullsize_count, $resume );
62
  }
74
  */
75
  function ewww_image_optimizer_bulk_head_output() {
76
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
77
+ $delay = ewww_image_optimizer_get_option( 'ewww_image_optimizer_delay' ) ? (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_delay' ) : 0;
78
  ?>
79
  <div id="ewww-bulk-loading">
80
  <p id="ewww-loading" class="ewww-bulk-info" style="display:none"><?php esc_html_e( 'Importing', 'ewww-image-optimizer' ); ?>&nbsp;<img src='<?php echo $loading_image; ?>' /></p>
108
  </div>
109
  </div>
110
  <form class="ewww-bulk-form">
111
+ <p><label for="ewww-force" style="font-weight: bold"><?php esc_html_e( 'Force re-optimize', 'ewww-image-optimizer' ); ?></label>&emsp;<input type="checkbox" id="ewww-force" name="ewww-force">
112
+ &nbsp;<?php esc_html_e( 'Previously optimized images will be skipped by default, check this box before scanning to override.', 'ewww-image-optimizer' ); ?></p>
113
  <p><label for="ewww-delay" style="font-weight: bold"><?php esc_html_e( 'Choose how long to pause between images (in seconds, 0 = disabled)', 'ewww-image-optimizer' ); ?></label>&emsp;<input type="text" id="ewww-delay" name="ewww-delay" value="<?php echo $delay; ?>"></p>
114
  <div id="ewww-delay-slider" style="width:50%"></div>
115
  </form>
129
  /* translators: %d: number of images */
130
  $scanning_starter_message = sprintf( esc_html__( 'Stage 1, %d images left to scan.', 'ewww-image-optimizer' ), $fullsize_count );
131
  if ( 'true' == $resume ) {
132
+ $scan_hide = 'style="display:none"';
133
  $start_hide = '';
134
  } else {
135
  $start_hide = 'style="display:none"';
136
+ $scan_hide = '';
137
 
138
  }
139
  ?>
202
  */
203
  function ewww_image_optimizer_count_optimized( $gallery ) {
204
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
 
 
 
 
 
 
205
  ewwwio_debug_message( "scanning for $gallery" );
206
+ global $wpdb;
207
+ $full_count = 0;
208
+ $unoptimized_full = 0;
209
+ $unoptimized_re = 0;
210
+ $resize_count = 0;
211
+ $attachment_query = '';
212
+ $started = microtime( true ); // Retrieve the time when the counting starts.
213
+ $max_query = apply_filters( 'ewww_image_optimizer_count_optimized_queries', 4000 );
214
+ $max_query = (int) $max_query;
215
  $attachment_query_count = 0;
216
  switch ( $gallery ) {
217
  case 'media':
218
+ $ids = array();
219
  $resume = get_option( 'ewww_image_optimizer_bulk_resume' );
220
  // See if we were given attachment IDs to work with via GET/POST.
221
  if ( ! empty( $_REQUEST['ids'] ) || $resume ) {
222
  ewwwio_debug_message( 'we have received attachment ids via $_REQUEST' );
223
  // Retrieve the attachment IDs that were pre-loaded in the database.
224
  if ( 'scanning' == $resume ) {
225
+ $finished = (array) get_option( 'ewww_image_optimizer_bulk_attachments' );
226
+ $remaining = (array) get_option( 'ewww_image_optimizer_scanning_attachments' );
227
  $attachment_ids = array_merge( $finished, $remaining );
228
  } elseif ( $resume ) {
229
  // This shouldn't ever happen, but doesn't hurt to account for the use case, just in case something changes in the future.
254
  // Creating the 'registry' object for working with nextgen.
255
  $registry = C_Component_Registry::get_instance();
256
  // Creating a database storage object from the 'registry' object.
257
+ $storage = $registry->get_utility( 'I_Gallery_Storage' );
258
  // Get an array of sizes available for the $image.
259
+ $sizes = $storage->get_image_sizes();
260
  $offset = 0;
261
  while ( $attachments = $wpdb->get_col( "SELECT meta_data FROM $wpdb->nggpictures $attachment_query LIMIT $offset, $max_query" ) ) { // WPCS: unprepared SQL ok.
262
  foreach ( $attachments as $attachment ) {
263
  if ( class_exists( 'Ngg_Serializable' ) ) {
264
  $serializer = new Ngg_Serializable();
265
+ $meta = $serializer->unserialize( $attachment );
266
  } else {
267
  $meta = unserialize( $attachment );
268
  }
284
  }
285
  }
286
  $full_count += count( $attachments );
287
+ $offset += $max_query;
288
  if ( ! empty( $attachment_ids ) ) {
289
+ $attachment_query = '';
290
  $attachment_query_count = 0;
291
+ $offset = 0;
292
  while ( $attachment_ids && $attachment_query_count < $max_query ) {
293
  $attachment_query .= "'" . array_pop( $attachment_ids ) . "',";
294
  $attachment_query_count++;
332
  }
333
  }
334
  $full_count += count( $attachments );
335
+ $offset += $max_query;
336
  if ( ! empty( $attachment_ids ) ) {
337
+ $attachment_query = '';
338
  $attachment_query_count = 0;
339
+ $offset = 0;
340
  while ( $attachment_ids && $attachment_query_count < $max_query ) {
341
  $attachment_query .= "'" . array_pop( $attachment_ids ) . "',";
342
  $attachment_query_count++;
397
  ewww_image_optimizer_aux_images_convert();
398
  }
399
  // Check the 'bulk resume' option.
400
+ $resume = get_option( 'ewww_image_optimizer_bulk_resume' );
401
  $scanning = get_option( 'ewww_image_optimizer_aux_resume' );
402
  if ( ! $resume && ! $scanning ) {
403
  update_option( 'ewww_image_optimizer_scanning_attachments', '', false );
422
  $attachments = array();
423
  foreach ( $ids as $gid ) {
424
  ewwwio_debug_message( "gallery id: $gid" );
425
+ $ims_images = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type = 'ims_image' AND post_mime_type LIKE %s AND post_parent = %d ORDER BY ID DESC", '%image%', $gid ) );
426
  $attachments = array_merge( $attachments, $ims_images );
427
  }
428
  } else {
454
  // Submit a couple variables for our javascript to work with.
455
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
456
  wp_localize_script('ewwwbulkscript', 'ewww_vars', array(
457
+ '_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-bulk' ),
458
+ 'attachments' => ewww_image_optimizer_aux_images_table_count_pending(),
459
+ 'image_count' => $image_count,
460
  /* translators: %d: number of images */
461
+ 'count_string' => sprintf( esc_html__( '%d images', 'ewww-image-optimizer' ), $image_count ),
462
+ 'scan_fail' => esc_html__( 'Operation timed out, you may need to increase the max_execution_time or memory_limit for PHP', 'ewww-image-optimizer' ),
463
+ 'scan_incomplete' => esc_html__( 'Scan did not complete, will try again', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' />",
464
+ 'operation_stopped' => esc_html__( 'Optimization stopped, reload page to resume.', 'ewww-image-optimizer' ),
465
  'operation_interrupted' => esc_html__( 'Operation Interrupted', 'ewww-image-optimizer' ),
466
+ 'temporary_failure' => esc_html__( 'Temporary failure, attempts remaining:', 'ewww-image-optimizer' ),
467
+ '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' ),
468
+ 'bad_attachment' => esc_html__( 'Previous failure due to broken/missing metadata, skipped resizes for attachment:', 'ewww-image-optimizer' ),
469
+ 'remove_failed' => esc_html__( 'Could not remove image from table.', 'ewww-image-optimizer' ),
470
  /* translators: used for Bulk Optimize progress bar, like so: Optimized 32/346 */
471
+ 'optimized' => esc_html__( 'Optimized', 'ewww-image-optimizer' ),
472
+ 'last_image_header' => esc_html__( 'Last Image Optimized', 'ewww-image-optimizer' ),
473
+ 'time_remaining' => esc_html__( 'remaining', 'ewww-image-optimizer' ),
474
+ 'original_restored' => esc_html__( 'Original Restored', 'ewww-image-optimizer' ),
475
+ 'restoring' => '<p>' . esc_html__( 'Restoring', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' /></p>",
476
+ 'bulk_fail_more' => '<a href="http://docs.ewww.io/article/39-bulk-optimizer-failure" target="_blank" data-beacon-article="596f84f72c7d3a73488b3ca7">' . esc_html__( 'more...', 'ewww-image-optimizer' ) . '</a>',
477
  ) );
478
  // Load the stylesheet for the jquery progressbar.
479
  wp_enqueue_style( 'jquery-ui-progressbar', plugins_url( '/includes/jquery-ui-1.10.1.custom.css', __FILE__ ) );
502
  } else {
503
  $ewwwdb = $wpdb;
504
  }
505
+ $offset = 0;
506
+ $max_query = (int) apply_filters( 'ewww_image_optimizer_count_optimized_queries', 4000 );
507
  $optimized_list = array();
508
  if ( defined( 'EWWW_IMAGE_OPTIMIZER_SCAN_MODE_B' ) && EWWW_IMAGE_OPTIMIZER_SCAN_MODE_B ) { // User manually enabled Plan B.
509
  ewwwio_debug_message( 'user chose low memory mode' );
525
  if ( ! empty( $optimized_list[ $optimized_path ] ) && ! empty( $optimized_list[ $optimized_path ]['id'] ) ) {
526
  $optimized = ewww_image_optimizer_remove_duplicate_records( array( $optimized_list[ $optimized_path ]['id'], $optimized['id'] ) );
527
  }
528
+ $optimized_list[ $optimized_path ]['image_size'] = $optimized['image_size'];
529
+ $optimized_list[ $optimized_path ]['id'] = $optimized['id'];
530
+ $optimized_list[ $optimized_path ]['pending'] = $optimized['pending'];
531
  $optimized_list[ $optimized_path ]['attachment_id'] = $optimized['attachment_id'];
532
+ $optimized_list[ $optimized_path ]['updated'] = $optimized['updated'];
533
  }
534
  ewwwio_memory( 'removed original records' );
535
  $offset += $max_query;
568
  */
569
  function ewww_image_optimizer_fetch_metadata_batch( $attachments_in ) {
570
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
571
+ if ( ! preg_match( '/^[\d,]+$/', $attachments_in ) ) {
572
  ewwwio_debug_message( 'invalid attachments string' );
573
  return array();
574
  }
575
+ ewwwio_debug_message( 'attachment query length: ' . strlen( $attachments_in ) );
576
  global $wpdb;
577
  // Retrieve image attachment metadata from the database (in batches).
578
  $attachments = $wpdb->get_results( "SELECT metas.post_id,metas.meta_key,metas.meta_value,posts.post_mime_type FROM $wpdb->postmeta metas INNER JOIN $wpdb->posts posts ON posts.ID = metas.post_id WHERE (posts.post_mime_type LIKE '%%image%%' OR posts.post_mime_type LIKE '%%pdf%%') AND metas.post_id IN ($attachments_in)", ARRAY_A ); // WPCS: unprepared SQL ok.
624
  if ( 'ewww-image-optimizer-cli' !== $hook && empty( $_REQUEST['ewww_scan'] ) ) {
625
  ewwwio_debug_message( 'bailing no cli' );
626
  ewww_image_optimizer_debug_log();
627
+ ewwwio_ob_clean();
628
  die( json_encode( array(
629
  'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
630
  ) ) );
632
  if ( ! empty( $_REQUEST['ewww_scan'] ) && ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) ) {
633
  ewwwio_debug_message( 'bailing no nonce' );
634
  ewww_image_optimizer_debug_log();
635
+ ewwwio_ob_clean();
636
  die( json_encode( array(
637
  'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ),
638
  ) ) );
645
  $ewwwdb = $wpdb;
646
  }
647
  global $optimized_list;
648
+ $image_count = 0;
649
  $attachments_processed = 0;
650
+ $attachment_query = '';
651
+ $images = array();
652
+ $attachment_images = array();
653
+ $reset_images = array();
654
+ $queued_ids = array();
655
+ $field_formats = array(
656
+ '%s', // path.
657
+ '%s', // gallery.
658
+ '%d', // orig_size.
659
+ '%d', // attachment_id.
660
+ '%s', // resize.
661
  '%d', // pending.
662
  );
663
  ewwwio_debug_message( 'scanning for media attachments' );
665
  set_transient( 'ewww_image_optimizer_no_scheduled_optimization', true, 60 * MINUTE_IN_SECONDS );
666
 
667
  // Retrieve the time when the scan starts.
668
+ $started = microtime( true );
669
  $attachment_ids = get_option( 'ewww_image_optimizer_scanning_attachments' );
670
 
671
  if ( ! empty( $attachment_ids ) && count( $attachment_ids ) > 300 ) {
724
  $selected_ids = array_splice( $attachment_ids, 0, $max_query );
725
  array_walk( $selected_ids, 'intval' );
726
  ewwwio_debug_message( 'selected items: ' . count( $selected_ids ) );
727
+ $attachments_in = implode( ',', $selected_ids );
728
  } else {
729
  ewwwio_debug_message( 'no array found' );
730
+ ewwwio_ob_clean();
731
  die( json_encode( array(
732
  'error' => esc_html__( 'List of attachment IDs not found.', 'ewww-image-optimizer' ),
733
  ) ) );
736
  $failsafe_selected_ids = $selected_ids;
737
 
738
  $attachment_meta = ewww_image_optimizer_fetch_metadata_batch( $attachments_in );
739
+ $attachments_in = null;
740
 
741
  // If we just completed the first batch, check how much the memory usage increased.
742
  if ( empty( $estimated_batch_memory ) ) {
768
  ewww_image_optimizer_debug_log();
769
  array_shift( $failsafe_selected_ids );
770
  clearstatcache();
771
+ $pending = false;
772
  $remote_file = false;
773
  if ( ! empty( $attachment_meta[ $selected_id ]['tinypng'] ) ) {
774
  ewwwio_debug_message( "TinyPNG already compressed $selected_id" );
821
  ewwwio_debug_message( "id: $selected_id and type: $mime" );
822
  ewww_image_optimizer_debug_log();
823
  $attached_file = ( ! empty( $attachment_meta[ $selected_id ]['_wp_attached_file'] ) ? $attachment_meta[ $selected_id ]['_wp_attached_file'] : '' );
824
+
825
  list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $selected_id, $attached_file, false );
826
+
827
  // Run a quick fix for as3cf files.
828
  if ( class_exists( 'Amazon_S3_And_CloudFront' ) && strpos( $file_path, 's3' ) === 0 ) {
829
  ewww_image_optimizer_check_table_as3cf( $meta, $selected_id, $file_path );
848
  }
849
  ewww_image_optimizer_debug_log();
850
  $attachment_images['full'] = $file_path;
851
+ $retina_path = ewww_image_optimizer_hidpi_optimize( $file_path, true );
852
  if ( $retina_path ) {
853
  $attachment_images['full-retina'] = $retina_path;
854
  }
857
  if ( isset( $meta['sizes'] ) && ewww_image_optimizer_iterable( $meta['sizes'] ) ) {
858
  // Meta sizes don't contain a full path, so we calculate one.
859
  $base_ims_dir = trailingslashit( dirname( $file_path ) ) . '_resized/';
860
+ $base_dir = trailingslashit( dirname( $file_path ) );
861
  // To keep track of the ones we have already processed.
862
  $processed = array();
863
  foreach ( $meta['sizes'] as $size => $data ) {
880
  $ims_path = $base_ims_dir . $data['file'];
881
  if ( file_exists( $ims_path ) ) {
882
  // We reset base_dir, because base_dir potentially gets overwritten with base_ims_dir.
883
+ $base_dir = trailingslashit( dirname( $file_path ) );
884
  $ims_temp_path = $base_dir . $data['file'];
885
  ewwwio_debug_message( "ims path: $ims_path" );
886
  if ( $file_path != $ims_temp_path && is_array( $optimized_list ) && isset( $optimized_list[ $ims_temp_path ] ) ) {
889
  // Update our records so that we have the correct path going forward.
890
  $ewwwdb->update( $ewwwdb->ewwwio_images,
891
  array(
892
+ 'path' => ewww_image_optimizer_relative_path_remove( $ims_path ),
893
  'updated' => $optimized_list[ $ims_temp_path ]['updated'],
894
  ),
895
  array(
931
  }
932
  }
933
  // Store info on the sizes we've processed, so we can check the list for duplicate sizes.
934
+ $processed[ $size ]['width'] = $data['width'];
935
  $processed[ $size ]['height'] = $data['height'];
936
  } // End foreach().
937
  } // End if().
940
  // Queue sizes from a custom theme.
941
  if ( isset( $meta['image_meta']['resized_images'] ) && ewww_image_optimizer_iterable( $meta['image_meta']['resized_images'] ) ) {
942
  $imagemeta_resize_pathinfo = pathinfo( $file_path );
943
+ $imagemeta_resize_path = '';
944
  foreach ( $meta['image_meta']['resized_images'] as $index => $imagemeta_resize ) {
945
  $imagemeta_resize_path = $imagemeta_resize_pathinfo['dirname'] . '/' . $imagemeta_resize_pathinfo['filename'] . '-' . $imagemeta_resize . '.' . $imagemeta_resize_pathinfo['extension'];
946
  if ( is_file( $imagemeta_resize_path ) ) {
953
  // Queue size from another custom theme.
954
  if ( isset( $meta['custom_sizes'] ) && ewww_image_optimizer_iterable( $meta['custom_sizes'] ) ) {
955
  $custom_sizes_pathinfo = pathinfo( $file_path );
956
+ $custom_size_path = '';
957
  foreach ( $meta['custom_sizes'] as $dimensions => $custom_size ) {
958
  $custom_size_path = $custom_sizes_pathinfo['dirname'] . '/' . $custom_size['file'];
959
  if ( is_file( $custom_size_path ) ) {
987
  } elseif ( is_array( $optimized_list ) && isset( $optimized_list[ $file_path ] ) ) {
988
  $already_optimized = $optimized_list[ $file_path ];
989
  }
990
+ if ( is_array( $already_optimized ) && ! empty( $already_optimized ) ) {
991
  ewwwio_debug_message( 'potential match found' );
992
  ewww_image_optimizer_debug_log();
993
  if ( ! empty( $already_optimized['pending'] ) ) {
1032
  $ewwwdb->update(
1033
  $ewwwdb->ewwwio_images,
1034
  array(
1035
+ 'pending' => 1,
1036
  'attachment_id' => $selected_id,
1037
+ 'gallery' => 'media',
1038
+ 'resize' => $size,
1039
+ 'updated' => $already_optimized['updated'],
1040
  ),
1041
  array(
1042
  'id' => $already_optimized['id'],
1087
  }
1088
  ewww_image_optimizer_debug_log();
1089
  $images[ $file_path ] = array(
1090
+ 'path' => ewww_image_optimizer_relative_path_remove( $utf8_file_path ),
1091
+ 'gallery' => 'media',
1092
+ 'orig_size' => $image_size,
1093
  'attachment_id' => $selected_id,
1094
+ 'resize' => $size,
1095
+ 'pending' => 1,
1096
  );
1097
  $image_count++;
1098
  ewwwio_debug_message( 'image added to $images queue' );
1188
  return;
1189
  }
1190
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
1191
+ $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' ) : '' );
1192
  if ( count( $attachment_ids ) ) {
1193
+ ewwwio_ob_clean();
1194
  die( json_encode( array(
1195
  /* translators: %d: number of images */
1196
+ 'remaining' => sprintf( esc_html__( 'Stage 1, %d images left to scan.', 'ewww-image-optimizer' ), count( $attachment_ids ) ) . "&nbsp;<img src='$loading_image' />",
1197
+ 'notice' => $notice,
1198
  'bad_attachment' => $bad_attachment,
1199
  ) ) );
1200
  } else {
1201
+ ewwwio_ob_clean();
1202
  die( json_encode( array(
1203
+ 'remaining' => esc_html__( 'Stage 2, please wait.', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' />",
1204
+ 'notice' => $notice,
1205
  'bad_attachment' => $bad_attachment,
1206
  ) ) );
1207
  }
1214
  // Verify that an authorized user has made the request.
1215
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
1216
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
1217
+ ewwwio_ob_clean();
1218
  die( esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) );
1219
  }
1220
+ ewwwio_ob_clean();
1221
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
1222
  echo esc_html__( 'Image credits available:', 'ewww-image-optimizer' ) . ' ' . ewww_image_optimizer_cloud_quota();
1223
  }
1232
  // Verify that an authorized user has made the request.
1233
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
1234
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
1235
+ ewwwio_ob_clean();
1236
  die( json_encode( array(
1237
  'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ),
1238
  ) ) );
1239
  }
1240
  session_write_close();
1241
+ $output = array();
1242
  $attachments = get_option( 'ewww_image_optimizer_bulk_attachments' );
1243
  if ( ! is_array( $attachments ) && ! empty( $attachments ) ) {
1244
  $attachments = unserialize( $attachments );
1255
  ewww_image_optimizer_aux_images_table_count_pending_media()
1256
  ) {
1257
  if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
1258
+ ewwwio_ob_clean();
1259
  die( json_encode( array(
1260
  'error' => esc_html__( 'Error retrieving list of images', 'ewww-image-optimizer' ),
1261
+ 'data' => print_r( $attachments, true ),
1262
  ) ) );
1263
  } else {
1264
+ ewwwio_ob_clean();
1265
  die( json_encode( array(
1266
  'error' => esc_html__( 'Error retrieving list of images', 'ewww-image-optimizer' ),
1267
+ 'data' => 'print_r disabled',
1268
  ) ) );
1269
  }
1270
  }
1274
  $attachment = (int) array_shift( $attachments );
1275
  ewwwio_debug_message( "first image: $attachment" );
1276
  $first_image = new EWWW_Image( $attachment, 'media' );
1277
+ $file = $first_image->file;
1278
  // Generate the WP spinner image for display.
1279
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
1280
  // Let the user know that we are beginning.
1285
  }
1286
  $output['start_time'] = time();
1287
  ewwwio_memory( __FUNCTION__ );
1288
+ ewwwio_ob_clean();
1289
  die( json_encode( $output ) );
1290
  }
1291
 
1309
  if ( ! empty( $_REQUEST['ewww_error_counter'] ) ) {
1310
  $error_counter = (int) $_REQUEST['ewww_error_counter'];
1311
  if ( 30 != $error_counter ) {
1312
+ $failed_file = get_transient( 'ewww_image_optimizer_failed_file' );
1313
  $previous_incomplete_file = get_transient( 'ewww_image_optimizer_bulk_current_image' );
1314
  if ( is_array( get_transient( 'ewww_image_optimizer_bulk_counter_measures' ) ) ) {
1315
  $previous_countermeasures = get_transient( 'ewww_image_optimizer_bulk_counter_measures' );
1316
  } else {
1317
  $previous_countermeasures = array(
1318
  'resize_existing' => false,
1319
+ 'png50' => false,
1320
+ 'png40' => false,
1321
+ 'png2jpg' => false,
1322
+ 'pngdefaults' => false,
1323
+ 'jpg2png' => false,
1324
+ 'jpg40' => false,
1325
+ 'gif2png' => false,
1326
+ 'pdf20' => false,
1327
  );
1328
  }
1329
  if ( $failed_file == $image->file || $previous_incomplete_file == $image->file ) {
1461
  function ewww_image_optimizer_bulk_loop( $hook = '', $delay = 0 ) {
1462
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1463
  global $ewww_defer;
1464
+ $ewww_defer = false;
1465
+ $output = array();
1466
  $time_adjustment = 0;
1467
  // Verify that an authorized user has started the optimizer.
1468
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
1469
  if ( 'ewww-image-optimizer-cli' !== $hook && ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) ) {
1470
+ ewwwio_ob_clean();
1471
  die( json_encode( array(
1472
  'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ),
1473
  ) ) );
1496
  }
1497
  $image = new EWWW_Image( $attachment, 'media' );
1498
  if ( ! $image->file ) {
1499
+ ewwwio_ob_clean();
1500
  die( json_encode( array(
1501
+ 'done' => 1,
1502
  'completed' => 0,
1503
  ) ) );
1504
  }
1505
 
1506
+ $output['results'] = '';
1507
  $output['completed'] = 0;
1508
  while ( $output['completed'] < $batch_image_limit && $image->file && microtime( true ) - $started + $time_adjustment < apply_filters( 'ewww_image_optimizer_timeout', 15 ) ) {
1509
  $output['completed']++;
1510
  $meta = false;
1511
  // See if the image needs fetching from a CDN.
1512
  if ( ! is_file( $image->file ) ) {
1513
+ $meta = wp_get_attachment_metadata( $image->attachment_id );
1514
  $file_path = ewww_image_optimizer_remote_fetch( $image->attachment_id, $meta );
1515
  unset( $meta );
1516
  if ( ! $file_path ) {
1537
  }
1538
  $new_dimensions = ewww_image_optimizer_resize_upload( $image->file );
1539
  if ( is_array( $new_dimensions ) ) {
1540
+ $meta['width'] = $new_dimensions[0];
1541
  $meta['height'] = $new_dimensions[1];
1542
  }
1543
  }
1548
  $output['error'] = esc_html__( 'License Exceeded', 'ewww-image-optimizer' );
1549
  delete_transient( 'ewww_image_optimizer_bulk_counter_measures' );
1550
  delete_transient( 'ewww_image_optimizer_bulk_current_image' );
1551
+ ewwwio_ob_clean();
1552
  die( json_encode( $output ) );
1553
  }
1554
  // Delete a pending record if the optimization failed for whatever reason.
1570
  if ( $converted ) {
1571
  $image->increment = $converted;
1572
  }
1573
+ $image->file = $file;
1574
  $image->converted = $original;
1575
+ $meta['file'] = trailingslashit( dirname( $meta['file'] ) ) . basename( $file );
1576
  $image->update_converted_attachment( $meta );
1577
  $meta = $image->convert_sizes( $meta );
1578
  }
1611
  }
1612
  $next_image = new EWWW_Image( $attachment, 'media' );
1613
  }
1614
+ $image = $next_image;
1615
  $time_adjustment = $image->time_estimate();
1616
  } // End while().
1617
 
1658
  return true;
1659
  }
1660
  $output['current_time'] = time();
1661
+ ewwwio_ob_clean();
1662
  die( json_encode( $output ) );
1663
  }
1664
 
1669
  // Verify that an authorized user has started the optimizer.
1670
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
1671
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
1672
+ ewwwio_ob_clean();
1673
  die( '<p><b>' . esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) . '</b></p>' );
1674
  }
1675
  // All done, so we can update the bulk options with empty values.
1679
  delete_transient( 'ewww_image_optimizer_skip_aux' );
1680
  // Let the user know we are done.
1681
  ewwwio_memory( __FUNCTION__ );
1682
+ ewwwio_ob_clean();
1683
  die( '<p><b>' . esc_html__( 'Finished', 'ewww-image-optimizer' ) . '</b> - <a href="upload.php">' . esc_html__( 'Return to Media Library', 'ewww-image-optimizer' ) . '</a></p>' );
1684
  }
1685
 
changelog.txt CHANGED
@@ -1,3 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  = 3.6.0 =
2
  In an effort to simplify the settings page and make room for new features, many settings have been "hidden" and/or rearranged. It is my hope that this will make it easier for new users to get going with EWWW IO.
3
  You can find more information about overriding options in the [Documentation](http://docs.ewww.io)
1
+ = 4.0.6 =
2
+ * changed: dummy images have no args appended with exactdn except for ssl flag
3
+ * fixed: resize_detection.js being combined with other scripts by Autoptimize
4
+ * fixed: retina optimization not deferred in async mode
5
+ * fixed: PDF files could trigger license exceeded message
6
+ * fixed: binary detection not fully functional with MacOS and PHP 7.2
7
+ * fixed: compatibility with Regenerate Thumbnails version 3
8
+
9
+ = 4.0.5 =
10
+ * added: enable lossy compression with ExactDN: http://docs.ewww.io/article/47-getting-more-from-exactdn
11
+ * added: CSS/JS minification with ExactDN, see http://docs.ewww.io/article/47-getting-more-from-exactdn
12
+ * added: disable WebP for specific files with ewww_image_optimizer_bypass_webp filter
13
+ * added: ExactDN obeys focus point from Theia Smart Thumbnails plugin
14
+ * added: admin-ajax requests for eddvbugm loader work with ExactDN
15
+ * fixed: multisite settings would not save in certain circumstances
16
+ * fixed: compression levels reset for API users on multisite after toggling single-site override on and off
17
+ * fixed: media library items with non-local images rewritten incorrectly by ExactDN
18
+ * fixed: restoring images throws errors on PHP 7.1
19
+ * fixed: has_cap with invalid argument not recognizing utf8-mb4 v5.2
20
+
21
+ = 4.0.4 =
22
+ * fixed: ExactDN domain validation failing on length check for some domains
23
+ * updated: PEL for better EXIF preservation
24
+
25
+ = 4.0.3 =
26
+ * added: support for additional ExactDN root domains
27
+ * added: button to remove WebP rewrite rules
28
+ * added: informational notice on thumbnail rebuild pages of how the plugins interact
29
+ * changed: WebP rewrite rules removed automatically when ExactDN is enabled, use Alt WebP instead
30
+ * changed: ExactDN now removes metadata if option is enabled
31
+ * fixed: multisite settings set to defaults when single-site resize settings are submitted
32
+
33
+ = 4.0.2 =
34
+ * fixed: WooCommerce images still not working with Alt WebP in all cases
35
+ * fixed: ob_clean() breaks AJAX actions when there is no buffer to clean
36
+ * fixed: notice on NextCellent gallery management pages
37
+ * fixed: missing JS for AJAX actions in NextCellent
38
+
39
+ = 4.0.1 =
40
+ * fixed: ExactDN option not disabled when verification fails too many times
41
+ * fixed: theme scanner sometimes skipped images on PHP 5.3
42
+ * fixed: invalid (float) width parameters for srcset attributes
43
+ * fixed: Jetpack lightbox and carousel were not fully working with Alt WebP
44
+ * fixed: WooCommerce lightbox and gallery not working with Alt WebP
45
+ * fixed: incorrect message about scanning scope when selecting images from media library for bulk optimization
46
+ * security: fixed wildcard LIKE queries to allow proper escaping
47
+
48
+ = 4.0.0 =
49
+ * added: ExactDN with CDN and automatic image resizing
50
+ * added: image resize detection for admin users
51
+ * changed: WP core, theme, and plugin images are excluded from lossy optimization
52
+ * fixed: files fetched from S3 not detected by PHP in some cases
53
+ * fixed: option override conflict preventing webp conversion
54
+ * fixed: Alt WebP breaks Draw Attention image maps
55
+ * fixed: customized WP_Background_Process class conflicts with other plugins using the same class
56
+ * fixed: image deletion could cause deletion of images on source site after cloning database
57
+ * fixed: WebP .htaccess rules using REQUEST_FILENAME instead of REQUEST_URI does not work on some servers
58
+ * fixed: per-site resize settings hidden when API is active network-wide
59
+ * fixed: network-wide settings not saving properly
60
+ * fixed: notice of undefined index with some configurations of the Shield security plugin
61
+ * deprecated: PHP 5.3 support will be removed by March 2018
62
+
63
+ = 3.6.1 =
64
+ * fixed: bulk optimizer fails to initialize if the bulk_attachments array is set to an empty string
65
+ * fixed: misplaced parenthesis breaks option overrides
66
+
67
  = 3.6.0 =
68
  In an effort to simplify the settings page and make room for new features, many settings have been "hidden" and/or rearranged. It is my hope that this will make it easier for new users to get going with EWWW IO.
69
  You can find more information about overriding options in the [Documentation](http://docs.ewww.io)
classes/class-ewww-flag.php CHANGED
@@ -183,11 +183,11 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
183
  return;
184
  }
185
  // If there is no requested bulk action, do nothing.
186
- if ( 'flagallery_page_flag-manage-gallery' == $hook && ( empty( $_REQUEST['bulkaction'] ) || ! preg_match( '/^bulk_optimize/', $_REQUEST['bulkaction'] )) ) {
187
  return;
188
  }
189
  // If there is no media to optimize, do nothing.
190
- if ( 'flagallery_page_flag-manage-gallery' == $hook && ( empty( $_REQUEST['doaction'] ) || ! is_array( $_REQUEST['doaction'] )) ) {
191
  return;
192
  }
193
  $ids = null;
@@ -215,7 +215,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
215
  global $flagdb;
216
  // We don't allow previous operations to resume if the user is asking to optimize specific galleries.
217
  update_option( 'ewww_image_optimizer_bulk_flag_resume', '' );
218
- $ids = array();
219
  $gids = array_map( 'intval', $_REQUEST['doaction'] );
220
  // For each gallery ID, retrieve the image IDs within.
221
  foreach ( $gids as $gid ) {
@@ -242,15 +242,15 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
242
  wp_enqueue_style( 'jquery-ui-progressbar', plugins_url( '/includes/jquery-ui-1.10.1.custom.css', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ) );
243
  // Prepare a few variables to be used by the javascript code.
244
  wp_localize_script('ewwwbulkscript', 'ewww_vars', array(
245
- '_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-bulk' ),
246
- 'gallery' => 'flag',
247
- 'attachments' => count( $ids ),
248
- 'scan_fail' => esc_html__( 'Operation timed out, you may need to increase the max_execution_time for PHP', 'ewww-image-optimizer' ),
249
- 'operation_stopped' => esc_html__( 'Optimization stopped, reload page to resume.', 'ewww-image-optimizer' ),
250
  'operation_interrupted' => esc_html__( 'Operation Interrupted', 'ewww-image-optimizer' ),
251
- 'temporary_failure' => esc_html__( 'Temporary failure, seconds left to retry:', 'ewww-image-optimizer' ),
252
- 'remove_failed' => esc_html__( 'Could not remove image from table.', 'ewww-image-optimizer' ),
253
- 'optimized' => esc_html__( 'Optimized', 'ewww-image-optimizer' ),
254
  ) );
255
  }
256
 
@@ -292,15 +292,15 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
292
  if ( ! isset( $image->image->imagePath ) ) {
293
  return;
294
  }
295
- $ewww_image = new EWWW_Image( $id, 'flag', $image->image->imagePath );
296
  $ewww_image->resize = 'full';
297
  // Optimize the full size.
298
- $res = ewww_image_optimizer( $image->image->imagePath, 3, false, false, true );
299
- $ewww_image = new EWWW_Image( $id, 'flag', $image->image->webimagePath );
300
  $ewww_image->resize = 'webview';
301
  // Optimize the web optimized version.
302
- $wres = ewww_image_optimizer( $image->image->webimagePath, 3, false, true );
303
- $ewww_image = new EWWW_Image( $id, 'flag', $image->image->thumbPath );
304
  $ewww_image->resize = 'thumbnail';
305
  // Optimize the thumbnail.
306
  $tres = ewww_image_optimizer( $image->image->thumbPath, 3, false, true );
@@ -318,15 +318,15 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
318
  // Make sure the image path is set.
319
  if ( isset( $image->imagePath ) ) {
320
  global $ewww_image;
321
- $ewww_image = new EWWW_Image( $image->pid, 'flag', $image->imagePath );
322
  $ewww_image->resize = 'full';
323
  // Optimize the full size.
324
- $res = ewww_image_optimizer( $image->imagePath, 3, false, false, true );
325
- $ewww_image = new EWWW_Image( $image->pid, 'flag', $image->webimagePath );
326
  $ewww_image->resize = 'webview';
327
  // Optimize the web optimized version.
328
- $wres = ewww_image_optimizer( $image->webimagePath, 3, false, true );
329
- $ewww_image = new EWWW_Image( $image->pid, 'flag', $image->thumbPath );
330
  $ewww_image->resize = 'thumbnail';
331
  // Optimize the thumbnail.
332
  $tres = ewww_image_optimizer( $image->thumbPath, 3, false, true );
@@ -334,7 +334,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
334
  require_once( FLAG_ABSPATH . 'lib/meta.php' );
335
  }
336
  // Retrieve the metadata for the image ID.
337
- $pid = $image->pid;
338
  $meta = new flagMeta( $pid );
339
  }
340
  ewww_image_optimizer_debug_log();
@@ -358,6 +358,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
358
  if ( ! wp_doing_ajax() ) {
359
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
360
  }
 
361
  wp_die( json_encode( array(
362
  'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
363
  ) ) );
@@ -367,6 +368,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
367
  if ( ! wp_doing_ajax() ) {
368
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
369
  }
 
370
  wp_die( json_encode( array(
371
  'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ),
372
  ) ) );
@@ -376,6 +378,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
376
  if ( ! wp_doing_ajax() ) {
377
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
378
  }
 
379
  wp_die( json_encode( array(
380
  'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
381
  ) ) );
@@ -387,21 +390,21 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
387
  // Retrieve the metadata for the image ID.
388
  $meta = new flagMeta( $id );
389
  // Determine the path of the image.
390
- $file_path = $meta->image->imagePath;
391
- $ewww_image = new EWWW_Image( $id, 'flag', $file_path );
392
  $ewww_image->resize = 'full';
393
  // Optimize the full size.
394
  $res = ewww_image_optimizer( $file_path, 3, false, false, true );
395
  if ( ! empty( $meta->image->meta_data['webview'] ) ) {
396
  // Determine path of the webview.
397
- $web_path = $meta->image->webimagePath;
398
- $ewww_image = new EWWW_Image( $id, 'flag', $web_path );
399
  $ewww_image->resize = 'webview';
400
- $wres = ewww_image_optimizer( $web_path, 3, false, true );
401
  }
402
  // Determine the path of the thumbnail.
403
- $thumb_path = $meta->image->thumbPath;
404
- $ewww_image = new EWWW_Image( $id, 'flag', $thumb_path );
405
  $ewww_image->resize = 'thumbnail';
406
  // Optimize the thumbnail.
407
  $tres = ewww_image_optimizer( $thumb_path, 3, false, true );
@@ -415,6 +418,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
415
  die;
416
  }
417
  $success = $this->ewww_manage_image_custom_column( $id );
 
418
  wp_die( json_encode( array(
419
  'success' => $success,
420
  ) ) );
@@ -430,6 +434,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
430
  if ( ! wp_doing_ajax() ) {
431
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
432
  }
 
433
  wp_die( json_encode( array(
434
  'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
435
  ) ) );
@@ -439,6 +444,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
439
  if ( ! wp_doing_ajax() ) {
440
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
441
  }
 
442
  wp_die( json_encode( array(
443
  'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ),
444
  ) ) );
@@ -449,6 +455,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
449
  if ( ! wp_doing_ajax() ) {
450
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
451
  }
 
452
  wp_die( json_encode( array(
453
  'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
454
  ) ) );
@@ -458,7 +465,8 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
458
  }
459
  ewww_image_optimizer_cloud_restore_from_meta_data( $id, 'flag' );
460
  $success = $this->ewww_manage_image_custom_column( $id );
461
- die( json_encode( array(
 
462
  'success' => $success,
463
  ) ) );
464
  }
@@ -469,6 +477,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
469
  function ewww_flag_bulk_init() {
470
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
471
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
 
472
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
473
  }
474
  $output = array();
@@ -481,11 +490,11 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
481
  }
482
  if ( ! is_array( $attachments ) ) {
483
  $output['error'] = esc_html__( 'Error retrieving list of images' );
484
- echo json_encode( $output );
485
- die();
486
  }
487
- $id = array_shift( $attachments );
488
- $file_name = $this->ewww_flag_bulk_filename( $id );
489
  $loading_image = plugins_url( '/images/wpspin.gif', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE );
490
  // Output the initial message letting the user know we are starting.
491
  if ( empty( $file_name ) ) {
@@ -493,8 +502,8 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
493
  } else {
494
  $output['results'] = '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . ' <b>' . $file_name . "</b>&nbsp;<img src='$loading_image' alt='loading'/></p>";
495
  }
496
- echo json_encode( $output );
497
- die();
498
  }
499
 
500
  /**
@@ -522,13 +531,13 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
522
  */
523
  function ewww_flag_bulk_loop() {
524
  global $ewww_defer;
525
- $ewww_defer = false;
526
- $output = array();
527
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
528
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
529
  $output['error'] = esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' );
530
- echo json_encode( $output );
531
- die();
532
  }
533
  session_write_close();
534
  // Find out if our nonce is on it's last leg/tick.
@@ -545,19 +554,19 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
545
  $started = microtime( true );
546
  // Retrieve the list of attachments left to work on.
547
  $attachments = get_option( 'ewww_image_optimizer_bulk_flag_attachments' );
548
- $id = array_shift( $attachments );
549
  // Get the image meta for the current ID.
550
- $meta = new flagMeta( $id );
551
- $file_path = $meta->image->imagePath;
552
- $ewww_image = new EWWW_Image( $id, 'flag', $file_path );
553
  $ewww_image->resize = 'full';
554
  // Optimize the full-size version.
555
- $fres = ewww_image_optimizer( $file_path, 3, false, false, true );
556
  $ewww_status = get_transient( 'ewww_image_optimizer_cloud_status' );
557
  if ( ! empty( $ewww_status ) && preg_match( '/exceeded/', $ewww_status ) ) {
558
  $output['error'] = esc_html__( 'License Exceeded', 'ewww-image-optimizer' );
559
- echo json_encode( $output );
560
- die();
561
  }
562
  // Let the user know what happened.
563
  $output['results'] = sprintf( '<p>' . esc_html__( 'Optimized image:', 'ewww-image-optimizer' ) . ' <strong>%s</strong><br>', esc_html( $meta->image->filename ) );
@@ -565,15 +574,15 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
565
  $output['results'] .= sprintf( esc_html__( 'Full size – %s', 'ewww-image-optimizer' ) . '<br>', esc_html( $fres[1] ) );
566
  if ( ! empty( $meta->image->meta_data['webview'] ) ) {
567
  // Determine path of the webview.
568
- $web_path = $meta->image->webimagePath;
569
- $ewww_image = new EWWW_Image( $id, 'flag', $web_path );
570
  $ewww_image->resize = 'webview';
571
- $wres = ewww_image_optimizer( $web_path, 3, false, true );
572
  /* Translators: %s: The compression results/savings */
573
  $output['results'] .= sprintf( esc_html__( 'Optimized size – %s', 'ewww-image-optimizer' ) . '<br>', esc_html( $wres[1] ) );
574
  }
575
- $thumb_path = $meta->image->thumbPath;
576
- $ewww_image = new EWWW_Image( $id, 'flag', $thumb_path );
577
  $ewww_image->resize = 'thumbnail';
578
  // Optimize the thumbnail.
579
  $tres = ewww_image_optimizer( $thumb_path, 3, false, true );
@@ -584,14 +593,14 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
584
  $elapsed = microtime( true ) - $started;
585
  // And output it to the user.
586
  /* Translators: %s: number of seconds, localized */
587
- $output['results'] .= sprintf( esc_html( _n( 'Elapsed: %s second', 'Elapsed: %s seconds', $elapsed, 'ewww-image-optimizer' ) ) . '</p>', number_format_i18n( $elapsed ) );
588
  $output['completed'] = 1;
589
  // Send the list back to the db.
590
  update_option( 'ewww_image_optimizer_bulk_flag_attachments', $attachments, false );
591
  if ( ! empty( $attachments ) ) {
592
  $next_attachment = array_shift( $attachments );
593
- $next_file = $this->ewww_flag_bulk_filename( $next_attachment );
594
- $loading_image = plugins_url( '/images/wpspin.gif', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE );
595
  if ( $next_file ) {
596
  $output['next_file'] = '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . " <b>$next_file</b>&nbsp;<img src='$loading_image' alt='loading'/></p>";
597
  } else {
@@ -600,7 +609,8 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
600
  } else {
601
  $output['done'] = 1;
602
  }
603
- die( json_encode( $output ) );
 
604
  }
605
 
606
  /**
@@ -609,14 +619,15 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
609
  function ewww_flag_bulk_cleanup() {
610
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
611
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
 
612
  wp_die( esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) );
613
  }
614
  // Reset the bulk flags in the db.
615
  update_option( 'ewww_image_optimizer_bulk_flag_resume', '' );
616
  update_option( 'ewww_image_optimizer_bulk_flag_attachments', '', false );
 
617
  // And let the user know we are done.
618
- echo '<p><b>' . esc_html__( 'Finished Optimization!', 'ewww-image-optimizer' ) . '</b></p>';
619
- die();
620
  }
621
 
622
  /**
@@ -641,7 +652,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
641
  'ewww_vars',
642
  array(
643
  'optimizing' => '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . " <img src='$loading_image' /></p>",
644
- 'restoring' => '<p>' . esc_html__( 'Restoring', 'ewww-image-optimizer' ) . " <img src='$loading_image' /></p>",
645
  )
646
  );
647
  }
@@ -690,7 +701,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
690
  }
691
  $msg = '';
692
  // Get the mimetype.
693
- $type = ewww_image_optimizer_mimetype( $file_path, 'i' );
694
  $valid = true;
695
  // If we don't have a valid tool for the image type, output the appropriate message.
696
  $skip = ewww_image_optimizer_skip_tools();
@@ -722,7 +733,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
722
  }
723
  $backup_available = false;
724
  global $wpdb;
725
- $optimized_images = $wpdb->get_results( $wpdb->prepare( "SELECT image_size,orig_size,resize,converted,level,backup,updated FROM $wpdb->ewwwio_images WHERE attachment_id = %d AND gallery = 'flag' AND image_size <> 0 ORDER BY orig_size DESC", $id ), ARRAY_A );
726
  $ewww_manual_nonce = wp_create_nonce( 'ewww-manual-' . $id );
727
  if ( ! empty( $optimized_images ) ) {
728
  list( $detail_output, $converted, $backup_available ) = ewww_image_optimizer_custom_column_results( $id, $optimized_images );
183
  return;
184
  }
185
  // If there is no requested bulk action, do nothing.
186
+ if ( 'flagallery_page_flag-manage-gallery' == $hook && ( empty( $_REQUEST['bulkaction'] ) || ! preg_match( '/^bulk_optimize/', $_REQUEST['bulkaction'] ) ) ) {
187
  return;
188
  }
189
  // If there is no media to optimize, do nothing.
190
+ if ( 'flagallery_page_flag-manage-gallery' == $hook && ( empty( $_REQUEST['doaction'] ) || ! is_array( $_REQUEST['doaction'] ) ) ) {
191
  return;
192
  }
193
  $ids = null;
215
  global $flagdb;
216
  // We don't allow previous operations to resume if the user is asking to optimize specific galleries.
217
  update_option( 'ewww_image_optimizer_bulk_flag_resume', '' );
218
+ $ids = array();
219
  $gids = array_map( 'intval', $_REQUEST['doaction'] );
220
  // For each gallery ID, retrieve the image IDs within.
221
  foreach ( $gids as $gid ) {
242
  wp_enqueue_style( 'jquery-ui-progressbar', plugins_url( '/includes/jquery-ui-1.10.1.custom.css', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ) );
243
  // Prepare a few variables to be used by the javascript code.
244
  wp_localize_script('ewwwbulkscript', 'ewww_vars', array(
245
+ '_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-bulk' ),
246
+ 'gallery' => 'flag',
247
+ 'attachments' => count( $ids ),
248
+ 'scan_fail' => esc_html__( 'Operation timed out, you may need to increase the max_execution_time for PHP', 'ewww-image-optimizer' ),
249
+ 'operation_stopped' => esc_html__( 'Optimization stopped, reload page to resume.', 'ewww-image-optimizer' ),
250
  'operation_interrupted' => esc_html__( 'Operation Interrupted', 'ewww-image-optimizer' ),
251
+ 'temporary_failure' => esc_html__( 'Temporary failure, seconds left to retry:', 'ewww-image-optimizer' ),
252
+ 'remove_failed' => esc_html__( 'Could not remove image from table.', 'ewww-image-optimizer' ),
253
+ 'optimized' => esc_html__( 'Optimized', 'ewww-image-optimizer' ),
254
  ) );
255
  }
256
 
292
  if ( ! isset( $image->image->imagePath ) ) {
293
  return;
294
  }
295
+ $ewww_image = new EWWW_Image( $id, 'flag', $image->image->imagePath );
296
  $ewww_image->resize = 'full';
297
  // Optimize the full size.
298
+ $res = ewww_image_optimizer( $image->image->imagePath, 3, false, false, true );
299
+ $ewww_image = new EWWW_Image( $id, 'flag', $image->image->webimagePath );
300
  $ewww_image->resize = 'webview';
301
  // Optimize the web optimized version.
302
+ $wres = ewww_image_optimizer( $image->image->webimagePath, 3, false, true );
303
+ $ewww_image = new EWWW_Image( $id, 'flag', $image->image->thumbPath );
304
  $ewww_image->resize = 'thumbnail';
305
  // Optimize the thumbnail.
306
  $tres = ewww_image_optimizer( $image->image->thumbPath, 3, false, true );
318
  // Make sure the image path is set.
319
  if ( isset( $image->imagePath ) ) {
320
  global $ewww_image;
321
+ $ewww_image = new EWWW_Image( $image->pid, 'flag', $image->imagePath );
322
  $ewww_image->resize = 'full';
323
  // Optimize the full size.
324
+ $res = ewww_image_optimizer( $image->imagePath, 3, false, false, true );
325
+ $ewww_image = new EWWW_Image( $image->pid, 'flag', $image->webimagePath );
326
  $ewww_image->resize = 'webview';
327
  // Optimize the web optimized version.
328
+ $wres = ewww_image_optimizer( $image->webimagePath, 3, false, true );
329
+ $ewww_image = new EWWW_Image( $image->pid, 'flag', $image->thumbPath );
330
  $ewww_image->resize = 'thumbnail';
331
  // Optimize the thumbnail.
332
  $tres = ewww_image_optimizer( $image->thumbPath, 3, false, true );
334
  require_once( FLAG_ABSPATH . 'lib/meta.php' );
335
  }
336
  // Retrieve the metadata for the image ID.
337
+ $pid = $image->pid;
338
  $meta = new flagMeta( $pid );
339
  }
340
  ewww_image_optimizer_debug_log();
358
  if ( ! wp_doing_ajax() ) {
359
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
360
  }
361
+ ewwwio_ob_clean();
362
  wp_die( json_encode( array(
363
  'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
364
  ) ) );
368
  if ( ! wp_doing_ajax() ) {
369
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
370
  }
371
+ ewwwio_ob_clean();
372
  wp_die( json_encode( array(
373
  'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ),
374
  ) ) );
378
  if ( ! wp_doing_ajax() ) {
379
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
380
  }
381
+ ewwwio_ob_clean();
382
  wp_die( json_encode( array(
383
  'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
384
  ) ) );
390
  // Retrieve the metadata for the image ID.
391
  $meta = new flagMeta( $id );
392
  // Determine the path of the image.
393
+ $file_path = $meta->image->imagePath;
394
+ $ewww_image = new EWWW_Image( $id, 'flag', $file_path );
395
  $ewww_image->resize = 'full';
396
  // Optimize the full size.
397
  $res = ewww_image_optimizer( $file_path, 3, false, false, true );
398
  if ( ! empty( $meta->image->meta_data['webview'] ) ) {
399
  // Determine path of the webview.
400
+ $web_path = $meta->image->webimagePath;
401
+ $ewww_image = new EWWW_Image( $id, 'flag', $web_path );
402
  $ewww_image->resize = 'webview';
403
+ $wres = ewww_image_optimizer( $web_path, 3, false, true );
404
  }
405
  // Determine the path of the thumbnail.
406
+ $thumb_path = $meta->image->thumbPath;
407
+ $ewww_image = new EWWW_Image( $id, 'flag', $thumb_path );
408
  $ewww_image->resize = 'thumbnail';
409
  // Optimize the thumbnail.
410
  $tres = ewww_image_optimizer( $thumb_path, 3, false, true );
418
  die;
419
  }
420
  $success = $this->ewww_manage_image_custom_column( $id );
421
+ ewwwio_ob_clean();
422
  wp_die( json_encode( array(
423
  'success' => $success,
424
  ) ) );
434
  if ( ! wp_doing_ajax() ) {
435
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
436
  }
437
+ ewwwio_ob_clean();
438
  wp_die( json_encode( array(
439
  'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
440
  ) ) );
444
  if ( ! wp_doing_ajax() ) {
445
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
446
  }
447
+ ewwwio_ob_clean();
448
  wp_die( json_encode( array(
449
  'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ),
450
  ) ) );
455
  if ( ! wp_doing_ajax() ) {
456
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
457
  }
458
+ ewwwio_ob_clean();
459
  wp_die( json_encode( array(
460
  'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
461
  ) ) );
465
  }
466
  ewww_image_optimizer_cloud_restore_from_meta_data( $id, 'flag' );
467
  $success = $this->ewww_manage_image_custom_column( $id );
468
+ ewwwio_ob_clean();
469
+ wp_die( json_encode( array(
470
  'success' => $success,
471
  ) ) );
472
  }
477
  function ewww_flag_bulk_init() {
478
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
479
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
480
+ ewwwio_ob_clean();
481
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
482
  }
483
  $output = array();
490
  }
491
  if ( ! is_array( $attachments ) ) {
492
  $output['error'] = esc_html__( 'Error retrieving list of images' );
493
+ ewwwio_ob_clean();
494
+ wp_die( json_encode( $output ) );
495
  }
496
+ $id = array_shift( $attachments );
497
+ $file_name = $this->ewww_flag_bulk_filename( $id );
498
  $loading_image = plugins_url( '/images/wpspin.gif', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE );
499
  // Output the initial message letting the user know we are starting.
500
  if ( empty( $file_name ) ) {
502
  } else {
503
  $output['results'] = '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . ' <b>' . $file_name . "</b>&nbsp;<img src='$loading_image' alt='loading'/></p>";
504
  }
505
+ ewwwio_ob_clean();
506
+ wp_die( json_encode( $output ) );
507
  }
508
 
509
  /**
531
  */
532
  function ewww_flag_bulk_loop() {
533
  global $ewww_defer;
534
+ $ewww_defer = false;
535
+ $output = array();
536
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
537
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
538
  $output['error'] = esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' );
539
+ ewwwio_ob_clean();
540
+ wp_die( json_encode( $output ) );
541
  }
542
  session_write_close();
543
  // Find out if our nonce is on it's last leg/tick.
554
  $started = microtime( true );
555
  // Retrieve the list of attachments left to work on.
556
  $attachments = get_option( 'ewww_image_optimizer_bulk_flag_attachments' );
557
+ $id = array_shift( $attachments );
558
  // Get the image meta for the current ID.
559
+ $meta = new flagMeta( $id );
560
+ $file_path = $meta->image->imagePath;
561
+ $ewww_image = new EWWW_Image( $id, 'flag', $file_path );
562
  $ewww_image->resize = 'full';
563
  // Optimize the full-size version.
564
+ $fres = ewww_image_optimizer( $file_path, 3, false, false, true );
565
  $ewww_status = get_transient( 'ewww_image_optimizer_cloud_status' );
566
  if ( ! empty( $ewww_status ) && preg_match( '/exceeded/', $ewww_status ) ) {
567
  $output['error'] = esc_html__( 'License Exceeded', 'ewww-image-optimizer' );
568
+ ewwwio_ob_clean();
569
+ wp_die( json_encode( $output ) );
570
  }
571
  // Let the user know what happened.
572
  $output['results'] = sprintf( '<p>' . esc_html__( 'Optimized image:', 'ewww-image-optimizer' ) . ' <strong>%s</strong><br>', esc_html( $meta->image->filename ) );
574
  $output['results'] .= sprintf( esc_html__( 'Full size – %s', 'ewww-image-optimizer' ) . '<br>', esc_html( $fres[1] ) );
575
  if ( ! empty( $meta->image->meta_data['webview'] ) ) {
576
  // Determine path of the webview.
577
+ $web_path = $meta->image->webimagePath;
578
+ $ewww_image = new EWWW_Image( $id, 'flag', $web_path );
579
  $ewww_image->resize = 'webview';
580
+ $wres = ewww_image_optimizer( $web_path, 3, false, true );
581
  /* Translators: %s: The compression results/savings */
582
  $output['results'] .= sprintf( esc_html__( 'Optimized size – %s', 'ewww-image-optimizer' ) . '<br>', esc_html( $wres[1] ) );
583
  }
584
+ $thumb_path = $meta->image->thumbPath;
585
+ $ewww_image = new EWWW_Image( $id, 'flag', $thumb_path );
586
  $ewww_image->resize = 'thumbnail';
587
  // Optimize the thumbnail.
588
  $tres = ewww_image_optimizer( $thumb_path, 3, false, true );
593
  $elapsed = microtime( true ) - $started;
594
  // And output it to the user.
595
  /* Translators: %s: number of seconds, localized */
596
+ $output['results'] .= sprintf( esc_html( _n( 'Elapsed: %s second', 'Elapsed: %s seconds', $elapsed, 'ewww-image-optimizer' ) ) . '</p>', number_format_i18n( $elapsed ) );
597
  $output['completed'] = 1;
598
  // Send the list back to the db.
599
  update_option( 'ewww_image_optimizer_bulk_flag_attachments', $attachments, false );
600
  if ( ! empty( $attachments ) ) {
601
  $next_attachment = array_shift( $attachments );
602
+ $next_file = $this->ewww_flag_bulk_filename( $next_attachment );
603
+ $loading_image = plugins_url( '/images/wpspin.gif', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE );
604
  if ( $next_file ) {
605
  $output['next_file'] = '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . " <b>$next_file</b>&nbsp;<img src='$loading_image' alt='loading'/></p>";
606
  } else {
609
  } else {
610
  $output['done'] = 1;
611
  }
612
+ ewwwio_ob_clean();
613
+ wp_die( json_encode( $output ) );
614
  }
615
 
616
  /**
619
  function ewww_flag_bulk_cleanup() {
620
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
621
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
622
+ ewwwio_ob_clean();
623
  wp_die( esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) );
624
  }
625
  // Reset the bulk flags in the db.
626
  update_option( 'ewww_image_optimizer_bulk_flag_resume', '' );
627
  update_option( 'ewww_image_optimizer_bulk_flag_attachments', '', false );
628
+ ewwwio_ob_clean();
629
  // And let the user know we are done.
630
+ wp_die( '<p><b>' . esc_html__( 'Finished Optimization!', 'ewww-image-optimizer' ) . '</b></p>' );
 
631
  }
632
 
633
  /**
652
  'ewww_vars',
653
  array(
654
  'optimizing' => '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . " <img src='$loading_image' /></p>",
655
+ 'restoring' => '<p>' . esc_html__( 'Restoring', 'ewww-image-optimizer' ) . " <img src='$loading_image' /></p>",
656
  )
657
  );
658
  }
701
  }
702
  $msg = '';
703
  // Get the mimetype.
704
+ $type = ewww_image_optimizer_mimetype( $file_path, 'i' );
705
  $valid = true;
706
  // If we don't have a valid tool for the image type, output the appropriate message.
707
  $skip = ewww_image_optimizer_skip_tools();
733
  }
734
  $backup_available = false;
735
  global $wpdb;
736
+ $optimized_images = $wpdb->get_results( $wpdb->prepare( "SELECT image_size,orig_size,resize,converted,level,backup,updated FROM $wpdb->ewwwio_images WHERE attachment_id = %d AND gallery = 'flag' AND image_size <> 0 ORDER BY orig_size DESC", $id ), ARRAY_A );
737
  $ewww_manual_nonce = wp_create_nonce( 'ewww-manual-' . $id );
738
  if ( ! empty( $optimized_images ) ) {
739
  list( $detail_output, $converted, $backup_available ) = ewww_image_optimizer_custom_column_results( $id, $optimized_images );
classes/class-ewww-image.php CHANGED
@@ -120,9 +120,9 @@ class EWWW_Image {
120
  ewwwio_debug_message( "creating EWWW_Image with $path" );
121
  $new_image = ewww_image_optimizer_find_already_optimized( $path );
122
  if ( ! $new_image ) {
123
- $this->file = $path;
124
  $this->orig_size = filesize( $path );
125
- $this->gallery = $gallery;
126
  if ( $id ) {
127
  $this->attachment_id = $id;
128
  }
@@ -208,7 +208,7 @@ class EWWW_Image {
208
  }
209
  // Update the attachment post with the new mimetype and id.
210
  wp_update_post( array(
211
- 'ID' => $this->attachment_id,
212
  'post_mime_type' => $mime,
213
  ) );
214
  }
@@ -243,6 +243,7 @@ class EWWW_Image {
243
  /* ewwwio_debug_message( 'about to process db results' ); */
244
  foreach ( $sizes_queried as $size_queried ) {
245
  $size_queried['path'] = ewww_image_optimizer_relative_path_replace( $size_queried['path'] );
 
246
  $sizes[ $size_queried['resize'] ] = $size_queried;
247
  // Convert here.
248
  $new_name = $this->convert( $size_queried['path'] );
@@ -254,7 +255,7 @@ class EWWW_Image {
254
  /* ewwwio_debug_message( print_r( $size_queried, true ) ); */
255
  if ( ewww_image_optimizer_iterable( $meta['sizes'] ) && is_array( $meta['sizes'][ $size_queried['resize'] ] ) ) {
256
  ewwwio_debug_message( 'updating regular size' );
257
- $meta['sizes'][ $size_queried['resize'] ]['file'] = basename( $new_name );
258
  $meta['sizes'][ $size_queried['resize'] ]['mime-type'] = ewww_image_optimizer_quick_mimetype( $new_name );
259
  } elseif ( ewww_image_optimizer_iterable( $meta['custom_sizes'] ) ) {
260
  $dimensions = str_replace( 'custom-size-', '', $size_queried['resize'] );
@@ -305,7 +306,7 @@ class EWWW_Image {
305
  if ( $new_name ) {
306
  $this->convert_retina( $base_dir . $data['file'] );
307
  $this->convert_db_path( $base_dir . $data['file'], $new_name );
308
- $meta['sizes'][ $size ]['file'] = basename( $new_name );
309
  $meta['sizes'][ $size ]['mime-type'] = ewww_image_optimizer_quick_mimetype( $new_name );
310
  }
311
  ewwwio_debug_message( "converted $size from meta" );
@@ -316,13 +317,13 @@ class EWWW_Image {
316
  // Convert sizes from a custom theme.
317
  if ( isset( $meta['image_meta']['resized_images'] ) && ewww_image_optimizer_iterable( $meta['image_meta']['resized_images'] ) ) {
318
  $imagemeta_resize_pathinfo = pathinfo( $this->file );
319
- $imagemeta_resize_path = '';
320
  foreach ( $meta['image_meta']['resized_images'] as $index => $imagemeta_resize ) {
321
  if ( isset( $sizes[ 'resized-images-' . $index ] ) ) {
322
  continue;
323
  }
324
  $imagemeta_resize_path = $imagemeta_resize_pathinfo['dirname'] . '/' . $imagemeta_resize_pathinfo['filename'] . '-' . $imagemeta_resize . '.' . $imagemeta_resize_pathinfo['extension'];
325
- $new_name = $this->convert( $imagemeta_resize_path );
326
  if ( $new_name ) {
327
  $this->convert_retina( $imagemeta_resize_path );
328
  $this->convert_db_path( $imagemeta_resize_path, $new_name );
@@ -335,13 +336,13 @@ class EWWW_Image {
335
  // and another custom theme.
336
  if ( isset( $meta['custom_sizes'] ) && ewww_image_optimizer_iterable( $meta['custom_sizes'] ) ) {
337
  $custom_sizes_pathinfo = pathinfo( $file_path );
338
- $custom_size_path = '';
339
  foreach ( $meta['custom_sizes'] as $dimensions => $custom_size ) {
340
  if ( isset( $sizes[ 'custom-size-' . $dimensions ] ) ) {
341
  continue;
342
  }
343
  $custom_size_path = $custom_sizes_pathinfo['dirname'] . '/' . $custom_size['file'];
344
- $new_name = $this->convert( $custom_size_path );
345
  if ( $new_name ) {
346
  $this->convert_retina( $custom_size_path );
347
  $this->convert_db_path( $custom_size_path, $new_name );
@@ -373,9 +374,9 @@ class EWWW_Image {
373
  $this->restore_db_path( $this->file, $this->converted, $this->id );
374
  $converted_path = $this->file;
375
  unlink( $this->file );
376
- $this->file = $this->converted;
377
  $this->converted = $converted_path;
378
- $meta['file'] = trailingslashit( dirname( $meta['file'] ) ) . basename( $this->file );
379
  $this->update_converted_attachment( $meta );
380
  $meta = $this->restore_sizes( $meta );
381
  return $meta;
@@ -408,15 +409,16 @@ class EWWW_Image {
408
  if ( empty( $size_queried['converted'] ) ) {
409
  continue;
410
  }
411
- $size_queried['path'] = ewww_image_optimizer_relative_path_replace( $size_queried['path'] );
412
  $size_queried['converted'] = ewww_image_optimizer_relative_path_replace( $size_queried['converted'] );
 
413
  $new_name = ( empty( $size_queried['converted'] ) ? '' : $size_queried['converted'] );
414
  if ( $new_name && is_file( $size_queried['path'] ) && is_file( $new_name ) ) {
415
  $this->restore_db_path( $size_queried['path'], $new_name, $size_queried['id'] );
416
  $this->replace_url( $new_name, $size_queried['path'] );
417
  if ( ewww_image_optimizer_iterable( $meta['sizes'] ) && is_array( $meta['sizes'][ $size_queried['resize'] ] ) ) {
418
  ewwwio_debug_message( 'updating regular size' );
419
- $meta['sizes'][ $size_queried['resize'] ]['file'] = basename( $new_name );
420
  $meta['sizes'][ $size_queried['resize'] ]['mime-type'] = ewww_image_optimizer_quick_mimetype( $new_name );
421
  } elseif ( ewww_image_optimizer_iterable( $meta['custom_sizes'] ) ) {
422
  $dimensions = str_replace( 'custom-size-', '', $size_queried['resize'] );
@@ -430,7 +432,7 @@ class EWWW_Image {
430
  if ( isset( $meta['sizes'] ) && ewww_image_optimizer_iterable( $meta['sizes'] ) ) {
431
  foreach ( $meta['sizes'] as $size => $data ) {
432
  if ( $meta['sizes'][ $size_queried['resize'] ]['height'] == $data['height'] && $meta['sizes'][ $size_queried['resize'] ]['width'] == $data['width'] ) {
433
- $meta['sizes'][ $size ]['file'] = $meta['sizes'][ $size_queried['resize'] ]['file'];
434
  $meta['sizes'][ $size ]['mime-type'] = $meta['sizes'][ $size_queried['resize'] ]['mime-type'];
435
  }
436
  }
@@ -506,16 +508,16 @@ class EWWW_Image {
506
  // If the user has disabled the utility checks.
507
  if ( EWWW_IMAGE_OPTIMIZER_CLOUD ) {
508
  $skip['jpegtran'] = true;
509
- $skip['optipng'] = true;
510
  $skip['gifsicle'] = true;
511
- $skip['pngout'] = true;
512
  $skip['pngquant'] = true;
513
- $skip['webp'] = true;
514
  }
515
  switch ( $type ) {
516
  case 'image/jpeg':
517
  $png_size = 0;
518
- $newfile = $this->unique_filename( $file, '.png' );
519
  ewwwio_debug_message( "attempting to convert JPG to PNG: $newfile" );
520
  // Convert the JPG to PNG.
521
  if ( ewww_image_optimizer_gmagick_support() ) {
@@ -564,7 +566,7 @@ class EWWW_Image {
564
  break;
565
  case 'image/png':
566
  $jpg_size = 0;
567
- $newfile = $this->unique_filename( $file, '.jpg' );
568
  ewwwio_debug_message( "attempting to convert PNG to JPG: $newfile" );
569
  // If the user set a fill background for transparency.
570
  $background = ewww_image_optimizer_jpg_background();
@@ -592,7 +594,7 @@ class EWWW_Image {
592
  try {
593
  if ( ewww_image_optimizer_png_alpha( $file ) ) {
594
  $gmagick_overlay = new Gmagick( $file );
595
- $gmagick = new Gmagick();
596
  $gmagick->newimage( $gmagick_overlay->getimagewidth(), $gmagick_overlay->getimageheight(), '#' . $magick_background );
597
  $gmagick->compositeimage( $gmagick_overlay, 1, 0, 0 );
598
  } else {
@@ -663,7 +665,7 @@ class EWWW_Image {
663
  break;
664
  case 'image/gif':
665
  $png_size = 0;
666
- $newfile = $this->unique_filename( $file, '.png' );
667
  ewwwio_debug_message( "attempting to convert GIF to PNG: $newfile" );
668
  // Convert the GIF to PNG.
669
  if ( ewww_image_optimizer_gmagick_support() ) {
@@ -733,21 +735,21 @@ class EWWW_Image {
733
  // Set the increment to 1 ( but allow the user to override it ).
734
  $filenum = apply_filters( 'ewww_image_optimizer_converted_filename_suffix', $this->increment );
735
  // But it must be only letters, numbers, or underscores.
736
- $filenum = ( preg_match( '/^[\w\d]*$/', $filenum ) ? $filenum : 1 );
737
- $suffix = ( ! empty( $filenum ) ? '-' . $filenum : '' );
738
- $dimensions = '';
739
  $default_hidpi_suffix = apply_filters( 'ewww_image_optimizer_hidpi_suffix', '@2x' );
740
- $hidpi_suffix = '';
741
  // See if this is a retina image, and strip the suffix.
742
  if ( preg_match( "/$default_hidpi_suffix$/", $filename ) ) {
743
  // Strip the dimensions.
744
- $filename = str_replace( $default_hidpi_suffix, '', $filename );
745
  $hidpi_suffix = $default_hidpi_suffix;
746
  }
747
  // See if this is a resize, and strip the dimensions.
748
  if ( preg_match( '/-\d+x\d+(-\d+)*$/', $filename, $fileresize ) ) {
749
  // Strip the dimensions.
750
- $filename = str_replace( $fileresize[0], '', $filename );
751
  $dimensions = $fileresize[0];
752
  }
753
  // While a file exists with the current increment.
@@ -794,7 +796,7 @@ class EWWW_Image {
794
 
795
  global $wpdb;
796
  // Retrieve any posts that link the image.
797
- $esql = $wpdb->prepare( "SELECT ID, post_content FROM $wpdb->posts WHERE post_content LIKE '%%%s%%'", $old_guid );
798
  ewwwio_debug_message( "using query: $esql" );
799
  $rows = $wpdb->get_results( $esql, ARRAY_A ); // WPCS: unprepared SQL ok.
800
  if ( ewww_image_optimizer_iterable( $rows ) ) {
@@ -844,24 +846,24 @@ class EWWW_Image {
844
  $id = $image_record['id'];
845
  } else { // Insert a new record.
846
  $ewwwdb->insert( $ewwwdb->ewwwio_images, array(
847
- 'path' => ewww_image_optimizer_relative_path_remove( $new_path ),
848
- 'converted' => ewww_image_optimizer_relative_path_remove( $path ),
849
- 'orig_size' => filesize( $new_path ),
850
  'attachment_id' => $this->attachment_id,
851
- 'results' => __( 'No savings', 'ewww-image-optimizer' ),
852
- 'updated' => date( 'Y-m-d H:i:s' ),
853
- 'updates' => 0,
854
  ) );
855
  return;
856
  }
857
  }
858
  $ewwwdb->update( $ewwwdb->ewwwio_images,
859
  array(
860
- 'path' => ewww_image_optimizer_relative_path_remove( $new_path ),
861
  'converted' => ewww_image_optimizer_relative_path_remove( $path ),
862
- 'results' => ewww_image_optimizer_image_results( $image_record['orig_size'], filesize( $new_path ) ),
863
- 'updates' => 0,
864
- 'trace' => '',
865
  ),
866
  array(
867
  'id' => $id,
@@ -900,13 +902,13 @@ class EWWW_Image {
900
  }
901
  $ewwwdb->update( $ewwwdb->ewwwio_images,
902
  array(
903
- 'path' => ewww_image_optimizer_relative_path_remove( $new_path ),
904
- 'converted' => '',
905
  'image_size' => 0,
906
- 'results' => __( 'Original Restored', 'ewww-image-optimizer' ),
907
- 'updates' => 0,
908
- 'trace' => '',
909
- 'level' => null,
910
  ),
911
  array(
912
  'id' => $id,
@@ -923,12 +925,12 @@ class EWWW_Image {
923
  */
924
  public function time_estimate() {
925
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
926
- $time = 0;
927
- $type = ewww_image_optimizer_quick_mimetype( $this->file );
928
  $image_size = ( empty( $this->opt_size ) ? $this->orig_size : $this->opt_size );
929
  if ( empty( $image_size ) ) {
930
  $this->orig_size = filesize( $this->file );
931
- $image_size = $this->orig_size;
932
  }
933
  switch ( $type ) {
934
  case 'image/jpeg':
120
  ewwwio_debug_message( "creating EWWW_Image with $path" );
121
  $new_image = ewww_image_optimizer_find_already_optimized( $path );
122
  if ( ! $new_image ) {
123
+ $this->file = $path;
124
  $this->orig_size = filesize( $path );
125
+ $this->gallery = $gallery;
126
  if ( $id ) {
127
  $this->attachment_id = $id;
128
  }
208
  }
209
  // Update the attachment post with the new mimetype and id.
210
  wp_update_post( array(
211
+ 'ID' => $this->attachment_id,
212
  'post_mime_type' => $mime,
213
  ) );
214
  }
243
  /* ewwwio_debug_message( 'about to process db results' ); */
244
  foreach ( $sizes_queried as $size_queried ) {
245
  $size_queried['path'] = ewww_image_optimizer_relative_path_replace( $size_queried['path'] );
246
+
247
  $sizes[ $size_queried['resize'] ] = $size_queried;
248
  // Convert here.
249
  $new_name = $this->convert( $size_queried['path'] );
255
  /* ewwwio_debug_message( print_r( $size_queried, true ) ); */
256
  if ( ewww_image_optimizer_iterable( $meta['sizes'] ) && is_array( $meta['sizes'][ $size_queried['resize'] ] ) ) {
257
  ewwwio_debug_message( 'updating regular size' );
258
+ $meta['sizes'][ $size_queried['resize'] ]['file'] = basename( $new_name );
259
  $meta['sizes'][ $size_queried['resize'] ]['mime-type'] = ewww_image_optimizer_quick_mimetype( $new_name );
260
  } elseif ( ewww_image_optimizer_iterable( $meta['custom_sizes'] ) ) {
261
  $dimensions = str_replace( 'custom-size-', '', $size_queried['resize'] );
306
  if ( $new_name ) {
307
  $this->convert_retina( $base_dir . $data['file'] );
308
  $this->convert_db_path( $base_dir . $data['file'], $new_name );
309
+ $meta['sizes'][ $size ]['file'] = basename( $new_name );
310
  $meta['sizes'][ $size ]['mime-type'] = ewww_image_optimizer_quick_mimetype( $new_name );
311
  }
312
  ewwwio_debug_message( "converted $size from meta" );
317
  // Convert sizes from a custom theme.
318
  if ( isset( $meta['image_meta']['resized_images'] ) && ewww_image_optimizer_iterable( $meta['image_meta']['resized_images'] ) ) {
319
  $imagemeta_resize_pathinfo = pathinfo( $this->file );
320
+ $imagemeta_resize_path = '';
321
  foreach ( $meta['image_meta']['resized_images'] as $index => $imagemeta_resize ) {
322
  if ( isset( $sizes[ 'resized-images-' . $index ] ) ) {
323
  continue;
324
  }
325
  $imagemeta_resize_path = $imagemeta_resize_pathinfo['dirname'] . '/' . $imagemeta_resize_pathinfo['filename'] . '-' . $imagemeta_resize . '.' . $imagemeta_resize_pathinfo['extension'];
326
+ $new_name = $this->convert( $imagemeta_resize_path );
327
  if ( $new_name ) {
328
  $this->convert_retina( $imagemeta_resize_path );
329
  $this->convert_db_path( $imagemeta_resize_path, $new_name );
336
  // and another custom theme.
337
  if ( isset( $meta['custom_sizes'] ) && ewww_image_optimizer_iterable( $meta['custom_sizes'] ) ) {
338
  $custom_sizes_pathinfo = pathinfo( $file_path );
339
+ $custom_size_path = '';
340
  foreach ( $meta['custom_sizes'] as $dimensions => $custom_size ) {
341
  if ( isset( $sizes[ 'custom-size-' . $dimensions ] ) ) {
342
  continue;
343
  }
344
  $custom_size_path = $custom_sizes_pathinfo['dirname'] . '/' . $custom_size['file'];
345
+ $new_name = $this->convert( $custom_size_path );
346
  if ( $new_name ) {
347
  $this->convert_retina( $custom_size_path );
348
  $this->convert_db_path( $custom_size_path, $new_name );
374
  $this->restore_db_path( $this->file, $this->converted, $this->id );
375
  $converted_path = $this->file;
376
  unlink( $this->file );
377
+ $this->file = $this->converted;
378
  $this->converted = $converted_path;
379
+ $meta['file'] = trailingslashit( dirname( $meta['file'] ) ) . basename( $this->file );
380
  $this->update_converted_attachment( $meta );
381
  $meta = $this->restore_sizes( $meta );
382
  return $meta;
409
  if ( empty( $size_queried['converted'] ) ) {
410
  continue;
411
  }
412
+ $size_queried['path'] = ewww_image_optimizer_relative_path_replace( $size_queried['path'] );
413
  $size_queried['converted'] = ewww_image_optimizer_relative_path_replace( $size_queried['converted'] );
414
+
415
  $new_name = ( empty( $size_queried['converted'] ) ? '' : $size_queried['converted'] );
416
  if ( $new_name && is_file( $size_queried['path'] ) && is_file( $new_name ) ) {
417
  $this->restore_db_path( $size_queried['path'], $new_name, $size_queried['id'] );
418
  $this->replace_url( $new_name, $size_queried['path'] );
419
  if ( ewww_image_optimizer_iterable( $meta['sizes'] ) && is_array( $meta['sizes'][ $size_queried['resize'] ] ) ) {
420
  ewwwio_debug_message( 'updating regular size' );
421
+ $meta['sizes'][ $size_queried['resize'] ]['file'] = basename( $new_name );
422
  $meta['sizes'][ $size_queried['resize'] ]['mime-type'] = ewww_image_optimizer_quick_mimetype( $new_name );
423
  } elseif ( ewww_image_optimizer_iterable( $meta['custom_sizes'] ) ) {
424
  $dimensions = str_replace( 'custom-size-', '', $size_queried['resize'] );
432
  if ( isset( $meta['sizes'] ) && ewww_image_optimizer_iterable( $meta['sizes'] ) ) {
433
  foreach ( $meta['sizes'] as $size => $data ) {
434
  if ( $meta['sizes'][ $size_queried['resize'] ]['height'] == $data['height'] && $meta['sizes'][ $size_queried['resize'] ]['width'] == $data['width'] ) {
435
+ $meta['sizes'][ $size ]['file'] = $meta['sizes'][ $size_queried['resize'] ]['file'];
436
  $meta['sizes'][ $size ]['mime-type'] = $meta['sizes'][ $size_queried['resize'] ]['mime-type'];
437
  }
438
  }
508
  // If the user has disabled the utility checks.
509
  if ( EWWW_IMAGE_OPTIMIZER_CLOUD ) {
510
  $skip['jpegtran'] = true;
511
+ $skip['optipng'] = true;
512
  $skip['gifsicle'] = true;
513
+ $skip['pngout'] = true;
514
  $skip['pngquant'] = true;
515
+ $skip['webp'] = true;
516
  }
517
  switch ( $type ) {
518
  case 'image/jpeg':
519
  $png_size = 0;
520
+ $newfile = $this->unique_filename( $file, '.png' );
521
  ewwwio_debug_message( "attempting to convert JPG to PNG: $newfile" );
522
  // Convert the JPG to PNG.
523
  if ( ewww_image_optimizer_gmagick_support() ) {
566
  break;
567
  case 'image/png':
568
  $jpg_size = 0;
569
+ $newfile = $this->unique_filename( $file, '.jpg' );
570
  ewwwio_debug_message( "attempting to convert PNG to JPG: $newfile" );
571
  // If the user set a fill background for transparency.
572
  $background = ewww_image_optimizer_jpg_background();
594
  try {
595
  if ( ewww_image_optimizer_png_alpha( $file ) ) {
596
  $gmagick_overlay = new Gmagick( $file );
597
+ $gmagick = new Gmagick();
598
  $gmagick->newimage( $gmagick_overlay->getimagewidth(), $gmagick_overlay->getimageheight(), '#' . $magick_background );
599
  $gmagick->compositeimage( $gmagick_overlay, 1, 0, 0 );
600
  } else {
665
  break;
666
  case 'image/gif':
667
  $png_size = 0;
668
+ $newfile = $this->unique_filename( $file, '.png' );
669
  ewwwio_debug_message( "attempting to convert GIF to PNG: $newfile" );
670
  // Convert the GIF to PNG.
671
  if ( ewww_image_optimizer_gmagick_support() ) {
735
  // Set the increment to 1 ( but allow the user to override it ).
736
  $filenum = apply_filters( 'ewww_image_optimizer_converted_filename_suffix', $this->increment );
737
  // But it must be only letters, numbers, or underscores.
738
+ $filenum = ( preg_match( '/^[\w\d]*$/', $filenum ) ? $filenum : 1 );
739
+ $suffix = ( ! empty( $filenum ) ? '-' . $filenum : '' );
740
+ $dimensions = '';
741
  $default_hidpi_suffix = apply_filters( 'ewww_image_optimizer_hidpi_suffix', '@2x' );
742
+ $hidpi_suffix = '';
743
  // See if this is a retina image, and strip the suffix.
744
  if ( preg_match( "/$default_hidpi_suffix$/", $filename ) ) {
745
  // Strip the dimensions.
746
+ $filename = str_replace( $default_hidpi_suffix, '', $filename );
747
  $hidpi_suffix = $default_hidpi_suffix;
748
  }
749
  // See if this is a resize, and strip the dimensions.
750
  if ( preg_match( '/-\d+x\d+(-\d+)*$/', $filename, $fileresize ) ) {
751
  // Strip the dimensions.
752
+ $filename = str_replace( $fileresize[0], '', $filename );
753
  $dimensions = $fileresize[0];
754
  }
755
  // While a file exists with the current increment.
796
 
797
  global $wpdb;
798
  // Retrieve any posts that link the image.
799
+ $esql = $wpdb->prepare( "SELECT ID, post_content FROM $wpdb->posts WHERE post_content LIKE %s", '%' . $wpdb->esc_like( $old_guid ) . '%' );
800
  ewwwio_debug_message( "using query: $esql" );
801
  $rows = $wpdb->get_results( $esql, ARRAY_A ); // WPCS: unprepared SQL ok.
802
  if ( ewww_image_optimizer_iterable( $rows ) ) {
846
  $id = $image_record['id'];
847
  } else { // Insert a new record.
848
  $ewwwdb->insert( $ewwwdb->ewwwio_images, array(
849
+ 'path' => ewww_image_optimizer_relative_path_remove( $new_path ),
850
+ 'converted' => ewww_image_optimizer_relative_path_remove( $path ),
851
+ 'orig_size' => filesize( $new_path ),
852
  'attachment_id' => $this->attachment_id,
853
+ 'results' => __( 'No savings', 'ewww-image-optimizer' ),
854
+ 'updated' => date( 'Y-m-d H:i:s' ),
855
+ 'updates' => 0,
856
  ) );
857
  return;
858
  }
859
  }
860
  $ewwwdb->update( $ewwwdb->ewwwio_images,
861
  array(
862
+ 'path' => ewww_image_optimizer_relative_path_remove( $new_path ),
863
  'converted' => ewww_image_optimizer_relative_path_remove( $path ),
864
+ 'results' => ewww_image_optimizer_image_results( $image_record['orig_size'], filesize( $new_path ) ),
865
+ 'updates' => 0,
866
+ 'trace' => '',
867
  ),
868
  array(
869
  'id' => $id,
902
  }
903
  $ewwwdb->update( $ewwwdb->ewwwio_images,
904
  array(
905
+ 'path' => ewww_image_optimizer_relative_path_remove( $new_path ),
906
+ 'converted' => '',
907
  'image_size' => 0,
908
+ 'results' => __( 'Original Restored', 'ewww-image-optimizer' ),
909
+ 'updates' => 0,
910
+ 'trace' => '',
911
+ 'level' => null,
912
  ),
913
  array(
914
  'id' => $id,
925
  */
926
  public function time_estimate() {
927
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
928
+ $time = 0;
929
+ $type = ewww_image_optimizer_quick_mimetype( $this->file );
930
  $image_size = ( empty( $this->opt_size ) ? $this->orig_size : $this->opt_size );
931
  if ( empty( $image_size ) ) {
932
  $this->orig_size = filesize( $this->file );
933
+ $image_size = $this->orig_size;
934
  }
935
  switch ( $type ) {
936
  case 'image/jpeg':
classes/class-ewww-nextcellent.php CHANGED
@@ -87,8 +87,8 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
87
  function ewww_added_new_image( $id, $meta ) {
88
  global $ewww_image;
89
  // Retrieve the image path.
90
- $file_path = $meta->image->imagePath;
91
- $ewww_image = new EWWW_Image( $id, 'nextcell', $file_path );
92
  $ewww_image->resize = 'full';
93
  // Run the optimizer on the current image.
94
  $fres = ewww_image_optimizer( $file_path, 2, false, false, true );
@@ -117,8 +117,8 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
117
  // If we have a path to work with.
118
  if ( $gallery_path ) {
119
  // Construct the absolute path of the current image.
120
- $file_path = trailingslashit( $gallery_path ) . $image['filename'];
121
- $ewww_image = new EWWW_Image( $image['id'], 'nextcell', $file_path );
122
  $ewww_image->resize = 'full';
123
  // Run the optimizer on the current image.
124
  $res = ewww_image_optimizer( ABSPATH . $file_path, 2, false, false, true );
@@ -147,7 +147,7 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
147
  } elseif ( ! empty( $_POST['image'] ) && is_numeric( $_POST['image'] ) ) {
148
  $id = (int) $_POST['image'];
149
  }
150
- $ewww_image = new EWWW_Image( $id, 'nextcell', $filename );
151
  $ewww_image->resize = 'thumbnail';
152
  ewww_image_optimizer( $filename );
153
  }
@@ -165,6 +165,7 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
165
  if ( ! wp_doing_ajax() ) {
166
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
167
  }
 
168
  wp_die( json_encode( array(
169
  'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
170
  ) ) );
@@ -174,6 +175,7 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
174
  if ( ! wp_doing_ajax() ) {
175
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
176
  }
 
177
  wp_die( json_encode( array(
178
  'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ),
179
  ) ) );
@@ -184,6 +186,7 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
184
  if ( ! wp_doing_ajax() ) {
185
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
186
  }
 
187
  wp_die( json_encode( array(
188
  'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
189
  ) ) );
@@ -198,7 +201,8 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
198
  wp_redirect( $sendback );
199
  die;
200
  }
201
- die( json_encode( array(
 
202
  'success' => $success,
203
  ) ) );
204
  }
@@ -213,6 +217,7 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
213
  if ( ! wp_doing_ajax() ) {
214
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
215
  }
 
216
  wp_die( json_encode( array(
217
  'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
218
  ) ) );
@@ -222,6 +227,7 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
222
  if ( ! wp_doing_ajax() ) {
223
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
224
  }
 
225
  wp_die( json_encode( array(
226
  'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ),
227
  ) ) );
@@ -232,13 +238,15 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
232
  if ( ! wp_doing_ajax() ) {
233
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
234
  }
 
235
  wp_die( json_encode( array(
236
  'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
237
  ) ) );
238
  }
239
  ewww_image_optimizer_cloud_restore_from_meta_data( $id, 'nextcell' );
240
  $success = $this->ewww_manage_image_custom_column( 'ewww_image_optimizer', $id, true );
241
- die( json_encode( array(
 
242
  'success' => $success,
243
  ) ) );
244
  }
@@ -264,8 +272,8 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
264
  // Retrieve the metadata for the image.
265
  $meta = new nggMeta( $id );
266
  // Retrieve the image path.
267
- $file_path = $meta->image->imagePath;
268
- $ewww_image = new EWWW_Image( $id, 'nextcell', $file_path );
269
  $ewww_image->resize = 'full';
270
  // Run the optimizer on the current image.
271
  $fres = ewww_image_optimizer( $file_path, 2, false, false, true );
@@ -275,8 +283,8 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
275
  'ewww_image_optimizer' => $fres[1],
276
  ) );
277
  // Get the filepath of the thumbnail image.
278
- $thumb_path = $meta->image->thumbPath;
279
- $ewww_image = new EWWW_Image( $id, 'nextcell', $thumb_path );
280
  $ewww_image->resize = 'thumbnail';
281
  // Run the optimization on the thumbnail.
282
  $tres = ewww_image_optimizer( $thumb_path, 2, false, true );
@@ -308,11 +316,9 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
308
  // Need this file to work with metadata.
309
  require_once( WP_CONTENT_DIR . '/plugins/nextcellent-gallery-nextgen-legacy/lib/meta.php' );
310
  // Get the metadata for the image.
311
- $meta = new nggMeta( $id );
312
- // Get the optimization status for the image.
313
- $status = $meta->get_META( 'ewww_image_optimizer' );
314
  $output = "<div id='ewww-nextcellent-status-$id'>";
315
- $msg = '';
316
  // Get the file path of the image.
317
  $file_path = $meta->image->imagePath;
318
  // Get the mimetype of the image.
@@ -357,14 +363,14 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
357
  echo $msg;
358
  return;
359
  }
360
- if ( ! empty( $status ) ) {
361
  ewww_image_optimizer_update_file_from_meta( $file_path, 'nextcell', $id, 'full' );
362
  $thumb_path = $meta->image->thumbPath;
363
  ewww_image_optimizer_update_file_from_meta( $thumb_path, 'nextcell', $id, 'thumbnail' );
364
  }
365
  $backup_available = false;
366
  global $wpdb;
367
- $optimized_images = $wpdb->get_results( $wpdb->prepare( "SELECT image_size,orig_size,resize,converted,level,backup,updated FROM $wpdb->ewwwio_images WHERE attachment_id = %d AND gallery = 'nextcell' AND image_size <> 0 ORDER BY orig_size DESC", $id ), ARRAY_A );
368
  $ewww_manual_nonce = wp_create_nonce( 'ewww-manual-' . $id );
369
  // If we have a valid status, display it, the image size, and give a re-optimize link.
370
  if ( ! empty( $optimized_images ) ) {
@@ -492,7 +498,7 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
492
  }
493
  echo '</div></div>';
494
  if ( ! empty( $_REQUEST['ewww_inline'] ) ) {
495
- die();
496
  }
497
  return;
498
  }
@@ -543,7 +549,7 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
543
  global $nggdb;
544
  // Reset the resume status, not allowed here.
545
  update_option( 'ewww_image_optimizer_bulk_ngg_resume', '' );
546
- $ids = array();
547
  $gids = array_map( 'intval', $_REQUEST['doaction'] );
548
  // For each gallery we are given.
549
  foreach ( $gids as $gid ) {
@@ -580,15 +586,15 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
580
  wp_enqueue_style( 'ngg-jqueryui' );
581
  // Include all the vars we need for javascript.
582
  wp_localize_script( 'ewwwbulkscript', 'ewww_vars', array(
583
- '_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-bulk' ),
584
- 'gallery' => 'nextgen',
585
- 'attachments' => count( $images ),
586
- 'scan_fail' => esc_html__( 'Operation timed out, you may need to increase the max_execution_time for PHP', 'ewww-image-optimizer' ),
587
- 'operation_stopped' => esc_html__( 'Optimization stopped, reload page to resume.', 'ewww-image-optimizer' ),
588
  'operation_interrupted' => esc_html__( 'Operation Interrupted', 'ewww-image-optimizer' ),
589
- 'temporary_failure' => esc_html__( 'Temporary failure, seconds left to retry:', 'ewww-image-optimizer' ),
590
- 'remove_failed' => esc_html__( 'Could not remove image from table.', 'ewww-image-optimizer' ),
591
- 'optimized' => esc_html__( 'Optimized', 'ewww-image-optimizer' ),
592
  ) );
593
  }
594
 
@@ -597,10 +603,12 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
597
  */
598
  function ewww_ngg_bulk_init() {
599
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
 
600
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
601
- wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
 
 
602
  }
603
- $output = array();
604
  // Toggle the resume flag to indicate an operation is in progress.
605
  update_option( 'ewww_image_optimizer_bulk_ngg_resume', 'true' );
606
  // Get the list of attachments remaining from the db.
@@ -610,10 +618,10 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
610
  }
611
  if ( ! is_array( $attachments ) ) {
612
  $output['error'] = esc_html__( 'Error retrieving list of images' );
613
- echo json_encode( $output );
614
- die();
615
  }
616
- $id = array_shift( $attachments );
617
  $file_name = $this->ewww_ngg_bulk_filename( $id );
618
  // Let the user know we are starting.
619
  $loading_image = plugins_url( '/images/wpspin.gif', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE );
@@ -622,8 +630,8 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
622
  } else {
623
  $output['results'] = '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . ' <b>' . $file_name . "</b>&nbsp;<img src='$loading_image' alt='loading'/></p>";
624
  }
625
- echo json_encode( $output );
626
- die();
627
  }
628
 
629
  /**
@@ -652,13 +660,13 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
652
  */
653
  function ewww_ngg_bulk_loop() {
654
  global $ewww_defer;
655
- $ewww_defer = false;
656
- $output = array();
657
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
658
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
659
  $outupt['error'] = esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' );
660
- echo json_encode( $output );
661
- die();
662
  }
663
  session_write_close();
664
  // Find out if our nonce is on it's last leg/tick.
@@ -673,14 +681,14 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
673
  // Find out what time we started, in microseconds.
674
  $started = microtime( true );
675
  // Get the list of attachments remaining from the db.
676
- $attachments = get_option( 'ewww_image_optimizer_bulk_ngg_attachments' );
677
- $id = array_shift( $attachments );
678
  list( $fres, $tres ) = $this->ewww_ngg_optimize( $id );
679
- $ewww_status = get_transient( 'ewww_image_optimizer_cloud_status' );
680
  if ( ! empty( $ewww_status ) && preg_match( '/exceeded/', $ewww_status ) ) {
681
  $output['error'] = esc_html__( 'License Exceeded', 'ewww-image-optimizer' );
682
- echo json_encode( $output );
683
- die();
684
  }
685
  // Output the results of the optimization.
686
  if ( $fres[0] ) {
@@ -694,14 +702,14 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
694
  // Output how much time we spent.
695
  $elapsed = microtime( true ) - $started;
696
  /* Translators: %s: localized number of seconds */
697
- $output['results'] .= sprintf( esc_html( _n( 'Elapsed: %s second', 'Elapsed: %s seconds', $elapsed, 'ewww-image-optimizer' ) ) . '</p>', number_format_i18n( $elapsed ) );
698
  $output['completed'] = 1;
699
  // Store the list back in the db.
700
  update_option( 'ewww_image_optimizer_bulk_ngg_attachments', $attachments, false );
701
  if ( ! empty( $attachments ) ) {
702
  $next_attachment = array_shift( $attachments );
703
- $next_file = $this->ewww_ngg_bulk_filename( $next_attachment );
704
- $loading_image = plugins_url( '/images/wpspin.gif', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE );
705
  if ( $next_file ) {
706
  $output['next_file'] = '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . " <b>$next_file</b>&nbsp;<img src='$loading_image' alt='loading'/></p>";
707
  } else {
@@ -710,7 +718,8 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
710
  } else {
711
  $output['done'] = 1;
712
  }
713
- die( json_encode( $output ) );
 
714
  }
715
 
716
  /**
@@ -719,14 +728,15 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
719
  function ewww_ngg_bulk_cleanup() {
720
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
721
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
 
722
  wp_die( esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) );
723
  }
724
  // Reset all the bulk options in the db...
725
  update_option( 'ewww_image_optimizer_bulk_ngg_resume', '' );
726
  update_option( 'ewww_image_optimizer_bulk_ngg_attachments', '', false );
727
  // and let the user know we are done.
728
- echo '<p><b>' . esc_html__( 'Finished Optimization!', 'ewww-image-optimizer' ) . '</b></p>';
729
- die();
730
  }
731
 
732
  /**
@@ -735,7 +745,7 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
735
  * @param string $hook The hook value for the current page.
736
  */
737
  function ewww_ngg_manual_actions_script( $hook ) {
738
- if ( 'galleries_page_nggallery-manage-gallery' != $hook ) {
739
  return;
740
  }
741
  if ( ! current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
@@ -751,7 +761,7 @@ if ( ! class_exists( 'EWWW_Nextcellent' ) ) {
751
  'ewww_vars',
752
  array(
753
  'optimizing' => '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . " <img src='$loading_image' /></p>",
754
- 'restoring' => '<p>' . esc_html__( 'Restoring', 'ewww-image-optimizer' ) . " <img src='$loading_image' /></p>",
755
  )
756
  );
757
  }
87
  function ewww_added_new_image( $id, $meta ) {
88
  global $ewww_image;
89
  // Retrieve the image path.
90
+ $file_path = $meta->image->imagePath;
91
+ $ewww_image = new EWWW_Image( $id, 'nextcell', $file_path );
92
  $ewww_image->resize = 'full';
93
  // Run the optimizer on the current image.
94
  $fres = ewww_image_optimizer( $file_path, 2, false, false, true );
117
  // If we have a path to work with.
118
  if ( $gallery_path ) {
119
  // Construct the absolute path of the current image.
120
+ $file_path = trailingslashit( $gallery_path ) . $image['filename'];
121
+ $ewww_image = new EWWW_Image( $image['id'], 'nextcell', $file_path );
122
  $ewww_image->resize = 'full';
123
  // Run the optimizer on the current image.
124
  $res = ewww_image_optimizer( ABSPATH . $file_path, 2, false, false, true );
147
  } elseif ( ! empty( $_POST['image'] ) && is_numeric( $_POST['image'] ) ) {
148
  $id = (int) $_POST['image'];
149
  }
150
+ $ewww_image = new EWWW_Image( $id, 'nextcell', $filename );
151
  $ewww_image->resize = 'thumbnail';
152
  ewww_image_optimizer( $filename );
153
  }
165
  if ( ! wp_doing_ajax() ) {
166
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
167
  }
168
+ ewwwio_ob_clean();
169
  wp_die( json_encode( array(
170
  'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
171
  ) ) );
175
  if ( ! wp_doing_ajax() ) {
176
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
177
  }
178
+ ewwwio_ob_clean();
179
  wp_die( json_encode( array(
180
  'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ),
181
  ) ) );
186
  if ( ! wp_doing_ajax() ) {
187
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
188
  }
189
+ ewwwio_ob_clean();
190
  wp_die( json_encode( array(
191
  'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
192
  ) ) );
201
  wp_redirect( $sendback );
202
  die;
203
  }
204
+ ewwwio_ob_clean();
205
+ wp_die( json_encode( array(
206
  'success' => $success,
207
  ) ) );
208
  }
217
  if ( ! wp_doing_ajax() ) {
218
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
219
  }
220
+ ewwwio_ob_clean();
221
  wp_die( json_encode( array(
222
  'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
223
  ) ) );
227
  if ( ! wp_doing_ajax() ) {
228
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
229
  }
230
+ ewwwio_ob_clean();
231
  wp_die( json_encode( array(
232
  'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ),
233
  ) ) );
238
  if ( ! wp_doing_ajax() ) {
239
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
240
  }
241
+ ewwwio_ob_clean();
242
  wp_die( 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( json_encode( array(
250
  'success' => $success,
251
  ) ) );
252
  }
272
  // Retrieve the metadata for the image.
273
  $meta = new nggMeta( $id );
274
  // Retrieve the image path.
275
+ $file_path = $meta->image->imagePath;
276
+ $ewww_image = new EWWW_Image( $id, 'nextcell', $file_path );
277
  $ewww_image->resize = 'full';
278
  // Run the optimizer on the current image.
279
  $fres = ewww_image_optimizer( $file_path, 2, false, false, true );
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 );
288
  $ewww_image->resize = 'thumbnail';
289
  // Run the optimization on the thumbnail.
290
  $tres = ewww_image_optimizer( $thumb_path, 2, false, true );
316
  // Need this file to work with metadata.
317
  require_once( WP_CONTENT_DIR . '/plugins/nextcellent-gallery-nextgen-legacy/lib/meta.php' );
318
  // Get the metadata for the image.
319
+ $meta = new nggMeta( $id );
 
 
320
  $output = "<div id='ewww-nextcellent-status-$id'>";
321
+ $msg = '';
322
  // Get the file path of the image.
323
  $file_path = $meta->image->imagePath;
324
  // Get the mimetype of the image.
363
  echo $msg;
364
  return;
365
  }
366
+ if ( ! empty( $meta->image->meta_data['ewww_image_optimizer'] ) ) {
367
  ewww_image_optimizer_update_file_from_meta( $file_path, 'nextcell', $id, 'full' );
368
  $thumb_path = $meta->image->thumbPath;
369
  ewww_image_optimizer_update_file_from_meta( $thumb_path, 'nextcell', $id, 'thumbnail' );
370
  }
371
  $backup_available = false;
372
  global $wpdb;
373
+ $optimized_images = $wpdb->get_results( $wpdb->prepare( "SELECT image_size,orig_size,resize,converted,level,backup,updated FROM $wpdb->ewwwio_images WHERE attachment_id = %d AND gallery = 'nextcell' AND image_size <> 0 ORDER BY orig_size DESC", $id ), ARRAY_A );
374
  $ewww_manual_nonce = wp_create_nonce( 'ewww-manual-' . $id );
375
  // If we have a valid status, display it, the image size, and give a re-optimize link.
376
  if ( ! empty( $optimized_images ) ) {
498
  }
499
  echo '</div></div>';
500
  if ( ! empty( $_REQUEST['ewww_inline'] ) ) {
501
+ wp_die();
502
  }
503
  return;
504
  }
549
  global $nggdb;
550
  // Reset the resume status, not allowed here.
551
  update_option( 'ewww_image_optimizer_bulk_ngg_resume', '' );
552
+ $ids = array();
553
  $gids = array_map( 'intval', $_REQUEST['doaction'] );
554
  // For each gallery we are given.
555
  foreach ( $gids as $gid ) {
586
  wp_enqueue_style( 'ngg-jqueryui' );
587
  // Include all the vars we need for javascript.
588
  wp_localize_script( 'ewwwbulkscript', 'ewww_vars', array(
589
+ '_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-bulk' ),
590
+ 'gallery' => 'nextgen',
591
+ 'attachments' => count( $images ),
592
+ 'scan_fail' => esc_html__( 'Operation timed out, you may need to increase the max_execution_time for PHP', 'ewww-image-optimizer' ),
593
+ 'operation_stopped' => esc_html__( 'Optimization stopped, reload page to resume.', 'ewww-image-optimizer' ),
594
  'operation_interrupted' => esc_html__( 'Operation Interrupted', 'ewww-image-optimizer' ),
595
+ 'temporary_failure' => esc_html__( 'Temporary failure, seconds left to retry:', 'ewww-image-optimizer' ),
596
+ 'remove_failed' => esc_html__( 'Could not remove image from table.', 'ewww-image-optimizer' ),
597
+ 'optimized' => esc_html__( 'Optimized', 'ewww-image-optimizer' ),
598
  ) );
599
  }
600
 
603
  */
604
  function ewww_ngg_bulk_init() {
605
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
606
+ $output = array();
607
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
608
+ $output['error'] = esc_html__( 'Access denied.', 'ewww-image-optimizer' );
609
+ ewwwio_ob_clean();
610
+ wp_die( json_encode( $output ) );
611
  }
 
612
  // Toggle the resume flag to indicate an operation is in progress.
613
  update_option( 'ewww_image_optimizer_bulk_ngg_resume', 'true' );
614
  // Get the list of attachments remaining from the db.
618
  }
619
  if ( ! is_array( $attachments ) ) {
620
  $output['error'] = esc_html__( 'Error retrieving list of images' );
621
+ ewwwio_ob_clean();
622
+ wp_die( json_encode( $output ) );
623
  }
624
+ $id = array_shift( $attachments );
625
  $file_name = $this->ewww_ngg_bulk_filename( $id );
626
  // Let the user know we are starting.
627
  $loading_image = plugins_url( '/images/wpspin.gif', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE );
630
  } else {
631
  $output['results'] = '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . ' <b>' . $file_name . "</b>&nbsp;<img src='$loading_image' alt='loading'/></p>";
632
  }
633
+ ewwwio_ob_clean();
634
+ wp_die( json_encode( $output ) );
635
  }
636
 
637
  /**
660
  */
661
  function ewww_ngg_bulk_loop() {
662
  global $ewww_defer;
663
+ $ewww_defer = false;
664
+ $output = array();
665
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
666
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
667
  $outupt['error'] = esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' );
668
+ ewwwio_ob_clean();
669
+ wp_die( json_encode( $output ) );
670
  }
671
  session_write_close();
672
  // Find out if our nonce is on it's last leg/tick.
681
  // Find out what time we started, in microseconds.
682
  $started = microtime( true );
683
  // Get the list of attachments remaining from the db.
684
+ $attachments = get_option( 'ewww_image_optimizer_bulk_ngg_attachments' );
685
+ $id = array_shift( $attachments );
686
  list( $fres, $tres ) = $this->ewww_ngg_optimize( $id );
687
+ $ewww_status = get_transient( 'ewww_image_optimizer_cloud_status' );
688
  if ( ! empty( $ewww_status ) && preg_match( '/exceeded/', $ewww_status ) ) {
689
  $output['error'] = esc_html__( 'License Exceeded', 'ewww-image-optimizer' );
690
+ ewwwio_ob_clean();
691
+ wp_die( json_encode( $output ) );
692
  }
693
  // Output the results of the optimization.
694
  if ( $fres[0] ) {
702
  // Output how much time we spent.
703
  $elapsed = microtime( true ) - $started;
704
  /* Translators: %s: localized number of seconds */
705
+ $output['results'] .= sprintf( esc_html( _n( 'Elapsed: %s second', 'Elapsed: %s seconds', $elapsed, 'ewww-image-optimizer' ) ) . '</p>', number_format_i18n( $elapsed ) );
706
  $output['completed'] = 1;
707
  // Store the list back in the db.
708
  update_option( 'ewww_image_optimizer_bulk_ngg_attachments', $attachments, false );
709
  if ( ! empty( $attachments ) ) {
710
  $next_attachment = array_shift( $attachments );
711
+ $next_file = $this->ewww_ngg_bulk_filename( $next_attachment );
712
+ $loading_image = plugins_url( '/images/wpspin.gif', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE );
713
  if ( $next_file ) {
714
  $output['next_file'] = '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . " <b>$next_file</b>&nbsp;<img src='$loading_image' alt='loading'/></p>";
715
  } else {
718
  } else {
719
  $output['done'] = 1;
720
  }
721
+ ewwwio_ob_clean();
722
+ wp_die( json_encode( $output ) );
723
  }
724
 
725
  /**
728
  function ewww_ngg_bulk_cleanup() {
729
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
730
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
731
+ ewwwio_ob_clean();
732
  wp_die( esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) );
733
  }
734
  // Reset all the bulk options in the db...
735
  update_option( 'ewww_image_optimizer_bulk_ngg_resume', '' );
736
  update_option( 'ewww_image_optimizer_bulk_ngg_attachments', '', false );
737
  // and let the user know we are done.
738
+ ewwwio_ob_clean();
739
+ wp_die( '<p><b>' . esc_html__( 'Finished Optimization!', 'ewww-image-optimizer' ) . '</b></p>' );
740
  }
741
 
742
  /**
745
  * @param string $hook The hook value for the current page.
746
  */
747
  function ewww_ngg_manual_actions_script( $hook ) {
748
+ if ( 'galleries_page_nggallery-manage' != $hook ) {
749
  return;
750
  }
751
  if ( ! current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
761
  'ewww_vars',
762
  array(
763
  'optimizing' => '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . " <img src='$loading_image' /></p>",
764
+ 'restoring' => '<p>' . esc_html__( 'Restoring', 'ewww-image-optimizer' ) . " <img src='$loading_image' /></p>",
765
  )
766
  );
767
  }
classes/class-ewww-nextgen.php CHANGED
@@ -67,12 +67,12 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
67
  // Creating the 'registry' object for working with nextgen.
68
  $registry = C_Component_Registry::get_instance();
69
  // Creating a database storage object from the 'registry' object.
70
- $storage = $registry->get_utility( 'I_Gallery_Storage' );
71
  }
72
  // Find the image id.
73
  if ( is_array( $image ) ) {
74
  $image_id = $image['id'];
75
- $image = $storage->object->_image_mapper->find( $image_id, true );
76
  } else {
77
  $image_id = $storage->object->_get_image_id( $image );
78
  }
@@ -107,13 +107,13 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
107
  // Creating the 'registry' object for working with nextgen.
108
  $registry = C_Component_Registry::get_instance();
109
  // Creating a database storage object from the 'registry' object.
110
- $storage = $registry->get_utility( 'I_Gallery_Storage' );
111
  }
112
  global $ewww_image;
113
  // Find the image id.
114
  if ( is_array( $image ) ) {
115
  $image_id = $image['id'];
116
- $image = $storage->object->_image_mapper->find( $image_id, true );
117
  } else {
118
  $image_id = $storage->object->_get_image_id( $image );
119
  }
@@ -131,7 +131,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
131
  // Get the absolute path.
132
  $file_path = $storage->get_image_abspath( $image, $size );
133
  ewwwio_debug_message( "optimizing (nextgen): $file_path" );
134
- $ewww_image = new EWWW_Image( $image_id, 'nextgen', $file_path );
135
  $ewww_image->resize = $size;
136
  // Optimize the image and grab the results.
137
  $res = ewww_image_optimizer( $file_path, 2, false, false, $full_size );
@@ -163,9 +163,9 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
163
  // Creating the 'registry' object for working with nextgen.
164
  $registry = C_Component_Registry::get_instance();
165
  // Creating a database storage object from the 'registry' object.
166
- $storage = $registry->get_utility( 'I_Gallery_Storage' );
167
- $filename = $storage->get_image_abspath( $image, $size );
168
- $ewww_image = new EWWW_Image( $image->pid, 'nextgen', $filename );
169
  $ewww_image->resize = $size;
170
  if ( file_exists( $filename ) ) {
171
  ewww_image_optimizer( $filename, 2 );
@@ -186,6 +186,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
186
  if ( ! wp_doing_ajax() ) {
187
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
188
  }
 
189
  wp_die( json_encode( array(
190
  'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
191
  ) ) );
@@ -195,6 +196,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
195
  if ( ! wp_doing_ajax() ) {
196
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
197
  }
 
198
  wp_die( json_encode( array(
199
  'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ),
200
  ) ) );
@@ -203,8 +205,9 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
203
  $id = intval( $_REQUEST['ewww_attachment_ID'] );
204
  if ( empty( $_REQUEST['ewww_manual_nonce'] ) || ! wp_verify_nonce( $_REQUEST['ewww_manual_nonce'], "ewww-manual-$id" ) ) {
205
  if ( ! wp_doing_ajax() ) {
206
- wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
207
  }
 
208
  wp_die( json_encode( array(
209
  'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
210
  ) ) );
@@ -212,13 +215,14 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
212
  // Creating the 'registry' object for working with nextgen.
213
  $registry = C_Component_Registry::get_instance();
214
  // Creating a database storage object from the 'registry' object.
215
- $storage = $registry->get_utility( 'I_Gallery_Storage' );
216
  // Get an image object.
217
- $image = $storage->object->_image_mapper->find( $id );
218
- $image = $this->ewww_added_new_image( $image, $storage );
219
  $success = $this->ewww_manage_image_custom_column( '', $image );
220
  if ( get_transient( 'ewww_image_optimizer_cloud_status' ) == 'exceeded' || ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_exceeded' ) > time() ) {
221
- die( json_encode( array(
 
222
  'error' => esc_html__( 'License exceeded', 'ewww-image-optimizer' ),
223
  ) ) );
224
  }
@@ -229,7 +233,8 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
229
  wp_redirect( $sendback );
230
  die;
231
  }
232
- die( json_encode( array(
 
233
  'success' => $success,
234
  ) ) );
235
  }
@@ -244,6 +249,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
244
  if ( ! wp_doing_ajax() ) {
245
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
246
  }
 
247
  wp_die( json_encode( array(
248
  'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
249
  ) ) );
@@ -253,6 +259,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
253
  if ( ! wp_doing_ajax() ) {
254
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
255
  }
 
256
  wp_die( json_encode( array(
257
  'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ),
258
  ) ) );
@@ -263,6 +270,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
263
  if ( ! wp_doing_ajax() ) {
264
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
265
  }
 
266
  wp_die( json_encode( array(
267
  'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
268
  ) ) );
@@ -270,12 +278,13 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
270
  // Creating the 'registry' object for working with nextgen.
271
  $registry = C_Component_Registry::get_instance();
272
  // Creating a database storage object from the 'registry' object.
273
- $storage = $registry->get_utility( 'I_Gallery_Storage' );
274
  // Get an image object.
275
  $image = $storage->object->_image_mapper->find( $id );
276
  ewww_image_optimizer_cloud_restore_from_meta_data( $image->pid, 'nextgen' );
277
  $success = $this->ewww_manage_image_custom_column( '', $image );
278
- die( json_encode( array(
 
279
  'success' => $success,
280
  ) ) );
281
  }
@@ -302,7 +311,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
302
  'ewww_vars',
303
  array(
304
  'optimizing' => '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' /></p>",
305
- 'restoring' => '<p>' . esc_html__( 'Restoring', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' /></p>",
306
  )
307
  );
308
  }
@@ -350,7 +359,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
350
  // Creating the 'registry' object for working with nextgen.
351
  $registry = C_Component_Registry::get_instance();
352
  // Creating a database storage object from the 'registry' object.
353
- $storage = $registry->get_utility( 'I_Gallery_Storage' );
354
  if ( is_object( $id ) ) {
355
  $image = $id;
356
  } else {
@@ -361,7 +370,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
361
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) && ewww_image_optimizer_function_exists( 'print_r' ) ) {
362
  $print_meta = print_r( $image->meta_data, true );
363
  $print_meta = preg_replace( array( '/ /', '/\n+/' ), array( '&nbsp;', '<br />' ), esc_html( $print_meta ) );
364
- $output .= '<div style="background-color:#ffff99;font-size: 10px;padding: 10px;margin:-10px -10px 10px;line-height: 1.1em">' . $print_meta . '</div>';
365
  }
366
  $msg = '';
367
  // Get the absolute path.
@@ -603,7 +612,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
603
  echo '<div style="background-color:#ffff99;">' . $ewww_debug . '</div>';
604
  }
605
  if ( ! empty( $_REQUEST['ewww_inline'] ) ) {
606
- die();
607
  }
608
  return;
609
  }
@@ -656,7 +665,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
656
  global $nggdb;
657
  // Reset the resume status, not allowed here.
658
  update_option( 'ewww_image_optimizer_bulk_ngg_resume', '' );
659
- $ids = array();
660
  $gids = array_map( 'intval', $_REQUEST['doaction'] );
661
  // For each gallery we are given.
662
  foreach ( $gids as $gid ) {
@@ -691,15 +700,15 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
691
  wp_enqueue_style( 'jquery-ui-nextgen' );
692
  // Include all the vars we need for javascript.
693
  wp_localize_script( 'ewwwbulkscript', 'ewww_vars', array(
694
- '_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-bulk' ),
695
- 'gallery' => 'nextgen',
696
- 'attachments' => count( $images ),
697
- 'scan_fail' => esc_html__( 'Operation timed out, you may need to increase the max_execution_time for PHP', 'ewww-image-optimizer' ),
698
- 'operation_stopped' => esc_html__( 'Optimization stopped, reload page to resume.', 'ewww-image-optimizer' ),
699
  'operation_interrupted' => esc_html__( 'Operation Interrupted', 'ewww-image-optimizer' ),
700
- 'temporary_failure' => esc_html__( 'Temporary failure, seconds left to retry:', 'ewww-image-optimizer' ),
701
- 'remove_failed' => esc_html__( 'Could not remove image from table.', 'ewww-image-optimizer' ),
702
- 'optimized' => esc_html__( 'Optimized', 'ewww-image-optimizer' ),
703
  ) );
704
  }
705
 
@@ -708,10 +717,12 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
708
  */
709
  function ewww_ngg_bulk_init() {
710
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
 
711
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
712
- wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
 
 
713
  }
714
- $output = array();
715
  // Toggle the resume flag to indicate an operation is in progress.
716
  update_option( 'ewww_image_optimizer_bulk_ngg_resume', 'true' );
717
  $attachments = get_option( 'ewww_image_optimizer_bulk_ngg_attachments' );
@@ -720,19 +731,19 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
720
  }
721
  if ( ! is_array( $attachments ) ) {
722
  $output['error'] = esc_html__( 'Error retrieving list of images' );
723
- echo json_encode( $output );
724
- die();
725
  }
726
- $id = array_shift( $attachments );
727
- $file = $this->ewww_ngg_bulk_filename( $id );
728
  $loading_image = plugins_url( '/images/wpspin.gif', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE );
729
  if ( empty( $file ) ) {
730
  $output['results'] = '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' alt='loading'/></p>";
731
  } else {
732
  $output['results'] = '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . " <b>$file</b>&nbsp;<img src='$loading_image' alt='loading'/></p>";
733
  }
734
- echo json_encode( $output );
735
- die();
736
  }
737
 
738
  /**
@@ -745,7 +756,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
745
  // Creating the 'registry' object for working with nextgen.
746
  $registry = C_Component_Registry::get_instance();
747
  // Creating a database storage object from the 'registry' object.
748
- $storage = $registry->get_utility( 'I_Gallery_Storage' );
749
  // Get an image object.
750
  $image = $storage->object->_image_mapper->find( $id );
751
  // Get the filename for the image, and output our current status.
@@ -764,13 +775,13 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
764
  */
765
  function ewww_ngg_bulk_loop() {
766
  global $ewww_defer;
767
- $ewww_defer = false;
768
- $output = array();
769
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
770
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
771
  $output['error'] = esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' );
772
- echo json_encode( $output );
773
- die();
774
  }
775
  session_write_close();
776
  // Find out if our nonce is on it's last leg/tick.
@@ -784,19 +795,19 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
784
  $started = microtime( true );
785
  // Get the list of attachments remaining from the db.
786
  $attachments = get_option( 'ewww_image_optimizer_bulk_ngg_attachments' );
787
- $id = array_shift( $attachments );
788
  // Creating the 'registry' object for working with nextgen.
789
  $registry = C_Component_Registry::get_instance();
790
  // Creating a database storage object from the 'registry' object.
791
- $storage = $registry->get_utility( 'I_Gallery_Storage' );
792
  // Get an image object.
793
- $image = $storage->object->_image_mapper->find( $id );
794
- $image = $this->ewww_added_new_image( $image, $storage );
795
  $ewww_status = get_transient( 'ewww_image_optimizer_cloud_status' );
796
  if ( ! empty( $ewww_status ) && preg_match( '/exceeded/', $ewww_status ) ) {
797
  $output['error'] = esc_html__( 'License Exceeded', 'ewww-image-optimizer' );
798
- echo json_encode( $output );
799
- die();
800
  }
801
  // Output the results of the optimization.
802
  $output['results'] = sprintf( '<p>' . esc_html__( 'Optimized image:', 'ewww-image-optimizer' ) . ' <strong>%s</strong><br>', esc_html( basename( $storage->object->get_image_abspath( $image, 'full' ) ) ) );
@@ -821,14 +832,14 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
821
  // Output how much time we spent.
822
  $elapsed = microtime( true ) - $started;
823
  /* Translators: %s: The localized number of seconds */
824
- $output['results'] .= sprintf( esc_html( _n( 'Elapsed: %s second', 'Elapsed: %s seconds', $elapsed, 'ewww-image-optimizer' ) ) . '</p>', number_format_i18n( $elapsed ) );
825
  $output['completed'] = 1;
826
  // Store the list back in the db.
827
  update_option( 'ewww_image_optimizer_bulk_ngg_attachments', $attachments, false );
828
  if ( ! empty( $attachments ) ) {
829
  $next_attachment = array_shift( $attachments );
830
- $next_file = $this->ewww_ngg_bulk_filename( $next_attachment );
831
- $loading_image = plugins_url( '/images/wpspin.gif', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE );
832
  if ( $next_file ) {
833
  $output['next_file'] = '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . " <b>$next_file</b>&nbsp;<img src='$loading_image' alt='loading'/></p>";
834
  } else {
@@ -837,7 +848,8 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
837
  } else {
838
  $output['done'] = 1;
839
  }
840
- die( json_encode( $output ) );
 
841
  }
842
 
843
  /**
@@ -846,13 +858,14 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
846
  function ewww_ngg_bulk_cleanup() {
847
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
848
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
 
849
  wp_die( esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) );
850
  }
851
  // Reset all the bulk options in the db.
852
  update_option( 'ewww_image_optimizer_bulk_ngg_resume', '' );
853
  update_option( 'ewww_image_optimizer_bulk_ngg_attachments', '', false );
854
- echo '<p><b>' . esc_html__( 'Finished Optimization!', 'ewww-image-optimizer' ) . '</b></p>';
855
- die();
856
  }
857
 
858
  /**
67
  // Creating the 'registry' object for working with nextgen.
68
  $registry = C_Component_Registry::get_instance();
69
  // Creating a database storage object from the 'registry' object.
70
+ $storage = $registry->get_utility( 'I_Gallery_Storage' );
71
  }
72
  // Find the image id.
73
  if ( is_array( $image ) ) {
74
  $image_id = $image['id'];
75
+ $image = $storage->object->_image_mapper->find( $image_id, true );
76
  } else {
77
  $image_id = $storage->object->_get_image_id( $image );
78
  }
107
  // Creating the 'registry' object for working with nextgen.
108
  $registry = C_Component_Registry::get_instance();
109
  // Creating a database storage object from the 'registry' object.
110
+ $storage = $registry->get_utility( 'I_Gallery_Storage' );
111
  }
112
  global $ewww_image;
113
  // Find the image id.
114
  if ( is_array( $image ) ) {
115
  $image_id = $image['id'];
116
+ $image = $storage->object->_image_mapper->find( $image_id, true );
117
  } else {
118
  $image_id = $storage->object->_get_image_id( $image );
119
  }
131
  // Get the absolute path.
132
  $file_path = $storage->get_image_abspath( $image, $size );
133
  ewwwio_debug_message( "optimizing (nextgen): $file_path" );
134
+ $ewww_image = new EWWW_Image( $image_id, 'nextgen', $file_path );
135
  $ewww_image->resize = $size;
136
  // Optimize the image and grab the results.
137
  $res = ewww_image_optimizer( $file_path, 2, false, false, $full_size );
163
  // Creating the 'registry' object for working with nextgen.
164
  $registry = C_Component_Registry::get_instance();
165
  // Creating a database storage object from the 'registry' object.
166
+ $storage = $registry->get_utility( 'I_Gallery_Storage' );
167
+ $filename = $storage->get_image_abspath( $image, $size );
168
+ $ewww_image = new EWWW_Image( $image->pid, 'nextgen', $filename );
169
  $ewww_image->resize = $size;
170
  if ( file_exists( $filename ) ) {
171
  ewww_image_optimizer( $filename, 2 );
186
  if ( ! wp_doing_ajax() ) {
187
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
188
  }
189
+ ewwwio_ob_clean();
190
  wp_die( json_encode( array(
191
  'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
192
  ) ) );
196
  if ( ! wp_doing_ajax() ) {
197
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
198
  }
199
+ ewwwio_ob_clean();
200
  wp_die( json_encode( array(
201
  'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ),
202
  ) ) );
205
  $id = intval( $_REQUEST['ewww_attachment_ID'] );
206
  if ( empty( $_REQUEST['ewww_manual_nonce'] ) || ! wp_verify_nonce( $_REQUEST['ewww_manual_nonce'], "ewww-manual-$id" ) ) {
207
  if ( ! wp_doing_ajax() ) {
208
+ wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
209
  }
210
+ ewwwio_ob_clean();
211
  wp_die( json_encode( array(
212
  'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
213
  ) ) );
215
  // Creating the 'registry' object for working with nextgen.
216
  $registry = C_Component_Registry::get_instance();
217
  // Creating a database storage object from the 'registry' object.
218
+ $storage = $registry->get_utility( 'I_Gallery_Storage' );
219
  // Get an image object.
220
+ $image = $storage->object->_image_mapper->find( $id );
221
+ $image = $this->ewww_added_new_image( $image, $storage );
222
  $success = $this->ewww_manage_image_custom_column( '', $image );
223
  if ( get_transient( 'ewww_image_optimizer_cloud_status' ) == 'exceeded' || ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_exceeded' ) > time() ) {
224
+ ewwwio_ob_clean();
225
+ wp_die( json_encode( array(
226
  'error' => esc_html__( 'License exceeded', 'ewww-image-optimizer' ),
227
  ) ) );
228
  }
233
  wp_redirect( $sendback );
234
  die;
235
  }
236
+ ewwwio_ob_clean();
237
+ wp_die( json_encode( array(
238
  'success' => $success,
239
  ) ) );
240
  }
249
  if ( ! wp_doing_ajax() ) {
250
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
251
  }
252
+ ewwwio_ob_clean();
253
  wp_die( json_encode( array(
254
  'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
255
  ) ) );
259
  if ( ! wp_doing_ajax() ) {
260
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
261
  }
262
+ ewwwio_ob_clean();
263
  wp_die( json_encode( array(
264
  'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ),
265
  ) ) );
270
  if ( ! wp_doing_ajax() ) {
271
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
272
  }
273
+ ewwwio_ob_clean();
274
  wp_die( json_encode( array(
275
  'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
276
  ) ) );
278
  // Creating the 'registry' object for working with nextgen.
279
  $registry = C_Component_Registry::get_instance();
280
  // Creating a database storage object from the 'registry' object.
281
+ $storage = $registry->get_utility( 'I_Gallery_Storage' );
282
  // Get an image object.
283
  $image = $storage->object->_image_mapper->find( $id );
284
  ewww_image_optimizer_cloud_restore_from_meta_data( $image->pid, 'nextgen' );
285
  $success = $this->ewww_manage_image_custom_column( '', $image );
286
+ ewwwio_ob_clean();
287
+ wp_die( json_encode( array(
288
  'success' => $success,
289
  ) ) );
290
  }
311
  'ewww_vars',
312
  array(
313
  'optimizing' => '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' /></p>",
314
+ 'restoring' => '<p>' . esc_html__( 'Restoring', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' /></p>",
315
  )
316
  );
317
  }
359
  // Creating the 'registry' object for working with nextgen.
360
  $registry = C_Component_Registry::get_instance();
361
  // Creating a database storage object from the 'registry' object.
362
+ $storage = $registry->get_utility( 'I_Gallery_Storage' );
363
  if ( is_object( $id ) ) {
364
  $image = $id;
365
  } else {
370
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) && ewww_image_optimizer_function_exists( 'print_r' ) ) {
371
  $print_meta = print_r( $image->meta_data, true );
372
  $print_meta = preg_replace( array( '/ /', '/\n+/' ), array( '&nbsp;', '<br />' ), esc_html( $print_meta ) );
373
+ $output .= '<div style="background-color:#ffff99;font-size: 10px;padding: 10px;margin:-10px -10px 10px;line-height: 1.1em">' . $print_meta . '</div>';
374
  }
375
  $msg = '';
376
  // Get the absolute path.
612
  echo '<div style="background-color:#ffff99;">' . $ewww_debug . '</div>';
613
  }
614
  if ( ! empty( $_REQUEST['ewww_inline'] ) ) {
615
+ wp_die();
616
  }
617
  return;
618
  }
665
  global $nggdb;
666
  // Reset the resume status, not allowed here.
667
  update_option( 'ewww_image_optimizer_bulk_ngg_resume', '' );
668
+ $ids = array();
669
  $gids = array_map( 'intval', $_REQUEST['doaction'] );
670
  // For each gallery we are given.
671
  foreach ( $gids as $gid ) {
700
  wp_enqueue_style( 'jquery-ui-nextgen' );
701
  // Include all the vars we need for javascript.
702
  wp_localize_script( 'ewwwbulkscript', 'ewww_vars', array(
703
+ '_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-bulk' ),
704
+ 'gallery' => 'nextgen',
705
+ 'attachments' => count( $images ),
706
+ 'scan_fail' => esc_html__( 'Operation timed out, you may need to increase the max_execution_time for PHP', 'ewww-image-optimizer' ),
707
+ 'operation_stopped' => esc_html__( 'Optimization stopped, reload page to resume.', 'ewww-image-optimizer' ),
708
  'operation_interrupted' => esc_html__( 'Operation Interrupted', 'ewww-image-optimizer' ),
709
+ 'temporary_failure' => esc_html__( 'Temporary failure, seconds left to retry:', 'ewww-image-optimizer' ),
710
+ 'remove_failed' => esc_html__( 'Could not remove image from table.', 'ewww-image-optimizer' ),
711
+ 'optimized' => esc_html__( 'Optimized', 'ewww-image-optimizer' ),
712
  ) );
713
  }
714
 
717
  */
718
  function ewww_ngg_bulk_init() {
719
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
720
+ $output = array();
721
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
722
+ $output['error'] = esc_html__( 'Access denied.', 'ewww-image-optimizer' );
723
+ ewwwio_ob_clean();
724
+ wp_die( json_encode( $output ) );
725
  }
 
726
  // Toggle the resume flag to indicate an operation is in progress.
727
  update_option( 'ewww_image_optimizer_bulk_ngg_resume', 'true' );
728
  $attachments = get_option( 'ewww_image_optimizer_bulk_ngg_attachments' );
731
  }
732
  if ( ! is_array( $attachments ) ) {
733
  $output['error'] = esc_html__( 'Error retrieving list of images' );
734
+ ewwwio_ob_clean();
735
+ wp_die( json_encode( $output ) );
736
  }
737
+ $id = array_shift( $attachments );
738
+ $file = $this->ewww_ngg_bulk_filename( $id );
739
  $loading_image = plugins_url( '/images/wpspin.gif', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE );
740
  if ( empty( $file ) ) {
741
  $output['results'] = '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' alt='loading'/></p>";
742
  } else {
743
  $output['results'] = '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . " <b>$file</b>&nbsp;<img src='$loading_image' alt='loading'/></p>";
744
  }
745
+ ewwwio_ob_clean();
746
+ wp_die( json_encode( $output ) );
747
  }
748
 
749
  /**
756
  // Creating the 'registry' object for working with nextgen.
757
  $registry = C_Component_Registry::get_instance();
758
  // Creating a database storage object from the 'registry' object.
759
+ $storage = $registry->get_utility( 'I_Gallery_Storage' );
760
  // Get an image object.
761
  $image = $storage->object->_image_mapper->find( $id );
762
  // Get the filename for the image, and output our current status.
775
  */
776
  function ewww_ngg_bulk_loop() {
777
  global $ewww_defer;
778
+ $ewww_defer = false;
779
+ $output = array();
780
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
781
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
782
  $output['error'] = esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' );
783
+ ewwwio_ob_clean();
784
+ wp_die( json_encode( $output ) );
785
  }
786
  session_write_close();
787
  // Find out if our nonce is on it's last leg/tick.
795
  $started = microtime( true );
796
  // Get the list of attachments remaining from the db.
797
  $attachments = get_option( 'ewww_image_optimizer_bulk_ngg_attachments' );
798
+ $id = array_shift( $attachments );
799
  // Creating the 'registry' object for working with nextgen.
800
  $registry = C_Component_Registry::get_instance();
801
  // Creating a database storage object from the 'registry' object.
802
+ $storage = $registry->get_utility( 'I_Gallery_Storage' );
803
  // Get an image object.
804
+ $image = $storage->object->_image_mapper->find( $id );
805
+ $image = $this->ewww_added_new_image( $image, $storage );
806
  $ewww_status = get_transient( 'ewww_image_optimizer_cloud_status' );
807
  if ( ! empty( $ewww_status ) && preg_match( '/exceeded/', $ewww_status ) ) {
808
  $output['error'] = esc_html__( 'License Exceeded', 'ewww-image-optimizer' );
809
+ ewwwio_ob_clean();
810
+ wp_die( json_encode( $output ) );
811
  }
812
  // Output the results of the optimization.
813
  $output['results'] = sprintf( '<p>' . esc_html__( 'Optimized image:', 'ewww-image-optimizer' ) . ' <strong>%s</strong><br>', esc_html( basename( $storage->object->get_image_abspath( $image, 'full' ) ) ) );
832
  // Output how much time we spent.
833
  $elapsed = microtime( true ) - $started;
834
  /* Translators: %s: The localized number of seconds */
835
+ $output['results'] .= sprintf( esc_html( _n( 'Elapsed: %s second', 'Elapsed: %s seconds', $elapsed, 'ewww-image-optimizer' ) ) . '</p>', number_format_i18n( $elapsed ) );
836
  $output['completed'] = 1;
837
  // Store the list back in the db.
838
  update_option( 'ewww_image_optimizer_bulk_ngg_attachments', $attachments, false );
839
  if ( ! empty( $attachments ) ) {
840
  $next_attachment = array_shift( $attachments );
841
+ $next_file = $this->ewww_ngg_bulk_filename( $next_attachment );
842
+ $loading_image = plugins_url( '/images/wpspin.gif', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE );
843
  if ( $next_file ) {
844
  $output['next_file'] = '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . " <b>$next_file</b>&nbsp;<img src='$loading_image' alt='loading'/></p>";
845
  } else {
848
  } else {
849
  $output['done'] = 1;
850
  }
851
+ ewwwio_ob_clean();
852
+ wp_die( json_encode( $output ) );
853
  }
854
 
855
  /**
858
  function ewww_ngg_bulk_cleanup() {
859
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
860
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) {
861
+ ewwwio_ob_clean();
862
  wp_die( esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) );
863
  }
864
  // Reset all the bulk options in the db.
865
  update_option( 'ewww_image_optimizer_bulk_ngg_resume', '' );
866
  update_option( 'ewww_image_optimizer_bulk_ngg_attachments', '', false );
867
+ ewwwio_ob_clean();
868
+ wp_die( '<p><b>' . esc_html__( 'Finished Optimization!', 'ewww-image-optimizer' ) . '</b></p>' );
869
  }
870
 
871
  /**
classes/class-ewwwdb.php CHANGED
@@ -71,7 +71,7 @@ class EwwwDB extends wpdb {
71
  */
72
  ewwwio_debug_message( 'we have records to store via ewwwdb' );
73
  $multi_formats = array();
74
- $values = array();
75
  foreach ( $data as $record ) {
76
  if ( ! ewww_image_optimizer_iterable( $record ) ) {
77
  continue;
@@ -89,14 +89,14 @@ class EwwwDB extends wpdb {
89
  }
90
 
91
  $formats[] = $value['format'];
92
- $values[] = $value['value'];
93
  }
94
  $multi_formats[] = '(' . implode( ',', $formats ) . ')';
95
  }
96
- $first = reset( $data );
97
- $fields = '`' . implode( '`, `', array_keys( $first ) ) . '`';
98
- $multi_formats = implode( ',', $multi_formats );
99
- $sql = "INSERT INTO `$table` ($fields) VALUES $multi_formats";
100
  $this->check_current_query = false;
101
  return $this->query( $this->prepare( $sql, $values ) );
102
  }
71
  */
72
  ewwwio_debug_message( 'we have records to store via ewwwdb' );
73
  $multi_formats = array();
74
+ $values = array();
75
  foreach ( $data as $record ) {
76
  if ( ! ewww_image_optimizer_iterable( $record ) ) {
77
  continue;
89
  }
90
 
91
  $formats[] = $value['format'];
92
+ $values[] = $value['value'];
93
  }
94
  $multi_formats[] = '(' . implode( ',', $formats ) . ')';
95
  }
96
+ $first = reset( $data );
97
+ $fields = '`' . implode( '`, `', array_keys( $first ) ) . '`';
98
+ $multi_formats = implode( ',', $multi_formats );
99
+ $sql = "INSERT INTO `$table` ($fields) VALUES $multi_formats";
100
  $this->check_current_query = false;
101
  return $this->query( $this->prepare( $sql, $values ) );
102
  }
vendor/wp-background-process.php → classes/class-ewwwio-background-process.php RENAMED
@@ -1,19 +1,19 @@
1
  <?php
2
  /**
3
- * WP Background Process
4
  *
5
- * @package WP-Background-Processing
6
  */
7
 
8
- if ( ! class_exists( 'WP_Background_Process' ) ) {
9
 
10
  /**
11
- * Abstract WP_Background_Process class.
12
  *
13
  * @abstract
14
  * @extends WP_Async_Request
15
  */
16
- abstract class WP_Background_Process extends WP_Async_Request {
17
 
18
  /**
19
  * Action
@@ -51,9 +51,20 @@ if ( ! class_exists( 'WP_Background_Process' ) ) {
51
  */
52
  protected $cron_interval_identifier;
53
 
54
- // either an 'a' or a 'b', depending on which one is currently running
 
 
 
 
 
55
  protected $active_queue;
56
 
 
 
 
 
 
 
57
  protected $second_queue;
58
 
59
  /**
@@ -73,7 +84,7 @@ if ( ! class_exists( 'WP_Background_Process' ) ) {
73
  * Dispatch
74
  *
75
  * @access public
76
- * @return void
77
  */
78
  public function dispatch() {
79
  // Schedule the cron healthcheck.
@@ -103,7 +114,7 @@ if ( ! class_exists( 'WP_Background_Process' ) ) {
103
  */
104
  public function save() {
105
  $key = $this->generate_key();
106
- ewwwio_debug_message( "queue $key will be saved to" );
107
  if ( ! empty( $this->data ) ) {
108
  $existing_data = get_option( $key );
109
  if ( ! empty( $existing_data ) ) {
@@ -158,13 +169,12 @@ ewwwio_debug_message( "queue $key will be saved to" );
158
  * @return string
159
  */
160
  protected function generate_key( $length = 64 ) {
161
- // $unique = md5( microtime() . rand() );
162
- $unique = 'a';
163
  if ( $this->is_queue_active( $unique ) ) {
164
  $unique = 'b';
165
  }
166
  $this->second_queue = $unique;
167
- $prepend = $this->identifier . '_batch_';
168
 
169
  return substr( $prepend . $unique, 0, $length );
170
  }
@@ -203,21 +213,13 @@ ewwwio_debug_message( "queue $key will be saved to" );
203
  protected function is_queue_empty() {
204
  global $wpdb;
205
 
206
- $table = $wpdb->options;
207
- $column = 'option_name';
208
-
209
- /* if ( is_multisite() ) {
210
- $table = $wpdb->sitemeta;
211
- $column = 'meta_key';
212
- }*/
213
-
214
- $key = $this->identifier . '_batch_%';
215
 
216
  $count = $wpdb->get_var( $wpdb->prepare( "
217
- SELECT COUNT(*)
218
- FROM {$table}
219
- WHERE {$column} LIKE %s AND option_value != ''
220
- ", $key ) );
221
 
222
  return ( $count > 0 ) ? false : true;
223
  }
@@ -227,6 +229,8 @@ ewwwio_debug_message( "queue $key will be saved to" );
227
  *
228
  * Check whether the current process is already running
229
  * in a background process.
 
 
230
  */
231
  protected function is_process_running() {
232
  if ( get_transient( $this->identifier . '_process_lock' ) ) {
@@ -237,14 +241,20 @@ ewwwio_debug_message( "queue $key will be saved to" );
237
  return false;
238
  }
239
 
 
 
 
 
 
 
240
  protected function is_queue_active( $queue_id ) {
241
  global $wpdb;
242
  $process_lock_transient = '_transient_' . $this->identifier . '_process_lock';
243
- if ( $wpdb->get_var( "SELECT option_value FROM $wpdb->options WHERE option_name LIKE '$process_lock_transient'" ) == $queue_id ) {
244
- ewwwio_debug_message( "queue $queue_id is running" );
245
  return true;
246
  }
247
- ewwwio_debug_message( "queue $queue_id is not running, checked with: ". $this->identifier . '_process_lock' );
248
  return false;
249
  }
250
 
@@ -266,15 +276,22 @@ ewwwio_debug_message( "queue $queue_id is not running, checked with: ". $this->i
266
  }
267
  }
268
 
 
 
 
 
 
 
 
269
  protected function update_lock() {
270
  if ( empty( $this->active_queue ) ) {
271
  return;
272
  }
273
  $lock_duration = ( property_exists( $this, 'queue_lock_time' ) ) ? $this->queue_lock_time : 60; // 1 minute
274
  $lock_duration = apply_filters( $this->identifier . '_queue_lock_time', $lock_duration );
275
- set_transient( $this->identifier . '_process_lock', $this->active_queue , $lock_duration );
276
  }
277
-
278
  /**
279
  * Unlock process
280
  *
@@ -296,31 +313,18 @@ ewwwio_debug_message( "queue $queue_id is not running, checked with: ". $this->i
296
  protected function get_batch() {
297
  global $wpdb;
298
 
299
- $table = $wpdb->options;
300
- $column = 'option_name';
301
- $key_column = 'option_id';
302
- $value_column = 'option_value';
303
-
304
- /* if ( is_multisite() ) {
305
- $table = $wpdb->sitemeta;
306
- $column = 'meta_key';
307
- $key_column = 'meta_id';
308
- $value_column = 'meta_value';
309
- }*/
310
-
311
- $key = $this->identifier . '_batch_%';
312
-
313
- $query = $wpdb->get_row( $wpdb->prepare( "
314
- SELECT *
315
- FROM {$table}
316
- WHERE {$column} LIKE %s AND {$value_column} != ''
317
- ORDER BY {$key_column} ASC
318
- LIMIT 1
319
- ", $key ) );
320
-
321
- $batch = new stdClass();
322
- $batch->key = $query->$column;
323
- $batch->data = maybe_unserialize( $query->$value_column );
324
  $this->active_queue = substr( $batch->key, -1 );
325
  $this->update_lock();
326
  return $batch;
@@ -461,6 +465,7 @@ ewwwio_debug_message( "queue $queue_id is not running, checked with: ". $this->i
461
  // Adds every 5 minutes to the existing schedules.
462
  $schedules[ $this->identifier . '_cron_interval' ] = array(
463
  'interval' => MINUTE_IN_SECONDS * $interval,
 
464
  'display' => sprintf( __( 'Every %d Minutes' ), $interval ),
465
  );
466
 
@@ -514,7 +519,6 @@ ewwwio_debug_message( "queue $queue_id is not running, checked with: ". $this->i
514
  * Cancel Process
515
  *
516
  * Stop processing queue items, clear cronjob and delete batch.
517
- *
518
  */
519
  public function cancel_process() {
520
  if ( ! $this->is_queue_empty() ) {
1
  <?php
2
  /**
3
+ * EWWWIO Background Process
4
  *
5
+ * @package EWWW_Image_Optimizer
6
  */
7
 
8
+ if ( ! class_exists( 'EWWWIO_Background_Process' ) ) {
9
 
10
  /**
11
+ * Abstract EWWWIO_Background_Process class.
12
  *
13
  * @abstract
14
  * @extends WP_Async_Request
15
  */
16
+ abstract class EWWWIO_Background_Process extends WP_Async_Request {
17
 
18
  /**
19
  * Action
51
  */
52
  protected $cron_interval_identifier;
53
 
54
+ /**
55
+ * Either an 'a' or a 'b', depending on which one is currently running.
56
+ *
57
+ * @var string
58
+ * @access protected
59
+ */
60
  protected $active_queue;
61
 
62
+ /**
63
+ * Either an 'a' or a 'b', depending on which one is NOT currently running.
64
+ *
65
+ * @var string
66
+ * @access protected
67
+ */
68
  protected $second_queue;
69
 
70
  /**
84
  * Dispatch
85
  *
86
  * @access public
87
+ * @return array The wp_remote_post response.
88
  */
89
  public function dispatch() {
90
  // Schedule the cron healthcheck.
114
  */
115
  public function save() {
116
  $key = $this->generate_key();
117
+ ewwwio_debug_message( "queue $key will be saved to" );
118
  if ( ! empty( $this->data ) ) {
119
  $existing_data = get_option( $key );
120
  if ( ! empty( $existing_data ) ) {
169
  * @return string
170
  */
171
  protected function generate_key( $length = 64 ) {
172
+ $unique = 'a';
 
173
  if ( $this->is_queue_active( $unique ) ) {
174
  $unique = 'b';
175
  }
176
  $this->second_queue = $unique;
177
+ $prepend = $this->identifier . '_batch_';
178
 
179
  return substr( $prepend . $unique, 0, $length );
180
  }
213
  protected function is_queue_empty() {
214
  global $wpdb;
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
  }
229
  *
230
  * Check whether the current process is already running
231
  * in a background process.
232
+ *
233
+ * @return bool
234
  */
235
  protected function is_process_running() {
236
  if ( get_transient( $this->identifier . '_process_lock' ) ) {
241
  return false;
242
  }
243
 
244
+ /**
245
+ * Is a particular queue active and running.
246
+ *
247
+ * @param string $queue_id The identifier for a background queue.
248
+ * @return bool
249
+ */
250
  protected function is_queue_active( $queue_id ) {
251
  global $wpdb;
252
  $process_lock_transient = '_transient_' . $this->identifier . '_process_lock';
253
+ if ( $wpdb->get_var( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name LIKE %s", $process_lock_transient ) ) == $queue_id ) {
254
+ ewwwio_debug_message( "queue $queue_id is running" );
255
  return true;
256
  }
257
+ ewwwio_debug_message( "queue $queue_id is not running, checked with: " . $this->identifier . '_process_lock' );
258
  return false;
259
  }
260
 
276
  }
277
  }
278
 
279
+ /**
280
+ * Update process lock
281
+ *
282
+ * Update the process lock so that other instances do not spawn.
283
+ *
284
+ * @return $this
285
+ */
286
  protected function update_lock() {
287
  if ( empty( $this->active_queue ) ) {
288
  return;
289
  }
290
  $lock_duration = ( property_exists( $this, 'queue_lock_time' ) ) ? $this->queue_lock_time : 60; // 1 minute
291
  $lock_duration = apply_filters( $this->identifier . '_queue_lock_time', $lock_duration );
292
+ set_transient( $this->identifier . '_process_lock', $this->active_queue, $lock_duration );
293
  }
294
+
295
  /**
296
  * Unlock process
297
  *
313
  protected function get_batch() {
314
  global $wpdb;
315
 
316
+ $key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
317
+
318
+ $query = $wpdb->get_row(
319
+ $wpdb->prepare(
320
+ "SELECT * FROM $wpdb->options WHERE option_name LIKE %s AND option_value != '' ORDER BY option_id ASC LIMIT 1",
321
+ $key
322
+ )
323
+ );
324
+
325
+ $batch = new stdClass();
326
+ $batch->key = $query->option_name;
327
+ $batch->data = maybe_unserialize( $query->option_value );
 
 
 
 
 
 
 
 
 
 
 
 
 
328
  $this->active_queue = substr( $batch->key, -1 );
329
  $this->update_lock();
330
  return $batch;
465
  // Adds every 5 minutes to the existing schedules.
466
  $schedules[ $this->identifier . '_cron_interval' ] = array(
467
  'interval' => MINUTE_IN_SECONDS * $interval,
468
+ /* translators: %d: number of minutes */
469
  'display' => sprintf( __( 'Every %d Minutes' ), $interval ),
470
  );
471
 
519
  * Cancel Process
520
  *
521
  * Stop processing queue items, clear cronjob and delete batch.
 
522
  */
523
  public function cancel_process() {
524
  if ( ! $this->is_queue_empty() ) {
classes/class-ewwwio-cli.php CHANGED
@@ -272,7 +272,7 @@ function ewww_image_optimizer_bulk_flag( $delay = 0 ) {
272
  // Record the starting time for the current image (in microseconds).
273
  $started = microtime( true );
274
  // Retrieve the meta for the current ID.
275
- $meta = new flagMeta( $id );
276
  $file_path = $meta->image->imagePath;
277
  // Optimize the full-size version.
278
  $fres = ewww_image_optimizer( $file_path, 3, false, false, true );
@@ -282,7 +282,7 @@ function ewww_image_optimizer_bulk_flag( $delay = 0 ) {
282
  if ( ! empty( $meta->image->meta_data['webview'] ) ) {
283
  // Determine path of the webview.
284
  $web_path = $meta->image->webimagePath;
285
- $wres = ewww_image_optimizer( $web_path, 3, false, true );
286
  /* translators: %s: compression results */
287
  WP_CLI::line( sprintf( __( 'Optimized size – %s', 'ewww-image-optimizer' ), html_entity_decode( $wres[1] ) ) );
288
  }
@@ -367,7 +367,7 @@ function ewww_image_optimizer_bulk_ngg( $delay = 0 ) {
367
  // Creating the 'registry' object for working with nextgen.
368
  $registry = C_Component_Registry::get_instance();
369
  // Creating a database storage object from the 'registry' object.
370
- $storage = $registry->get_utility( 'I_Gallery_Storage' );
371
  // Get an image object.
372
  $image = $storage->object->_image_mapper->find( $id );
373
  $image = $ewwwngg->ewww_added_new_image( $image, $storage );
272
  // Record the starting time for the current image (in microseconds).
273
  $started = microtime( true );
274
  // Retrieve the meta for the current ID.
275
+ $meta = new flagMeta( $id );
276
  $file_path = $meta->image->imagePath;
277
  // Optimize the full-size version.
278
  $fres = ewww_image_optimizer( $file_path, 3, false, false, true );
282
  if ( ! empty( $meta->image->meta_data['webview'] ) ) {
283
  // Determine path of the webview.
284
  $web_path = $meta->image->webimagePath;
285
+ $wres = ewww_image_optimizer( $web_path, 3, false, true );
286
  /* translators: %s: compression results */
287
  WP_CLI::line( sprintf( __( 'Optimized size – %s', 'ewww-image-optimizer' ), html_entity_decode( $wres[1] ) ) );
288
  }
367
  // Creating the 'registry' object for working with nextgen.
368
  $registry = C_Component_Registry::get_instance();
369
  // Creating a database storage object from the 'registry' object.
370
+ $storage = $registry->get_utility( 'I_Gallery_Storage' );
371
  // Get an image object.
372
  $image = $storage->object->_image_mapper->find( $id );
373
  $image = $ewwwngg->ewww_added_new_image( $image, $storage );
classes/class-ewwwio-gd-editor.php CHANGED
@@ -37,10 +37,10 @@ if ( class_exists( 'Bbpp_Animated_Gif' ) ) {
37
  if ( $current_size && $this->size['width'] == $current_size[0] && $this->size['height'] == $current_size[1] ) {
38
  ewwwio_debug_message( "existing file has same dimensions, not saving $filename" );
39
  return array(
40
- 'path' => $filename,
41
- 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
42
- 'width' => $this->size['width'],
43
- 'height' => $this->size['height'],
44
  'mime-type' => $mime_type,
45
  );
46
  }
@@ -99,7 +99,7 @@ if ( class_exists( 'Bbpp_Animated_Gif' ) ) {
99
  ewwwio_debug_message( print_r( $this, true ) );
100
  }
101
  $info = pathinfo( $this->file );
102
- $dir = $info['dirname'];
103
  if ( ewww_image_optimizer_iterable( $metadata ) ) {
104
  foreach ( $metadata as $size ) {
105
  $filename = trailingslashit( $dir ) . $size['file'];
@@ -160,10 +160,10 @@ if ( class_exists( 'Bbpp_Animated_Gif' ) ) {
160
  if ( $current_size && $this->size['width'] == $current_size[0] && $this->size['height'] == $current_size[1] ) {
161
  ewwwio_debug_message( "existing file has same dimensions, not saving $filename" );
162
  return array(
163
- 'path' => $filename,
164
- 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
165
- 'width' => $this->size['width'],
166
- 'height' => $this->size['height'],
167
  'mime-type' => $mime_type,
168
  );
169
  }
@@ -232,10 +232,10 @@ if ( class_exists( 'Bbpp_Animated_Gif' ) ) {
232
  if ( $current_size && $this->size['width'] == $current_size[0] && $this->size['height'] == $current_size[1] ) {
233
  ewwwio_debug_message( "existing file has same dimensions, not saving $filename" );
234
  return array(
235
- 'path' => $filename,
236
- 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
237
- 'width' => $this->size['width'],
238
- 'height' => $this->size['height'],
239
  'mime-type' => $mime_type,
240
  );
241
  }
@@ -304,10 +304,10 @@ if ( class_exists( 'Bbpp_Animated_Gif' ) ) {
304
  if ( $current_size && $this->size['width'] == $current_size[0] && $this->size['height'] == $current_size[1] ) {
305
  ewwwio_debug_message( "existing file has same dimensions, not saving $filename" );
306
  return array(
307
- 'path' => $filename,
308
- 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
309
- 'width' => $this->size['width'],
310
- 'height' => $this->size['height'],
311
  'mime-type' => $mime_type,
312
  );
313
  }
37
  if ( $current_size && $this->size['width'] == $current_size[0] && $this->size['height'] == $current_size[1] ) {
38
  ewwwio_debug_message( "existing file has same dimensions, not saving $filename" );
39
  return array(
40
+ 'path' => $filename,
41
+ 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
42
+ 'width' => $this->size['width'],
43
+ 'height' => $this->size['height'],
44
  'mime-type' => $mime_type,
45
  );
46
  }
99
  ewwwio_debug_message( print_r( $this, true ) );
100
  }
101
  $info = pathinfo( $this->file );
102
+ $dir = $info['dirname'];
103
  if ( ewww_image_optimizer_iterable( $metadata ) ) {
104
  foreach ( $metadata as $size ) {
105
  $filename = trailingslashit( $dir ) . $size['file'];
160
  if ( $current_size && $this->size['width'] == $current_size[0] && $this->size['height'] == $current_size[1] ) {
161
  ewwwio_debug_message( "existing file has same dimensions, not saving $filename" );
162
  return array(
163
+ 'path' => $filename,
164
+ 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
165
+ 'width' => $this->size['width'],
166
+ 'height' => $this->size['height'],
167
  'mime-type' => $mime_type,
168
  );
169
  }
232
  if ( $current_size && $this->size['width'] == $current_size[0] && $this->size['height'] == $current_size[1] ) {
233
  ewwwio_debug_message( "existing file has same dimensions, not saving $filename" );
234
  return array(
235
+ 'path' => $filename,
236
+ 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
237
+ 'width' => $this->size['width'],
238
+ 'height' => $this->size['height'],
239
  'mime-type' => $mime_type,
240
  );
241
  }
304
  if ( $current_size && $this->size['width'] == $current_size[0] && $this->size['height'] == $current_size[1] ) {
305
  ewwwio_debug_message( "existing file has same dimensions, not saving $filename" );
306
  return array(
307
+ 'path' => $filename,
308
+ 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
309
+ 'width' => $this->size['width'],
310
+ 'height' => $this->size['height'],
311
  'mime-type' => $mime_type,
312
  );
313
  }
classes/class-ewwwio-gmagick-editor.php CHANGED
@@ -36,10 +36,10 @@ if ( class_exists( 'WP_Image_Editor_Gmagick' ) ) {
36
  if ( $current_size && $this->size['width'] == $current_size[0] && $this->size['height'] == $current_size[1] ) {
37
  ewwwio_debug_message( "existing file has same dimensions, not saving $filename" );
38
  return array(
39
- 'path' => $filename,
40
- 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
41
- 'width' => $this->size['width'],
42
- 'height' => $this->size['height'],
43
  'mime-type' => $mime_type,
44
  );
45
  }
36
  if ( $current_size && $this->size['width'] == $current_size[0] && $this->size['height'] == $current_size[1] ) {
37
  ewwwio_debug_message( "existing file has same dimensions, not saving $filename" );
38
  return array(
39
+ 'path' => $filename,
40
+ 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
41
+ 'width' => $this->size['width'],
42
+ 'height' => $this->size['height'],
43
  'mime-type' => $mime_type,
44
  );
45
  }
classes/class-ewwwio-hs-beacon.php CHANGED
@@ -97,7 +97,7 @@ class EWWWIO_HS_Beacon {
97
  if ( is_multisite() && is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) && ! current_user_can( 'manage_network_options' ) ) {
98
  return;
99
  }
100
- $optin_url = 'admin.php?action=ewww_opt_into_hs_beacon';
101
  $optout_url = 'admin.php?action=ewww_opt_out_of_hs_beacon';
102
  echo '<div class="updated"><p>';
103
  esc_html_e( 'Enable the support beacon, which gives you access to documentation and our support team right from your WordPress dashboard. To assist you more efficiently, we may collect the current url, IP address, browser/device information, and debugging information.', 'ewww-image-optimizer' );
97
  if ( is_multisite() && is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) && ! current_user_can( 'manage_network_options' ) ) {
98
  return;
99
  }
100
+ $optin_url = 'admin.php?action=ewww_opt_into_hs_beacon';
101
  $optout_url = 'admin.php?action=ewww_opt_out_of_hs_beacon';
102
  echo '<div class="updated"><p>';
103
  esc_html_e( 'Enable the support beacon, which gives you access to documentation and our support team right from your WordPress dashboard. To assist you more efficiently, we may collect the current url, IP address, browser/device information, and debugging information.', 'ewww-image-optimizer' );
classes/class-ewwwio-imagick-editor.php CHANGED
@@ -36,10 +36,10 @@ if ( class_exists( 'WP_Thumb_Image_Editor_Imagick' ) ) {
36
  if ( $current_size && $this->size['width'] == $current_size[0] && $this->size['height'] == $current_size[1] ) {
37
  ewwwio_debug_message( "existing file has same dimensions, not saving $filename" );
38
  return array(
39
- 'path' => $filename,
40
- 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
41
- 'width' => $this->size['width'],
42
- 'height' => $this->size['height'],
43
  'mime-type' => $mime_type,
44
  );
45
  }
@@ -70,8 +70,8 @@ if ( class_exists( 'WP_Thumb_Image_Editor_Imagick' ) ) {
70
  $ewwwio_image_background = new EWWWIO_Image_Background_Process();
71
  }
72
  $ewwwio_image_background->push_to_queue( $filename );
73
- $ewwwio_image_background->save()->dispatch();
74
- ewwwio_debug_message( "image editor (wpthumb imagick) queued: $filename" );
75
  }
76
  */
77
  }
@@ -108,10 +108,10 @@ if ( class_exists( 'WP_Thumb_Image_Editor_Imagick' ) ) {
108
  if ( $current_size && $this->size['width'] == $current_size[0] && $this->size['height'] == $current_size[1] ) {
109
  ewwwio_debug_message( "existing file has same dimensions, not saving $filename" );
110
  return array(
111
- 'path' => $filename,
112
- 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
113
- 'width' => $this->size['width'],
114
- 'height' => $this->size['height'],
115
  'mime-type' => $mime_type,
116
  );
117
  }
@@ -180,10 +180,10 @@ if ( class_exists( 'WP_Thumb_Image_Editor_Imagick' ) ) {
180
  if ( $current_size && $this->size['width'] == $current_size[0] && $this->size['height'] == $current_size[1] ) {
181
  ewwwio_debug_message( "existing file has same dimensions, not saving $filename" );
182
  return array(
183
- 'path' => $filename,
184
- 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
185
- 'width' => $this->size['width'],
186
- 'height' => $this->size['height'],
187
  'mime-type' => $mime_type,
188
  );
189
  }
@@ -298,10 +298,10 @@ if ( class_exists( 'WP_Thumb_Image_Editor_Imagick' ) ) {
298
  if ( $current_size && $this->size['width'] == $current_size[0] && $this->size['height'] == $current_size[1] ) {
299
  ewwwio_debug_message( "existing file has same dimensions, not saving $filename" );
300
  return array(
301
- 'path' => $filename,
302
- 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
303
- 'width' => $this->size['width'],
304
- 'height' => $this->size['height'],
305
  'mime-type' => $mime_type,
306
  );
307
  }
36
  if ( $current_size && $this->size['width'] == $current_size[0] && $this->size['height'] == $current_size[1] ) {
37
  ewwwio_debug_message( "existing file has same dimensions, not saving $filename" );
38
  return array(
39
+ 'path' => $filename,
40
+ 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
41
+ 'width' => $this->size['width'],
42
+ 'height' => $this->size['height'],
43
  'mime-type' => $mime_type,
44
  );
45
  }
70
  $ewwwio_image_background = new EWWWIO_Image_Background_Process();
71
  }
72
  $ewwwio_image_background->push_to_queue( $filename );
73
+ $ewwwio_image_background->save()->dispatch();
74
+ ewwwio_debug_message( "image editor (wpthumb imagick) queued: $filename" );
75
  }
76
  */
77
  }
108
  if ( $current_size && $this->size['width'] == $current_size[0] && $this->size['height'] == $current_size[1] ) {
109
  ewwwio_debug_message( "existing file has same dimensions, not saving $filename" );
110
  return array(
111
+ 'path' => $filename,
112
+ 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
113
+ 'width' => $this->size['width'],
114
+ 'height' => $this->size['height'],
115
  'mime-type' => $mime_type,
116
  );
117
  }
180
  if ( $current_size && $this->size['width'] == $current_size[0] && $this->size['height'] == $current_size[1] ) {
181
  ewwwio_debug_message( "existing file has same dimensions, not saving $filename" );
182
  return array(
183
+ 'path' => $filename,
184
+ 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
185
+ 'width' => $this->size['width'],
186
+ 'height' => $this->size['height'],
187
  'mime-type' => $mime_type,
188
  );
189
  }
298
  if ( $current_size && $this->size['width'] == $current_size[0] && $this->size['height'] == $current_size[1] ) {
299
  ewwwio_debug_message( "existing file has same dimensions, not saving $filename" );
300
  return array(
301
+ 'path' => $filename,
302
+ 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
303
+ 'width' => $this->size['width'],
304
+ 'height' => $this->size['height'],
305
  'mime-type' => $mime_type,
306
  );
307
  }
classes/class-ewwwio-media-background-process.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Classes for Background and Async processing.
4
  *
5
- * This file contains classes and methods that extend WP_Background_Process and
6
  * WP_Async_Request to allow parallel and background processing of images.
7
  *
8
  * @link https://ewww.io
@@ -14,23 +14,23 @@ if ( ! defined( 'ABSPATH' ) ) {
14
  }
15
 
16
  /**
17
- * The parent WP_Async_Request class file.
18
  */
19
  require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'vendor/wp-async-request.php' );
20
 
21
  /**
22
- * The parent WP_Background_Process class file.
23
  */
24
- require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'vendor/wp-background-process.php' );
25
 
26
  /**
27
  * Processes media uploads in background/async mode.
28
  *
29
  * Uses a dual-queue system to track uploads to be optimized, handling them one at a time.
30
  *
31
- * @see WP_Background_Process
32
  */
33
- class EWWWIO_Media_Background_Process extends WP_Background_Process {
34
 
35
  /**
36
  * The action name used to trigger this class extension.
@@ -56,20 +56,21 @@ class EWWWIO_Media_Background_Process extends WP_Background_Process {
56
  protected function task( $item ) {
57
  session_write_close();
58
  global $ewww_defer;
59
- $ewww_defer = false;
60
  $max_attempts = 15;
61
- $id = $item['id'];
62
  if ( empty( $item['attempts'] ) ) {
63
  $item['attempts'] = 0;
64
  sleep( 4 ); // On the first attempt, hold off and wait for the db to catch up.
65
  }
66
  ewwwio_debug_message( "background processing $id, type: " . $item['type'] );
67
- $type = $item['type'];
68
  $image_types = array(
69
  'image/jpeg',
70
  'image/png',
71
  'image/gif',
72
  );
 
73
  $meta = wp_get_attachment_metadata( $id, true );
74
  if ( in_array( $type, $image_types ) && empty( $meta ) && $item['attempts'] < $max_attempts ) {
75
  $item['attempts']++;
@@ -119,9 +120,9 @@ $ewwwio_media_background = new EWWWIO_Media_Background_Process();
119
  * time. This is only used for Nextcellent thumbs currently.
120
  *
121
  * @deprecated 3.1.3
122
- * @see WP_Background_Process
123
  */
124
- class EWWWIO_Image_Background_Process extends WP_Background_Process {
125
 
126
  /**
127
  * The action name used to trigger this class extension.
@@ -169,9 +170,9 @@ $ewwwio_image_background = new EWWWIO_Image_Background_Process();
169
  *
170
  * Uses a dual-queue system to track uploads to be optimized, handling them one at a time.
171
  *
172
- * @see WP_Background_Process
173
  */
174
- class EWWWIO_Flag_Background_Process extends WP_Background_Process {
175
 
176
  /**
177
  * The action name used to trigger this class extension.
@@ -247,9 +248,9 @@ $ewwwio_flag_background = new EWWWIO_Flag_Background_Process();
247
  *
248
  * Uses a dual-queue system to track uploads to be optimized, handling them one at a time.
249
  *
250
- * @see WP_Background_Process
251
  */
252
- class EWWWIO_Ngg_Background_Process extends WP_Background_Process {
253
 
254
  /**
255
  * The action name used to trigger this class extension.
@@ -325,9 +326,9 @@ $ewwwio_ngg_background = new EWWWIO_Ngg_Background_Process();
325
  *
326
  * Uses a dual-queue system to track uploads to be optimized, handling them one at a time.
327
  *
328
- * @see WP_Background_Process
329
  */
330
- class EWWWIO_Ngg2_Background_Process extends WP_Background_Process {
331
 
332
  /**
333
  * The action name used to trigger this class extension.
@@ -360,7 +361,7 @@ class EWWWIO_Ngg2_Background_Process extends WP_Background_Process {
360
  // Creating the 'registry' object for working with nextgen.
361
  $registry = C_Component_Registry::get_instance();
362
  // Creating a database storage object from the 'registry' object.
363
- $storage = $registry->get_utility( 'I_Gallery_Storage' );
364
  // Get a NextGEN image object.
365
  $image = $storage->object->_image_mapper->find( $id );
366
  if ( ! is_object( $image ) && $item['attempts'] < $max_attempts ) {
@@ -441,8 +442,9 @@ class EWWWIO_Async_Request extends WP_Async_Request {
441
  $file_path = $this->find_file( $_POST['ewwwio_path'] );
442
  if ( ! empty( $file_path ) ) {
443
  ewwwio_debug_message( "processing async optimization request for {$_POST['ewwwio_path']}" );
444
- $ewww_image = new EWWW_Image( $id, 'media', $file_path );
445
  $ewww_image->resize = 'full';
 
446
  list( $file, $msg, $conv, $original ) = ewww_image_optimizer( $file_path, 1, false, false, true );
447
  } else {
448
  ewwwio_debug_message( "could not process async optimization request for {$_POST['ewwwio_path']}" );
@@ -451,8 +453,9 @@ class EWWWIO_Async_Request extends WP_Async_Request {
451
  $file_path = $this->find_file( $_POST['ewwwio_path'] );
452
  if ( ! empty( $file_path ) ) {
453
  ewwwio_debug_message( "processing async optimization request for {$_POST['ewwwio_path']}" );
454
- $ewww_image = new EWWW_Image( $id, 'media', $file_path );
455
  $ewww_image->resize = ( empty( $size ) ? null : $size );
 
456
  list( $file, $msg, $conv, $original ) = ewww_image_optimizer( $file_path );
457
  } else {
458
  ewwwio_debug_message( "could not process async optimization request for {$_POST['ewwwio_path']}" );
@@ -483,18 +486,19 @@ class EWWWIO_Async_Request extends WP_Async_Request {
483
  return $file_path;
484
  }
485
  // Retrieve the location of the WordPress upload folder.
486
- $upload_dir = wp_upload_dir();
487
  $upload_path = trailingslashit( $upload_dir['basedir'] );
488
- $file = $upload_path . $file_path;
489
  if ( is_file( $file ) ) {
490
  return $file;
491
  }
492
  $upload_path = trailingslashit( WP_CONTENT_DIR );
493
- $file = $upload_path . $file_path;
494
  if ( is_file( $file ) ) {
495
  return $file;
496
  }
497
  $upload_path .= 'uploads/';
 
498
  $file = $upload_path . $file_path;
499
  if ( is_file( $file ) ) {
500
  return $file;
2
  /**
3
  * Classes for Background and Async processing.
4
  *
5
+ * This file contains classes and methods that extend EWWWIO_Background_Process and
6
  * WP_Async_Request to allow parallel and background processing of images.
7
  *
8
  * @link https://ewww.io
14
  }
15
 
16
  /**
17
+ * The (grand)parent WP_Async_Request class file.
18
  */
19
  require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'vendor/wp-async-request.php' );
20
 
21
  /**
22
+ * The parent EWWWIO_Background_Process class file.
23
  */
24
+ require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-ewwwio-background-process.php' );
25
 
26
  /**
27
  * Processes media uploads in background/async mode.
28
  *
29
  * Uses a dual-queue system to track uploads to be optimized, handling them one at a time.
30
  *
31
+ * @see EWWWIO_Background_Process
32
  */
33
+ class EWWWIO_Media_Background_Process extends EWWWIO_Background_Process {
34
 
35
  /**
36
  * The action name used to trigger this class extension.
56
  protected function task( $item ) {
57
  session_write_close();
58
  global $ewww_defer;
59
+ $ewww_defer = false;
60
  $max_attempts = 15;
61
+ $id = $item['id'];
62
  if ( empty( $item['attempts'] ) ) {
63
  $item['attempts'] = 0;
64
  sleep( 4 ); // On the first attempt, hold off and wait for the db to catch up.
65
  }
66
  ewwwio_debug_message( "background processing $id, type: " . $item['type'] );
67
+ $type = $item['type'];
68
  $image_types = array(
69
  'image/jpeg',
70
  'image/png',
71
  'image/gif',
72
  );
73
+
74
  $meta = wp_get_attachment_metadata( $id, true );
75
  if ( in_array( $type, $image_types ) && empty( $meta ) && $item['attempts'] < $max_attempts ) {
76
  $item['attempts']++;
120
  * time. This is only used for Nextcellent thumbs currently.
121
  *
122
  * @deprecated 3.1.3
123
+ * @see EWWWIO_Background_Process
124
  */
125
+ class EWWWIO_Image_Background_Process extends EWWWIO_Background_Process {
126
 
127
  /**
128
  * The action name used to trigger this class extension.
170
  *
171
  * Uses a dual-queue system to track uploads to be optimized, handling them one at a time.
172
  *
173
+ * @see EWWWIO_Background_Process
174
  */
175
+ class EWWWIO_Flag_Background_Process extends EWWWIO_Background_Process {
176
 
177
  /**
178
  * The action name used to trigger this class extension.
248
  *
249
  * Uses a dual-queue system to track uploads to be optimized, handling them one at a time.
250
  *
251
+ * @see EWWWIO_Background_Process
252
  */
253
+ class EWWWIO_Ngg_Background_Process extends EWWWIO_Background_Process {
254
 
255
  /**
256
  * The action name used to trigger this class extension.
326
  *
327
  * Uses a dual-queue system to track uploads to be optimized, handling them one at a time.
328
  *
329
+ * @see EWWWIO_Background_Process
330
  */
331
+ class EWWWIO_Ngg2_Background_Process extends EWWWIO_Background_Process {
332
 
333
  /**
334
  * The action name used to trigger this class extension.
361
  // Creating the 'registry' object for working with nextgen.
362
  $registry = C_Component_Registry::get_instance();
363
  // Creating a database storage object from the 'registry' object.
364
+ $storage = $registry->get_utility( 'I_Gallery_Storage' );
365
  // Get a NextGEN image object.
366
  $image = $storage->object->_image_mapper->find( $id );
367
  if ( ! is_object( $image ) && $item['attempts'] < $max_attempts ) {
442
  $file_path = $this->find_file( $_POST['ewwwio_path'] );
443
  if ( ! empty( $file_path ) ) {
444
  ewwwio_debug_message( "processing async optimization request for {$_POST['ewwwio_path']}" );
445
+ $ewww_image = new EWWW_Image( $id, 'media', $file_path );
446
  $ewww_image->resize = 'full';
447
+
448
  list( $file, $msg, $conv, $original ) = ewww_image_optimizer( $file_path, 1, false, false, true );
449
  } else {
450
  ewwwio_debug_message( "could not process async optimization request for {$_POST['ewwwio_path']}" );
453
  $file_path = $this->find_file( $_POST['ewwwio_path'] );
454
  if ( ! empty( $file_path ) ) {
455
  ewwwio_debug_message( "processing async optimization request for {$_POST['ewwwio_path']}" );
456
+ $ewww_image = new EWWW_Image( $id, 'media', $file_path );
457
  $ewww_image->resize = ( empty( $size ) ? null : $size );
458
+
459
  list( $file, $msg, $conv, $original ) = ewww_image_optimizer( $file_path );
460
  } else {
461
  ewwwio_debug_message( "could not process async optimization request for {$_POST['ewwwio_path']}" );
486
  return $file_path;
487
  }
488
  // Retrieve the location of the WordPress upload folder.
489
+ $upload_dir = wp_upload_dir();
490
  $upload_path = trailingslashit( $upload_dir['basedir'] );
491
+ $file = $upload_path . $file_path;
492
  if ( is_file( $file ) ) {
493
  return $file;
494
  }
495
  $upload_path = trailingslashit( WP_CONTENT_DIR );
496
+ $file = $upload_path . $file_path;
497
  if ( is_file( $file ) ) {
498
  return $file;
499
  }
500
  $upload_path .= 'uploads/';
501
+
502
  $file = $upload_path . $file_path;
503
  if ( is_file( $file ) ) {
504
  return $file;
classes/class-ewwwio-tracking.php CHANGED
@@ -61,9 +61,9 @@ class EWWWIO_Tracking {
61
  $data = array();
62
 
63
  // Retrieve current theme info.
64
- $theme_data = wp_get_theme();
65
- $theme = $theme_data->Name . ' ' . $theme_data->Version;
66
- $data['email'] = get_bloginfo( 'admin_email' ); // Not tracked, used to issue free credits.
67
  $data['site_id'] = md5( home_url() );
68
  if ( strlen( ewww_image_optimizer_get_option( 'ewww_image_optimizer_tracking_site_id' ) ) == 32 && ctype_alnum( ewww_image_optimizer_get_option( 'ewww_image_optimizer_tracking_site_id' ) ) ) {
69
  ewwwio_debug_message( 'using pre-existing site_id' );
@@ -72,20 +72,19 @@ class EWWWIO_Tracking {
72
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_tracking_site_id', $data['site_id'] );
73
  }
74
  $data['ewwwio_version'] = EWWW_IMAGE_OPTIMIZER_VERSION;
75
- $data['wp_version'] = get_bloginfo( 'version' );
76
- $data['php_version'] = PHP_VERSION_ID;
77
- $data['libxml_version'] = defined( 'LIBXML_VERSION' ) ? LIBXML_VERSION : '' ;
78
- $data['server'] = isset( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : '';
79
-
80
- $data['multisite'] = is_multisite();
81
- $data['theme'] = $theme;
82
 
83
  // Retrieve current plugin information.
84
  if ( ! function_exists( 'get_plugins' ) ) {
85
  require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
86
  }
87
 
88
- $plugins = array_keys( get_plugins() );
89
  $active_plugins = get_option( 'active_plugins', array() );
90
 
91
  foreach ( $plugins as $key => $plugin ) {
@@ -95,66 +94,67 @@ class EWWWIO_Tracking {
95
  }
96
  }
97
 
98
- $data['active_plugins'] = $active_plugins;
99
  $data['inactive_plugins'] = $plugins;
100
- $data['locale'] = ( $data['wp_version'] >= 4.7 ) ? get_user_locale() : get_locale();
101
  if ( ! function_exists( 'ewww_image_optimizer_aux_images_table_count_pending' ) ) {
102
  require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'aux-optimize.php' );
103
  }
104
  $data['images_optimized'] = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ? 0 : ewww_image_optimizer_aux_images_table_count();
105
- $data['bytes_saved'] = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ? 0 : ewww_image_optimizer_savings();
106
 
107
- $data['nextgen'] = class_exists( 'EWWW_Nextgen' ) ? true : false;
108
- $data['nextcellent'] = class_exists( 'EWWW_Nextcellent' ) ? true : false;
109
- $data['flagallery'] = class_exists( 'EWWW_Flag' ) ? true : false;
110
- $data['memory_limit'] = ewwwio_memory_limit();
111
- $data['time_limit'] = (int) ini_get( 'max_execution_time' );
112
  $data['operating_system'] = ewww_image_optimizer_function_exists( 'php_uname' ) ? php_uname( 's' ) : '';
113
 
114
- $data['cloud_api'] = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ? true : false;
115
  $data['keep_metadata'] = ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) ? false : true;
116
- $data['jpg_level'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' );
117
- $data['png_level'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' );
118
- $data['gif_level'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' );
119
- $data['pdf_level'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' );
120
- $data['bulk_delay'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_delay' );
121
- $data['backups'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_backup_files' );
122
-
123
- $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' );
124
- $data['disable_pngout'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_pngout' );
125
- $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' );
126
- $data['jpg_quality'] = (int) apply_filters( 'jpeg_quality', 82 );
127
- $data['parallel_opt'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_parallel_optimization' );
128
- $data['background_opt'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_background_optimization' );
129
- $data['scheduled_opt'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_auto' );
130
- $data['include_media_folders'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_include_media_paths' );
131
- $data['folders_to_opt'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_aux_paths' );
132
- $data['folders_to_ignore'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_exclude_paths' );
133
- $data['resize_media_width'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' );
134
- $data['resize_media_height'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' );
135
- $data['resize_indirect_width'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherwidth' );
136
  $data['resize_indirect_height'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherheight' );
137
- $data['resize_existing'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' );
138
- $data['total_sizes'] = (int) count( ewww_image_optimizer_get_image_sizes() );
139
- $data['disabled_opt_sizes'] = is_array( get_option( 'ewww_image_optimizer_disable_resizes_opt' ) ) ? count( get_option( 'ewww_image_optimizer_disable_resizes_opt' ) ) : 0;
140
- $data['disabled_create_sizes'] = is_array( get_option( 'ewww_image_optimizer_disable_resizes' ) ) ? count( get_option( 'ewww_image_optimizer_disable_resizes' ) ) : 0;
141
- $data['skip_small_images'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_skip_size' );
142
- $data['skip_large_pngs'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_skip_png_size' );
143
- $data['exclude_full_lossy'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_lossy_skip_full' );
144
- $data['exclude_full_meta'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_skip_full' );
145
- $data['system_paths'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_skip_bundle' );
146
-
147
- $data['hide_conversion'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_convert_links' );
148
  $data['delete_originals'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' );
149
- $data['jpg2png'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_to_png' );
150
- $data['png2jpg'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_to_jpg' );
151
- $data['gif2png'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_to_png' );
152
- $data['fill_color'] = is_null( ewww_image_optimizer_jpg_background() ) ? '' : ewww_image_optimizer_jpg_background();
153
 
154
  $data['webp_create'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' );
155
- $data['webp_force'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' );
156
- $data['webp_urls'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' );
157
- $data['alt_webp'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' );
 
158
  $this->data = $data;
159
  }
160
 
@@ -184,13 +184,15 @@ class EWWWIO_Tracking {
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 ) ) {
 
 
194
  return $request;
195
  }
196
 
@@ -332,13 +334,15 @@ class EWWWIO_Tracking {
332
  ) {
333
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_tracking_notice', 1 );
334
  } else {
335
- $optin_url = 'admin.php?action=ewww_opt_into_tracking';
336
- $optout_url = 'admin.php?action=ewww_opt_out_of_tracking';
 
337
  echo '<div class="updated"><p>';
338
- esc_html_e( 'Allow EWWW Image Optimizer to track plugin usage? Opt-in to tracking to receive up to 500 free image credits. No sensitive data is tracked.', 'ewww-image-optimizer' );
339
- echo '&nbsp;<a href="http://docs.ewww.io/article/23-usage-tracking">' . esc_html__( 'Learn more.', 'ewww-image-optimizer' ) . '</a>';
340
- echo '&nbsp;<a href="' . esc_url( $optin_url ) . '" class="button-secondary">' . esc_html__( 'Allow', 'ewww-image-optimizer' ) . '</a>';
341
- echo '&nbsp;<a href="' . esc_url( $optout_url ) . '" class="button-secondary">' . esc_html__( 'Do not allow', 'ewww-image-optimizer' ) . '</a>';
 
342
  echo '</p></div>';
343
  }
344
  }
61
  $data = array();
62
 
63
  // Retrieve current theme info.
64
+ $theme_data = wp_get_theme();
65
+ $theme = $theme_data->Name . ' ' . $theme_data->Version;
66
+ $data['email'] = get_bloginfo( 'admin_email' ); // Not tracked, used to issue free credits.
67
  $data['site_id'] = md5( home_url() );
68
  if ( strlen( ewww_image_optimizer_get_option( 'ewww_image_optimizer_tracking_site_id' ) ) == 32 && ctype_alnum( ewww_image_optimizer_get_option( 'ewww_image_optimizer_tracking_site_id' ) ) ) {
69
  ewwwio_debug_message( 'using pre-existing site_id' );
72
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_tracking_site_id', $data['site_id'] );
73
  }
74
  $data['ewwwio_version'] = EWWW_IMAGE_OPTIMIZER_VERSION;
75
+ $data['wp_version'] = get_bloginfo( 'version' );
76
+ $data['php_version'] = PHP_VERSION_ID;
77
+ $data['libxml_version'] = defined( 'LIBXML_VERSION' ) ? LIBXML_VERSION : '';
78
+ $data['server'] = isset( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : '';
79
+ $data['multisite'] = is_multisite();
80
+ $data['theme'] = $theme;
 
81
 
82
  // Retrieve current plugin information.
83
  if ( ! function_exists( 'get_plugins' ) ) {
84
  require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
85
  }
86
 
87
+ $plugins = array_keys( get_plugins() );
88
  $active_plugins = get_option( 'active_plugins', array() );
89
 
90
  foreach ( $plugins as $key => $plugin ) {
94
  }
95
  }
96
 
97
+ $data['active_plugins'] = $active_plugins;
98
  $data['inactive_plugins'] = $plugins;
99
+ $data['locale'] = ( $data['wp_version'] >= 4.7 ) ? get_user_locale() : get_locale();
100
  if ( ! function_exists( 'ewww_image_optimizer_aux_images_table_count_pending' ) ) {
101
  require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'aux-optimize.php' );
102
  }
103
  $data['images_optimized'] = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ? 0 : ewww_image_optimizer_aux_images_table_count();
104
+ $data['bytes_saved'] = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ? 0 : ewww_image_optimizer_savings();
105
 
106
+ $data['nextgen'] = class_exists( 'EWWW_Nextgen' ) ? true : false;
107
+ $data['nextcellent'] = class_exists( 'EWWW_Nextcellent' ) ? true : false;
108
+ $data['flagallery'] = class_exists( 'EWWW_Flag' ) ? true : false;
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' );
118
+ $data['pdf_level'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' );
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' );
125
+ $data['jpg_quality'] = (int) apply_filters( 'jpeg_quality', 82 );
126
+ $data['parallel_opt'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_parallel_optimization' );
127
+ $data['background_opt'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_background_optimization' );
128
+ $data['scheduled_opt'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_auto' );
129
+ $data['include_media_folders'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_include_media_paths' );
130
+ $data['folders_to_opt'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_aux_paths' );
131
+ $data['folders_to_ignore'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_exclude_paths' );
132
+ $data['resize_media_width'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' );
133
+ $data['resize_media_height'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' );
134
+ $data['resize_indirect_width'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherwidth' );
135
  $data['resize_indirect_height'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherheight' );
136
+ $data['resize_existing'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' );
137
+ $data['total_sizes'] = (int) count( ewww_image_optimizer_get_image_sizes() );
138
+ $data['disabled_opt_sizes'] = is_array( get_option( 'ewww_image_optimizer_disable_resizes_opt' ) ) ? count( get_option( 'ewww_image_optimizer_disable_resizes_opt' ) ) : 0;
139
+ $data['disabled_create_sizes'] = is_array( get_option( 'ewww_image_optimizer_disable_resizes' ) ) ? count( get_option( 'ewww_image_optimizer_disable_resizes' ) ) : 0;
140
+ $data['skip_small_images'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_skip_size' );
141
+ $data['skip_large_pngs'] = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_skip_png_size' );
142
+ $data['exclude_full_lossy'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_lossy_skip_full' );
143
+ $data['exclude_full_meta'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_skip_full' );
144
+ $data['system_paths'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_skip_bundle' );
145
+
146
+ $data['hide_conversion'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_convert_links' );
147
  $data['delete_originals'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' );
148
+ $data['jpg2png'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_to_png' );
149
+ $data['png2jpg'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_to_jpg' );
150
+ $data['gif2png'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_to_png' );
151
+ $data['fill_color'] = is_null( ewww_image_optimizer_jpg_background() ) ? '' : ewww_image_optimizer_jpg_background();
152
 
153
  $data['webp_create'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' );
154
+ $data['webp_force'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' );
155
+ $data['webp_urls'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' );
156
+ $data['alt_webp'] = (bool) ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' );
157
+
158
  $this->data = $data;
159
  }
160
 
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 ) ) {
194
+ $error_message = $request->get_error_message();
195
+ ewwwio_debug_message( "check-in failed: $error_message" );
196
  return $request;
197
  }
198
 
334
  ) {
335
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_tracking_notice', 1 );
336
  } else {
337
+ $admin_email = '<strong>' . esc_html( get_bloginfo( 'admin_email' ) ) . '</strong>';
338
+ $optin_url = 'admin.php?action=ewww_opt_into_tracking';
339
+ $optout_url = 'admin.php?action=ewww_opt_out_of_tracking';
340
  echo '<div class="updated"><p>';
341
+ /* translators: %s: admin email as configured in settings */
342
+ printf( esc_html__( 'Allow EWWW Image Optimizer to track plugin usage? Opt-in to tracking and receive 500 free image credits in your admin email: %s. No sensitive data is tracked.', 'ewww-image-optimizer' ), $admin_email );
343
+ echo '&nbsp;<a href="http://docs.ewww.io/article/23-usage-tracking" target="_blank" data-beacon-article="591f3a8e2c7d3a057f893d91">' . esc_html__( 'Learn more.', 'ewww-image-optimizer' ) . '</a>';
344
+ echo '<a href="' . esc_url( $optin_url ) . '" class="button-secondary" style="margin-left:5px;">' . esc_html__( 'Allow', 'ewww-image-optimizer' ) . '</a>';
345
+ echo '<a href="' . esc_url( $optout_url ) . '" class="button-secondary" style="margin-left:5px">' . esc_html__( 'Do not allow', 'ewww-image-optimizer' ) . '</a>';
346
  echo '</p></div>';
347
  }
348
  }
classes/class-exactdn.php ADDED
@@ -0,0 +1,1759 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class and methods to implement ExactDN (based on Photon implementation).
4
+ *
5
+ * @link https://ewww.io
6
+ * @package EWWW_Image_Optimizer
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ /**
14
+ * Enables EWWW IO to filter the page content and replace image urls with ExactDN urls.
15
+ */
16
+ class ExactDN {
17
+
18
+ /**
19
+ * Allowed extensions are currently only images. Might add PDF/CSS/JS at some point.
20
+ *
21
+ * @access private
22
+ * @var array $extensions
23
+ */
24
+ private $extensions = array(
25
+ 'gif',
26
+ 'jpg',
27
+ 'jpeg',
28
+ 'jpe',
29
+ 'png',
30
+ );
31
+
32
+ /**
33
+ * A list of image sizes registered for attachments.
34
+ *
35
+ * @access protected
36
+ * @var array $image_sizes
37
+ */
38
+ protected static $image_sizes = null;
39
+
40
+ /**
41
+ * Indicates if we are in full-page filtering mode.
42
+ *
43
+ * @access public
44
+ * @var bool $filtering_the_page
45
+ */
46
+ public $filtering_the_page = false;
47
+
48
+ /**
49
+ * Indicates if we are in content filtering mode.
50
+ *
51
+ * @access public
52
+ * @var bool $filtering_the_content
53
+ */
54
+ public $filtering_the_content = false;
55
+
56
+ /**
57
+ * List of permitted domains for ExactDN rewriting.
58
+ *
59
+ * @access public
60
+ * @var array $allowed_domains
61
+ */
62
+ public $allowed_domains = array();
63
+
64
+ /**
65
+ * The ExactDN domain/zone.
66
+ *
67
+ * @access private
68
+ * @var float $elapsed_time
69
+ */
70
+ private $exactdn_domain = false;
71
+
72
+ /**
73
+ * Allow us to track how much overhead ExactDN introduces.
74
+ *
75
+ * @access private
76
+ * @var float $elapsed_time
77
+ */
78
+ private $elapsed_time = 0;
79
+
80
+ /**
81
+ * Register (once) actions and filters for ExactDN. If you want to use this class, use the global.
82
+ */
83
+ function __construct() {
84
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
85
+ global $exactdn;
86
+ if ( is_object( $exactdn ) ) {
87
+ return 'you are doing it wrong';
88
+ }
89
+
90
+ // Make sure we have an ExactDN domain to use.
91
+ if ( ! $this->setup() ) {
92
+ return;
93
+ }
94
+
95
+ // Images in post content and galleries.
96
+ add_filter( 'the_content', array( $this, 'filter_the_content' ), 999999 );
97
+ // Start an output buffer before any output starts.
98
+ add_action( 'template_redirect', array( $this, 'buffer_start' ), 1 );
99
+
100
+ // Core image retrieval.
101
+ if ( ! function_exists( 'aq_resize' ) ) {
102
+ add_filter( 'image_downsize', array( $this, 'filter_image_downsize' ), 10, 3 );
103
+ } else {
104
+ ewwwio_debug_message( 'aq_resize detected, image_downsize filter disabled' );
105
+ }
106
+
107
+ // Overrides for admin-ajax images.
108
+ add_filter( 'exactdn_admin_allow_image_downsize', array( $this, 'allow_admin_image_downsize' ), 10, 2 );
109
+ // Overrides for "pass through" images.
110
+ add_filter( 'exactdn_pre_args', array( $this, 'exactdn_remove_args' ), 10, 3 );
111
+
112
+ // Responsive image srcset substitution.
113
+ add_filter( 'wp_calculate_image_srcset', array( $this, 'filter_srcset_array' ), 1001, 5 );
114
+ add_filter( 'wp_calculate_image_sizes', array( $this, 'filter_sizes' ), 1, 2 ); // Early so themes can still filter.
115
+
116
+ // DNS prefetching.
117
+ add_action( 'wp_head', array( $this, 'dns_prefetch' ) );
118
+
119
+ // Helpers for manipulated images.
120
+ if ( defined( 'EXACTDN_RECALC' ) && EXACTDN_RECALC ) {
121
+ add_action( 'wp_enqueue_scripts', array( $this, 'action_wp_enqueue_scripts' ), 9 );
122
+ }
123
+
124
+ // Find the "local" domain.
125
+ $upload_dir = wp_upload_dir( null, false );
126
+ $this->upload_domain = defined( 'EXACTDN_LOCAL_DOMAIN' ) && EXACTDN_LOCAL_DOMAIN ? EXACTDN_LOCAL_DOMAIN : $this->parse_url( $upload_dir['baseurl'], PHP_URL_HOST );
127
+ ewwwio_debug_message( "allowing images from here: $this->upload_domain" );
128
+ $this->allowed_domains[] = $this->upload_domain;
129
+ }
130
+
131
+ /**
132
+ * If ExactDN is enabled, validates and configures the ExactDN domain name.
133
+ */
134
+ function setup() {
135
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
136
+ // If we don't have a domain yet, go grab one.
137
+ if ( ! $this->get_exactdn_domain() ) {
138
+ ewwwio_debug_message( 'attempting to activate exactDN' );
139
+ $exactdn_domain = $this->activate_site();
140
+ } else {
141
+ ewwwio_debug_message( 'grabbing existing exactDN domain' );
142
+ $exactdn_domain = $this->get_exactdn_domain();
143
+ }
144
+ if ( ! $exactdn_domain ) {
145
+ if ( get_option( 'ewww_image_optimizer_exactdn_failures' ) < 5 ) {
146
+ $failures = (int) get_option( 'ewww_image_optimizer_exactdn_failures' );
147
+ $failures++;
148
+ ewwwio_debug_message( "could not activate ExactDN, failures: $failures" );
149
+ update_option( 'ewww_image_optimizer_exactdn_failures', $failures );
150
+ return false;
151
+ }
152
+ delete_option( 'ewww_image_optimizer_exactdn' );
153
+ delete_site_option( 'ewww_image_optimizer_exactdn' );
154
+ return false;
155
+ }
156
+ // If we have a domain, verify it.
157
+ if ( $this->verify_domain( $exactdn_domain ) ) {
158
+ ewwwio_debug_message( 'verified existing exactDN domain' );
159
+ delete_option( 'ewww_image_optimizer_exactdn_failures' );
160
+ $this->exactdn_domain = $exactdn_domain;
161
+ ewwwio_debug_message( 'exactdn_domain: ' . $exactdn_domain );
162
+ return true;
163
+ } elseif ( get_option( 'ewww_image_optimizer_exactdn_failures' ) < 5 ) {
164
+ $failures = (int) get_option( 'ewww_image_optimizer_exactdn_failures' );
165
+ $failures++;
166
+ ewwwio_debug_message( "could not verify existing exactDN domain, failures: $failures" );
167
+ update_option( 'ewww_image_optimizer_exactdn_failures', $failures );
168
+ $this->set_exactdn_checkin( time() + 3600 );
169
+ return false;
170
+ }
171
+ delete_option( 'ewww_image_optimizer_exactdn_domain' );
172
+ delete_site_option( 'ewww_image_optimizer_exactdn_domain' );
173
+ return false;
174
+ }
175
+
176
+ /**
177
+ * Use the Site URL to get the zone domain.
178
+ */
179
+ function activate_site() {
180
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
181
+ $site_url = get_home_url();
182
+ $url = 'http://optimize.exactlywww.com/exactdn/activate.php';
183
+ $ssl = wp_http_supports( array( 'ssl' ) );
184
+ if ( $ssl ) {
185
+ $url = set_url_scheme( $url, 'https' );
186
+ }
187
+ $result = wp_remote_post( $url, array(
188
+ 'timeout' => 10,
189
+ 'body' => array(
190
+ 'site_url' => $site_url,
191
+ ),
192
+ ) );
193
+ if ( is_wp_error( $result ) ) {
194
+ $error_message = $result->get_error_message();
195
+ ewwwio_debug_message( "exactdn activation request failed: $error_message" );
196
+ return false;
197
+ } elseif ( ! empty( $result['body'] ) && strpos( $result['body'], 'domain' ) !== false ) {
198
+ $response = json_decode( $result['body'], true );
199
+ if ( ! empty( $response['domain'] ) ) {
200
+ return $this->set_exactdn_domain( $response['domain'] );
201
+ }
202
+ } elseif ( ! empty( $result['body'] ) && strpos( $result['body'], 'error' ) !== false ) {
203
+ $response = json_decode( $result['body'], true );
204
+ $error_message = $response['error'];
205
+ ewwwio_debug_message( "exactdn activation request failed: $error_message" );
206
+ return false;
207
+ }
208
+ return false;
209
+ }
210
+
211
+ /**
212
+ * Verify the ExactDN domain.
213
+ *
214
+ * @param string $domain The ExactDN domain to verify.
215
+ * @return bool Whether the domain is still valid.
216
+ */
217
+ function verify_domain( $domain ) {
218
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
219
+ // Check the time, to see how long it has been since we verified the domain.
220
+ $last_checkin = $this->get_exactdn_checkin();
221
+ if ( ! empty( $last_checkin ) && $last_checkin > time() ) {
222
+ ewwwio_debug_message( 'not time yet' );
223
+ return true;
224
+ }
225
+ $url = 'http://optimize.exactlywww.com/exactdn/verify.php';
226
+ $ssl = wp_http_supports( array( 'ssl' ) );
227
+ if ( $ssl ) {
228
+ $url = set_url_scheme( $url, 'https' );
229
+ }
230
+ $result = wp_remote_post( $url, array(
231
+ 'timeout' => 10,
232
+ 'body' => array(
233
+ 'alias' => $domain,
234
+ ),
235
+ ) );
236
+ if ( is_wp_error( $result ) ) {
237
+ $error_message = $result->get_error_message();
238
+ ewwwio_debug_message( "exactdn verification request failed: $error_message" );
239
+ return false;
240
+ } elseif ( ! empty( $result['body'] ) && strpos( $result['body'], 'error' ) === false ) {
241
+ $response = json_decode( $result['body'], true );
242
+ if ( ! empty( $response['success'] ) ) {
243
+ $this->set_exactdn_checkin( time() + 86400 );
244
+ return true;
245
+ }
246
+ } elseif ( ! empty( $result['body'] ) ) {
247
+ $response = json_decode( $result['body'], true );
248
+ $error_message = $response['error'];
249
+ ewwwio_debug_message( "exactdn activation request failed: $error_message" );
250
+ return false;
251
+ }
252
+ return false;
253
+ }
254
+
255
+ /**
256
+ * Validate the ExactDN domain.
257
+ *
258
+ * @param string $domain The unverified ExactDN domain.
259
+ * @return string The validated ExactDN domain.
260
+ */
261
+ function sanitize_domain( $domain ) {
262
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
263
+ if ( ! $domain ) {
264
+ return;
265
+ }
266
+ if ( strlen( $domain ) > 80 ) {
267
+ ewwwio_debug_message( "$domain too long" );
268
+ return false;
269
+ }
270
+ if ( ! preg_match( '#^[A-Za-z0-9\.\-]+$#', $domain ) ) {
271
+ ewwwio_debug_message( "$domain has bad characters" );
272
+ return false;
273
+ }
274
+ return $domain;
275
+ }
276
+
277
+ /**
278
+ * Get the ExactDN domain name to use.
279
+ *
280
+ * @return string The ExactDN domain name for this site or network.
281
+ */
282
+ function get_exactdn_domain() {
283
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
284
+ if ( defined( 'EXACTDN_DOMAIN' ) && EXACTDN_DOMAIN ) {
285
+ return $this->sanitize_domain( EXACTDN_DOMAIN );
286
+ }
287
+ if ( is_multisite() ) {
288
+ if ( ! SUBDOMAIN_INSTALL ) {
289
+ return $this->sanitize_domain( get_site_option( 'ewww_image_optimizer_exactdn_domain' ) );
290
+ }
291
+ }
292
+ return $this->sanitize_domain( get_option( 'ewww_image_optimizer_exactdn_domain' ) );
293
+ }
294
+
295
+ /**
296
+ * Get the ExactDN last check-in time.
297
+ *
298
+ * @return int The last time we verified the ExactDN domain.
299
+ */
300
+ function get_exactdn_checkin() {
301
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
302
+ if ( defined( 'EXACTDN_DOMAIN' ) && EXACTDN_DOMAIN ) {
303
+ return (int) get_option( 'ewww_image_optimizer_exactdn_validation' );
304
+ }
305
+ if ( is_multisite() ) {
306
+ if ( ! SUBDOMAIN_INSTALL ) {
307
+ return (int) get_site_option( 'ewww_image_optimizer_exactdn_validation' );
308
+ }
309
+ }
310
+ return (int) get_option( 'ewww_image_optimizer_exactdn_validation' );
311
+ }
312
+
313
+ /**
314
+ * Set the ExactDN domain name to use.
315
+ *
316
+ * @param string $domain The ExactDN domain name for this site or network.
317
+ */
318
+ function set_exactdn_domain( $domain ) {
319
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
320
+ if ( defined( 'EXACTDN_DOMAIN' ) && $this->sanitize_domain( EXACTDN_DOMAIN ) ) {
321
+ return true;
322
+ }
323
+ $domain = $this->sanitize_domain( $domain );
324
+ if ( ! $domain ) {
325
+ return false;
326
+ }
327
+ if ( is_multisite() ) {
328
+ if ( ! SUBDOMAIN_INSTALL ) {
329
+ update_site_option( 'ewww_image_optimizer_exactdn_domain', $domain );
330
+ return $domain;
331
+ }
332
+ }
333
+ update_option( 'ewww_image_optimizer_exactdn_domain', $domain );
334
+ return $domain;
335
+ }
336
+
337
+ /**
338
+ * Set the last check-in time for ExactDN.
339
+ *
340
+ * @param int $time The last time we verified the ExactDN domain.
341
+ */
342
+ function set_exactdn_checkin( $time ) {
343
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
344
+ if ( defined( 'EXACTDN_DOMAIN' ) && EXACTDN_DOMAIN ) {
345
+ return update_option( 'ewww_image_optimizer_exactdn_validation', $time );
346
+ }
347
+ if ( is_multisite() ) {
348
+ if ( ! SUBDOMAIN_INSTALL ) {
349
+ return update_site_option( 'ewww_image_optimizer_exactdn_validation', $time );
350
+ }
351
+ }
352
+ return update_option( 'ewww_image_optimizer_exactdn_validation', $time );
353
+ }
354
+
355
+ /**
356
+ * Match all images and any relevant <a> tags in a block of HTML.
357
+ *
358
+ * @param string $content Some HTML.
359
+ * @return array An array of $images matches, where $images[0] is
360
+ * an array of full matches, and the link_url, img_tag,
361
+ * and img_url keys are arrays of those matches.
362
+ */
363
+ function parse_images_from_html( $content ) {
364
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
365
+ $images = array();
366
+
367
+ if ( preg_match_all( '#(?:<a[^>]+?href=["|\'](?P<link_url>[^\s]+?)["|\'][^>]*?>\s*)?(?P<img_tag><img[^>]*?\s+?src=["|\'](?P<img_url>[^\s]+?)["|\'].*?>){1}(?:\s*</a>)?#is', $content, $images ) ) {
368
+ foreach ( $images as $key => $unused ) {
369
+ // Simplify the output as much as possible, mostly for confirming test results.
370
+ if ( is_numeric( $key ) && $key > 0 ) {
371
+ unset( $images[ $key ] );
372
+ }
373
+ }
374
+ return $images;
375
+ }
376
+ return array();
377
+ }
378
+
379
+ /**
380
+ * Try to determine height and width from strings WP appends to resized image filenames.
381
+ *
382
+ * @param string $src The image URL.
383
+ * @return array An array consisting of width and height.
384
+ */
385
+ function parse_dimensions_from_filename( $src ) {
386
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
387
+ $width_height_string = array();
388
+ ewwwio_debug_message( "looking for dimensions in $src" );
389
+ if ( preg_match( '#-(\d+)x(\d+)(@2x)?\.(?:' . implode( '|', $this->extensions ) . '){1}(?:\?.+)?$#i', $src, $width_height_string ) ) {
390
+ $width = (int) $width_height_string[1];
391
+ $height = (int) $width_height_string[2];
392
+
393
+ if ( strpos( $src, '@2x' ) ) {
394
+ $width = 2 * $width;
395
+ $height = 2 * $height;
396
+ }
397
+ if ( $width && $height ) {
398
+ ewwwio_debug_message( "found w$width h$height" );
399
+ return array( $width, $height );
400
+ }
401
+ }
402
+ return array( false, false );
403
+ }
404
+
405
+ /**
406
+ * Get $content_width, with a filter.
407
+ *
408
+ * @return bool|string The content width, if set. Default false.
409
+ */
410
+ function get_content_width() {
411
+ $content_width = isset( $GLOBALS['content_width'] ) ? $GLOBALS['content_width'] : false;
412
+ /**
413
+ * Filter the Content Width value.
414
+ *
415
+ * @param string $content_width Content Width value.
416
+ */
417
+ return apply_filters( 'exactdn_content_width', $content_width );
418
+ }
419
+
420
+ /**
421
+ * Starts an output buffer and registers the callback function to do ExactDN url replacement.
422
+ */
423
+ function buffer_start() {
424
+ ob_start( array( $this, 'filter_the_page' ) );
425
+ }
426
+
427
+ /**
428
+ * Identify images in page content, and if images are local (uploaded to the current site), pass through ExactDN.
429
+ *
430
+ * @param string $content The page/post content.
431
+ * @return string The content with ExactDN image urls.
432
+ */
433
+ function filter_the_page( $content ) {
434
+ $this->filtering_the_page = true;
435
+
436
+ $content = $this->filter_the_content( $content );
437
+
438
+ $this->filtering_the_page = false;
439
+ ewwwio_debug_message( "parsing page took $this->elapsed_time seconds" );
440
+ return $content;
441
+ }
442
+
443
+ /**
444
+ * Identify images in the content, and if images are local (uploaded to the current site), pass through ExactDN.
445
+ *
446
+ * @param string $content The page/post content.
447
+ * @return string The content with ExactDN image urls.
448
+ */
449
+ function filter_the_content( $content ) {
450
+ $started = microtime( true );
451
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
452
+ $images = $this->parse_images_from_html( $content );
453
+
454
+ if ( ! empty( $images ) ) {
455
+ ewwwio_debug_message( 'we have images to parse' );
456
+ $content_width = false;
457
+ if ( ! $this->filtering_the_page ) {
458
+ $this->filtering_the_content = true;
459
+ ewwwio_debug_message( 'filtering the content' );
460
+ $content_width = $this->get_content_width();
461
+ }
462
+ $resize_existing = defined( 'EXACTDN_RESIZE_EXISTING' ) && EXACTDN_RESIZE_EXISTING;
463
+
464
+ $image_sizes = $this->image_sizes();
465
+
466
+ foreach ( $images[0] as $index => $tag ) {
467
+ // Default to resize, though fit may be used in certain cases where a dimension cannot be ascertained.
468
+ $transform = 'resize';
469
+
470
+ // Start with a clean attachment ID each time.
471
+ $attachment_id = false;
472
+
473
+ // Flag if we need to munge a fullsize URL.
474
+ $fullsize_url = false;
475
+
476
+ // Identify image source.
477
+ $src = $images['img_url'][ $index ];
478
+ $src_orig = $images['img_url'][ $index ];
479
+ ewwwio_debug_message( $src );
480
+
481
+ /**
482
+ * Allow specific images to be skipped by ExactDN.
483
+ *
484
+ * @param bool false Should ExactDN ignore this image. Default false.
485
+ * @param string $src Image URL.
486
+ * @param string $tag Image HTML Tag.
487
+ */
488
+ if ( apply_filters( 'exactdn_skip_image', false, $src, $tag ) ) {
489
+ continue;
490
+ }
491
+
492
+ ewwwio_debug_message( 'made it passed the filters' );
493
+ // Support Lazy Load plugins.
494
+ // Don't modify $tag yet as we need unmodified version later.
495
+ if ( preg_match( '#data-lazy-src=["|\'](.+?)["|\']#i', $images['img_tag'][ $index ], $lazy_load_src ) ) {
496
+ $placeholder_src = $src;
497
+ $placeholder_src_orig = $src;
498
+ $src = $lazy_load_src[1];
499
+ $src_orig = $lazy_load_src[1];
500
+ } elseif ( preg_match( '#data-lazy-original=["|\'](.+?)["|\']#i', $images['img_tag'][ $index ], $lazy_load_src ) ) {
501
+ $placeholder_src = $src;
502
+ $placeholder_src_orig = $src;
503
+ $src = $lazy_load_src[1];
504
+ $src_orig = $lazy_load_src[1];
505
+ }
506
+
507
+ // Check if image URL should be used with ExactDN.
508
+ if ( $this->validate_image_url( $src ) ) {
509
+ ewwwio_debug_message( 'url validated' );
510
+ // Find the width and height attributes.
511
+ $width = false;
512
+ $height = false;
513
+
514
+ // First, check the image tag.
515
+ if ( preg_match( '#width=["|\']?([\d%]+)["|\']?#i', $images['img_tag'][ $index ], $width_string ) ) {
516
+ $width = $width_string[1];
517
+ }
518
+
519
+ if ( preg_match( '#height=["|\']?([\d%]+)["|\']?#i', $images['img_tag'][ $index ], $height_string ) ) {
520
+ $height = $height_string[1];
521
+ }
522
+
523
+ // Can't pass both a relative width and height, so unset the dimensions in favor of not breaking the horizontal layout.
524
+ if ( false !== strpos( $width, '%' ) && false !== strpos( $height, '%' ) ) {
525
+ $width = false;
526
+ $height = false;
527
+ }
528
+
529
+ // Detect WP registered image size from HTML class.
530
+ if ( preg_match( '#class=["|\']?[^"\']*size-([^"\'\s]+)[^"\']*["|\']?#i', $images['img_tag'][ $index ], $size ) ) {
531
+ $size = array_pop( $size );
532
+
533
+ ewwwio_debug_message( "detected $size" );
534
+ if ( false === $width && false === $height && 'full' != $size && array_key_exists( $size, $image_sizes ) ) {
535
+ $width = (int) $image_sizes[ $size ]['width'];
536
+ $height = (int) $image_sizes[ $size ]['height'];
537
+ $transform = $image_sizes[ $size ]['crop'] ? 'resize' : 'fit';
538
+ }
539
+ } else {
540
+ unset( $size );
541
+ }
542
+
543
+ list( $filename_width, $filename_height ) = $this->parse_dimensions_from_filename( $src );
544
+ // WP Attachment ID, if uploaded to this site.
545
+ preg_match( '#class=["|\']?[^"\']*wp-image-([\d]+)[^"\']*["|\']?#i', $images['img_tag'][ $index ], $attachment_id );
546
+ if ( empty( $attachment_id ) ) {
547
+ $attachment_id = array( attachment_url_to_postid( $src ) );
548
+ }
549
+ if ( ! empty( $attachment_id ) ) {
550
+ $attachment_id = intval( array_pop( $attachment_id ) );
551
+
552
+ if ( $attachment_id ) {
553
+ ewwwio_debug_message( "detected attachment $attachment_id" );
554
+ $attachment = get_post( $attachment_id );
555
+
556
+ // Basic check on returned post object.
557
+ if ( is_object( $attachment ) && ! is_wp_error( $attachment ) && 'attachment' == $attachment->post_type ) {
558
+ $src_per_wp = wp_get_attachment_image_src( $attachment_id, 'full' );
559
+
560
+ if ( $this->validate_image_url( $src_per_wp[0] ) ) {
561
+ ewwwio_debug_message( "detected $width filenamew $filename_width" );
562
+ if ( $resize_existing || ( $width && $filename_width != $width ) ) {
563
+ ewwwio_debug_message( 'resizing existing or width does not match' );
564
+ $src = $src_per_wp[0];
565
+ }
566
+ $fullsize_url = true;
567
+
568
+ // Prevent image distortion if a detected dimension exceeds the image's natural dimensions.
569
+ if ( ( false !== $width && $width > $src_per_wp[1] ) || ( false !== $height && $height > $src_per_wp[2] ) ) {
570
+ $width = false === $width ? false : min( $width, $src_per_wp[1] );
571
+ $height = false === $height ? false : min( $height, $src_per_wp[2] );
572
+ }
573
+
574
+ // If no width and height are found, max out at source image's natural dimensions.
575
+ // Otherwise, respect registered image sizes' cropping setting.
576
+ if ( false === $width && false === $height ) {
577
+ $width = $src_per_wp[1];
578
+ $height = $src_per_wp[2];
579
+ $transform = 'fit';
580
+ } elseif ( isset( $size ) && array_key_exists( $size, $image_sizes ) && isset( $image_sizes[ $size ]['crop'] ) ) {
581
+ $transform = (bool) $image_sizes[ $size ]['crop'] ? 'resize' : 'fit';
582
+ }
583
+ }
584
+ } else {
585
+ unset( $attachment_id );
586
+ unset( $attachment );
587
+ }
588
+ }
589
+ }
590
+
591
+ // If width is available, constrain to $content_width.
592
+ if ( false !== $width && false === strpos( $width, '%' ) && is_numeric( $content_width ) ) {
593
+ if ( $width > $content_width && false !== $height && false === strpos( $height, '%' ) ) {
594
+ ewwwio_debug_message( 'constraining to content width' );
595
+ $height = round( ( $content_width * $height ) / $width );
596
+ $width = $content_width;
597
+ } elseif ( $width > $content_width ) {
598
+ ewwwio_debug_message( 'constraining to content width' );
599
+ $width = $content_width;
600
+ }
601
+ }
602
+
603
+ // Set a width if none is found and $content_width is available.
604
+ // If width is set in this manner and height is available, use `fit` instead of `resize` to prevent skewing.
605
+ if ( false === $width && is_numeric( $content_width ) ) {
606
+ $width = (int) $content_width;
607
+
608
+ if ( false !== $height ) {
609
+ $transform = 'fit';
610
+ }
611
+ }
612
+
613
+ // Detect if image source is for a custom-cropped thumbnail and prevent further URL manipulation.
614
+ if ( ! $fullsize_url && preg_match_all( '#-e[a-z0-9]+(-\d+x\d+)?\.(' . implode( '|', $this->extensions ) . '){1}$#i', basename( $src ), $filename ) ) {
615
+ $fullsize_url = true;
616
+ }
617
+
618
+ // Build array of ExactDN args and expose to filter before passing to ExactDN URL function.
619
+ $args = array();
620
+
621
+ if ( false !== $width && false !== $height && false === strpos( $width, '%' ) && false === strpos( $height, '%' ) ) {
622
+ $args[ $transform ] = $width . ',' . $height;
623
+ } elseif ( false !== $width ) {
624
+ $args['w'] = $width;
625
+ } elseif ( false !== $height ) {
626
+ $args['h'] = $height;
627
+ }
628
+
629
+ if ( ! $resize_existing && ( ! $width || $filename_width == $width ) ) {
630
+ ewwwio_debug_message( 'preventing resize' );
631
+ $args = array();
632
+ } elseif ( ! $fullsize_url ) {
633
+ // Build URL, first maybe removing WP's resized string so we pass the original image to ExactDN (for higher quality).
634
+ $src = $this->strip_image_dimensions_maybe( $src );
635
+ }
636
+
637
+ $args = $this->maybe_smart_crop( $args, $attachment_id );
638
+
639
+ /**
640
+ * Filter the array of ExactDN arguments added to an image.
641
+ * By default, only includes width and height values.
642
+ *
643
+ * @param array $args Array of ExactDN Arguments.
644
+ * @param array $args {
645
+ * Array of image details.
646
+ *
647
+ * @type $tag Image tag (Image HTML output).
648
+ * @type $src Image URL.
649
+ * @type $src_orig Original Image URL.
650
+ * @type $width Image width.
651
+ * @type $height Image height.
652
+ * }
653
+ */
654
+ $args = apply_filters( 'exactdn_post_image_args', $args, compact( 'tag', 'src', 'src_orig', 'width', 'height' ) );
655
+ ewwwio_debug_message( "width $width" );
656
+ ewwwio_debug_message( "height $height" );
657
+ ewwwio_debug_message( "transform $transform" );
658
+
659
+ $exactdn_url = $this->generate_url( $src, $args );
660
+ ewwwio_debug_message( "new url $exactdn_url" );
661
+
662
+ // Modify image tag if ExactDN function provides a URL
663
+ // Ensure changes are only applied to the current image by copying and modifying the matched tag, then replacing the entire tag with our modified version.
664
+ if ( $src != $exactdn_url ) {
665
+ $new_tag = $tag;
666
+
667
+ // If present, replace the link href with an ExactDN URL for the full-size image.
668
+ if ( ! empty( $images['link_url'][ $index ] ) && $this->validate_image_url( $images['link_url'][ $index ] ) ) {
669
+ $new_tag = preg_replace( '#(href=["|\'])' . $images['link_url'][ $index ] . '(["|\'])#i', '\1' . $this->generate_url( $images['link_url'][ $index ] ) . '\2', $new_tag, 1 );
670
+ }
671
+
672
+ // Insert new image src into the srcset as well, if we have a width.
673
+ if ( false !== $width && false === strpos( $width, '%' ) ) {
674
+ ewwwio_debug_message( 'checking to see if srcset width already exists' );
675
+ $srcset_url = $exactdn_url . ' ' . (int) $width . 'w, ';
676
+ if ( false === strpos( $tag, $width . 'w' ) ) {
677
+ // For double-quotes...
678
+ $new_tag = str_replace( 'srcset="', 'srcset="' . $srcset_url, $new_tag );
679
+ // and for single-quotes.
680
+ $new_tag = str_replace( "srcset='", "srcset='" . $srcset_url, $new_tag );
681
+ }
682
+ }
683
+
684
+ // Supplant the original source value with our ExactDN URL.
685
+ $exactdn_url = esc_url( $exactdn_url );
686
+ $new_tag = str_replace( $src_orig, $exactdn_url, $new_tag );
687
+
688
+ // If Lazy Load is in use, pass placeholder image through ExactDN.
689
+ if ( isset( $placeholder_src ) && $this->validate_image_url( $placeholder_src ) ) {
690
+ $placeholder_src = $this->generate_url( $placeholder_src );
691
+
692
+ if ( $placeholder_src != $placeholder_src_orig ) {
693
+ $new_tag = str_replace( $placeholder_src_orig, esc_url( $placeholder_src ), $new_tag );
694
+ }
695
+
696
+ unset( $placeholder_src );
697
+ }
698
+
699
+ // Enable image dimension recalculation via wp-config.php.
700
+ if ( defined( 'EXACTDN_RECALC' ) && EXACTDN_RECALC ) {
701
+ // Remove the width and height arguments from the tag to prevent distortion.
702
+ $new_tag = preg_replace( '#(?<=\s)(width|height)=["|\']?[\d%]+["|\']?\s?#i', '', $new_tag );
703
+
704
+ // Tag an image for dimension checking (via JS).
705
+ $new_tag = preg_replace( '#(\s?/)?>(\s*</a>)?$#i', ' data-recalc-dims="1"\1>\2', $new_tag );
706
+ }
707
+ // Replace original tag with modified version.
708
+ $content = str_replace( $tag, $new_tag, $content );
709
+ }
710
+ } elseif ( ! preg_match( '#data-lazy-(original|src)=#i', $images['img_tag'][ $index ] ) && $this->validate_image_url( $src, true ) ) {
711
+ ewwwio_debug_message( 'found a potential exactdn src url to insert into srcset' );
712
+ // Find the width attribute.
713
+ $width = false;
714
+ // First, check the image tag.
715
+ if ( preg_match( '#width=["|\']?([\d%]+)["|\']?#i', $tag, $width_string ) ) {
716
+ $width = $width_string[1];
717
+ ewwwio_debug_message( 'found the width' );
718
+ // Insert new image src into the srcset as well, if we have a width.
719
+ if (
720
+ false !== $width &&
721
+ false === strpos( $width, '%' ) &&
722
+ false !== strpos( $src, $width ) &&
723
+ (
724
+ false !== strpos( $src, 'exactdn.com' ) ||
725
+ false !== strpos( $src, 'exactdn.net' ) ||
726
+ false !== strpos( $src, 'exactcdn.com' ) ||
727
+ false !== strpos( $src, 'exactcdn.net' )
728
+ )
729
+ ) {
730
+ $new_tag = $tag;
731
+ $exactdn_url = $src;
732
+ ewwwio_debug_message( 'checking to see if srcset width already exists' );
733
+ $srcset_url = $exactdn_url . ' ' . (int) $width . 'w, ';
734
+ if ( false === strpos( $tag, $width . 'w' ) ) {
735
+ ewwwio_debug_message( 'src not in srcset, adding' );
736
+ // For double-quotes...
737
+ $new_tag = str_replace( 'srcset="', 'srcset="' . $srcset_url, $new_tag );
738
+ // and for single-quotes.
739
+ $new_tag = str_replace( "srcset='", "srcset='" . $srcset_url, $new_tag );
740
+ // Replace original tag with modified version.
741
+ $content = str_replace( $tag, $new_tag, $content );
742
+ }
743
+ }
744
+ }
745
+ } // End if().
746
+ } // End foreach().
747
+ if ( $this->filtering_the_page && defined( 'EXACTDN_ALL_THE_THINGS' ) && EXACTDN_ALL_THE_THINGS ) {
748
+ ewwwio_debug_message( 'rewriting all other wp_content urls' );
749
+ if ( $this->exactdn_domain && $this->upload_domain ) {
750
+ $escaped_upload_domain = str_replace( '.', '\.', $this->upload_domain );
751
+ ewwwio_debug_message( $escaped_upload_domain );
752
+ // Pre-empt rewriting of wp-includes and wp-content if the extension is php/ashx by using a temporary placeholder.
753
+ $content = preg_replace( '#(https?)://' . $escaped_upload_domain . '([^"\'?>]+?)?/wp-content/([^"\'?>]+?)\.(php|ashx)#i', '$1://' . $this->upload_domain . '$2/?wpcontent-bypass?/$3.$4', $content );
754
+ $content = preg_replace( '#(https?)://' . $escaped_upload_domain . '/([^"\'?>]+?)?wp-(includes|content)#i', '$1://' . $this->exactdn_domain . '/$2wp-$3', $content );
755
+ $content = str_replace( '?wpcontent-bypass?', 'wp-content', $content );
756
+ }
757
+ }
758
+ } // End if();
759
+ ewwwio_debug_message( 'done parsing page' );
760
+ $this->filtering_the_content = false;
761
+
762
+ $elapsed_time = microtime( true ) - $started;
763
+ ewwwio_debug_message( "parsing the_content took $elapsed_time seconds" );
764
+ $this->elapsed_time += microtime( true ) - $started;
765
+ return $content;
766
+ }
767
+
768
+ /**
769
+ * Allow resizing of images for some admin-ajax requests.
770
+ *
771
+ * @param bool $allow Will normally be false, unless already modified by another function.
772
+ * @param array $image Bunch of information about the image, but we don't care about that here.
773
+ * @return bool True if it's an allowable admin-ajax request, false for all other admin requests.
774
+ */
775
+ function allow_admin_image_downsize( $allow, $image ) {
776
+ if ( ! wp_doing_ajax() ) {
777
+ return $allow;
778
+ }
779
+ if ( ! empty( $_POST['action'] ) && 'eddvbugm_viewport_downloads' == $_POST['action'] ) {
780
+ return true;
781
+ }
782
+ return $allow;
783
+ }
784
+
785
+ /**
786
+ * Filter post thumbnail image retrieval, passing images through ExactDN.
787
+ *
788
+ * @param array|bool $image Defaults to false, but may be a url if another plugin/theme has already filtered the value.
789
+ * @param int $attachment_id The ID number for the image attachment.
790
+ * @param string|array $size The name of the image size or an array of width and height. Default 'medium'.
791
+ * @uses is_admin, apply_filters, wp_get_attachment_url, this::validate_image_url, this::image_sizes, this::generate_url
792
+ * @filter image_downsize
793
+ * @return string|bool
794
+ */
795
+ function filter_image_downsize( $image, $attachment_id, $size ) {
796
+ $started = microtime( true );
797
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
798
+ // Don't foul up the admin side of things, unless a plugin wants to.
799
+ if ( is_admin() &&
800
+ /**
801
+ * Provide plugins a way of running ExactDN for images in the WordPress Dashboard (wp-admin).
802
+ *
803
+ * Note: enabling this will result in ExactDN URLs added to your post content, which could make migrations across domains (and off ExactDN) a bit more challenging.
804
+ *
805
+ * @param bool false Stop ExactDN from being run on the Dashboard. Default to false.
806
+ * @param array $args {
807
+ * Array of image details.
808
+ *
809
+ * @type array|bool $image Image URL or false.
810
+ * @type int $attachment_id Attachment ID of the image.
811
+ * @type array|string $size Image size. Can be a string (name of the image size, e.g. full) or an array of height and width.
812
+ * }
813
+ */
814
+ false === apply_filters( 'exactdn_admin_allow_image_downsize', false, compact( 'image', 'attachment_id', 'size' ) )
815
+ ) {
816
+ return $image;
817
+ }
818
+
819
+ /**
820
+ * Provide plugins a way of preventing ExactDN from being applied to images retrieved from WordPress Core.
821
+ *
822
+ * @param bool false Stop ExactDN from being applied to the image. Default to false.
823
+ * @param array $args {
824
+ * Array of image details.
825
+ *
826
+ * @type string|bool $image Image URL or false.
827
+ * @type int $attachment_id Attachment ID of the image.
828
+ * @type array|string $size Image size. Can be a string (name of the image size, e.g. full) or an array of height and width.
829
+ * }
830
+ */
831
+ if ( apply_filters( 'exactdn_override_image_downsize', false, compact( 'image', 'attachment_id', 'size' ) ) ) {
832
+ return $image;
833
+ }
834
+
835
+ if ( function_exists( 'aq_resize' ) ) {
836
+ ewwwio_debug_message( 'aq_resize detected, image_downsize filter disabled' );
837
+ return $image;
838
+ }
839
+
840
+ if ( $this->filtering_the_content || $this->filtering_the_page ) {
841
+ ewwwio_debug_message( 'end image_downsize early' );
842
+ return $image;
843
+ }
844
+
845
+ // Get the image URL and proceed with ExactDN replacement if successful.
846
+ $image_url = wp_get_attachment_url( $attachment_id );
847
+ ewwwio_debug_message( $image_url );
848
+ ewwwio_debug_message( $attachment_id );
849
+ if ( is_string( $size ) || is_int( $size ) ) {
850
+ ewwwio_debug_message( $size );
851
+ } elseif ( is_array( $size ) ) {
852
+ foreach ( $size as $dimension ) {
853
+ ewwwio_debug_message( 'dimension: ' . $dimension );
854
+ }
855
+ }
856
+ // Set this to true later when we know we have size meta.
857
+ $has_size_meta = false;
858
+
859
+ if ( $image_url ) {
860
+ // Check if image URL should be used with ExactDN.
861
+ if ( ! $this->validate_image_url( $image_url ) ) {
862
+ return $image;
863
+ }
864
+
865
+ $intermediate = true; // For the fourth array item returned by the image_downsize filter.
866
+ $resize_existing = defined( 'EXACTDN_RESIZE_EXISTING' ) && EXACTDN_RESIZE_EXISTING;
867
+
868
+ // If an image is requested with a size known to WordPress, use that size's settings with ExactDN.
869
+ if ( is_string( $size ) && array_key_exists( $size, $this->image_sizes() ) ) {
870
+ $image_args = $this->image_sizes();
871
+ $image_args = $image_args[ $size ];
872
+
873
+ $exactdn_args = array();
874
+
875
+ $image_meta = image_get_intermediate_size( $attachment_id, $size );
876
+
877
+ // 'full' is a special case: We need consistent data regardless of the requested size.
878
+ if ( 'full' === $size ) {
879
+ $image_meta = wp_get_attachment_metadata( $attachment_id );
880
+ $intermediate = false;
881
+ } elseif ( ! $image_meta ) {
882
+ // If we still don't have any image meta at this point, it's probably from a custom thumbnail size
883
+ // for an image that was uploaded before the custom image was added to the theme. Try to determine the size manually.
884
+ $image_meta = wp_get_attachment_metadata( $attachment_id );
885
+
886
+ if ( isset( $image_meta['width'], $image_meta['height'] ) ) {
887
+ $image_resized = image_resize_dimensions( $image_meta['width'], $image_meta['height'], $image_args['width'], $image_args['height'], $image_args['crop'] );
888
+ if ( $image_resized ) { // This could be false when the requested image size is larger than the full-size image.
889
+ $image_meta['width'] = $image_resized[6];
890
+ $image_meta['height'] = $image_resized[7];
891
+ }
892
+ }
893
+ }
894
+
895
+ if ( isset( $image_meta['width'], $image_meta['height'] ) ) {
896
+ $image_args['width'] = $image_meta['width'];
897
+ $image_args['height'] = $image_meta['height'];
898
+
899
+ list( $image_args['width'], $image_args['height'] ) = image_constrain_size_for_editor( $image_args['width'], $image_args['height'], $size, 'display' );
900
+
901
+ $has_size_meta = true;
902
+ }
903
+
904
+ // Expose determined arguments to a filter before passing to ExactDN.
905
+ $transform = $image_args['crop'] ? 'resize' : 'fit';
906
+
907
+ // Check specified image dimensions and account for possible zero values; ExactDN fails to resize if a dimension is zero.
908
+ if ( 0 == $image_args['width'] || 0 == $image_args['height'] ) {
909
+ if ( 0 == $image_args['width'] && 0 < $image_args['height'] ) {
910
+ $exactdn_args['h'] = $image_args['height'];
911
+ } elseif ( 0 == $image_args['height'] && 0 < $image_args['width'] ) {
912
+ $exactdn_args['w'] = $image_args['width'];
913
+ }
914
+ } else {
915
+ $image_meta = wp_get_attachment_metadata( $attachment_id );
916
+ if ( ( 'resize' === $transform ) && $image_meta ) {
917
+ if ( isset( $image_meta['width'], $image_meta['height'] ) ) {
918
+ // Lets make sure that we don't upscale images since wp never upscales them as well.
919
+ $smaller_width = ( ( $image_meta['width'] < $image_args['width'] ) ? $image_meta['width'] : $image_args['width'] );
920
+ $smaller_height = ( ( $image_meta['height'] < $image_args['height'] ) ? $image_meta['height'] : $image_args['height'] );
921
+
922
+ $exactdn_args[ $transform ] = $smaller_width . ',' . $smaller_height;
923
+ }
924
+ } else {
925
+ $exactdn_args[ $transform ] = $image_args['width'] . ',' . $image_args['height'];
926
+ }
927
+ }
928
+
929
+ if ( ! empty( $image_meta['sizes'] ) && 'full' !== $size && ! empty( $image_meta['sizes'][ $size ]['file'] ) ) {
930
+ $image_url_basename = wp_basename( $image_url );
931
+ $intermediate_url = str_replace( $image_url_basename, $image_meta['sizes'][ $size ]['file'], $image_url );
932
+
933
+ list( $filename_width, $filename_height ) = $this->parse_dimensions_from_filename( $intermediate_url );
934
+ if ( $filename_width && $filename_height && $image_args['width'] === $filename_width && $image_args['height'] === $filename_height ) {
935
+ $image_url = $intermediate_url;
936
+ } else {
937
+ $resize_existing = true;
938
+ }
939
+ } else {
940
+ $resize_existing = true;
941
+ }
942
+
943
+ $exactdn_args = $this->maybe_smart_crop( $exactdn_args, $attachment_id, $image_meta );
944
+
945
+ /**
946
+ * Filter the ExactDN arguments added to an image, when that image size is a string.
947
+ * Image size will be a string (e.g. "full", "medium") when it is known to WordPress.
948
+ *
949
+ * @param array $exactdn_args ExactDN arguments.
950
+ * @param array $args {
951
+ * Array of image details.
952
+ *
953
+ * @type array $image_args Image arguments (width, height, crop).
954
+ * @type string $image_url Image URL.
955
+ * @type int $attachment_id Attachment ID of the image.
956
+ * @type string $size Image size name.
957
+ * @type string $transform Value can be resize or fit.
958
+ * }
959
+ */
960
+ $exactdn_args = apply_filters( 'exactdn_image_downsize_string', $exactdn_args, compact( 'image_args', 'image_url', 'attachment_id', 'size', 'transform' ) );
961
+
962
+ // Generate ExactDN URL.
963
+ if ( ! $resize_existing ) {
964
+ $image = array(
965
+ $this->generate_url( $image_url ),
966
+ $has_size_meta ? $image_args['width'] : false,
967
+ $has_size_meta ? $image_args['height'] : false,
968
+ $intermediate,
969
+ );
970
+ } else {
971
+ $image = array(
972
+ $this->generate_url( $image_url, $exactdn_args ),
973
+ $has_size_meta ? $image_args['width'] : false,
974
+ $has_size_meta ? $image_args['height'] : false,
975
+ $intermediate,
976
+ );
977
+ }
978
+ } elseif ( is_array( $size ) ) {
979
+ // Pull width and height values from the provided array, if possible.
980
+ $width = isset( $size[0] ) ? (int) $size[0] : false;
981
+ $height = isset( $size[1] ) ? (int) $size[1] : false;
982
+
983
+ // Don't bother if necessary parameters aren't passed.
984
+ if ( ! $width || ! $height ) {
985
+ return $image;
986
+ }
987
+
988
+ $image_meta = wp_get_attachment_metadata( $attachment_id );
989
+ if ( isset( $image_meta['width'], $image_meta['height'] ) ) {
990
+ $image_resized = image_resize_dimensions( $image_meta['width'], $image_meta['height'], $width, $height );
991
+
992
+ if ( $image_resized ) { // This could be false when the requested image size is larger than the full-size image.
993
+ $width = $image_resized[6];
994
+ $height = $image_resized[7];
995
+ } else {
996
+ $width = $image_meta['width'];
997
+ $height = $image_meta['height'];
998
+ }
999
+ $has_size_meta = true;
1000
+ }
1001
+
1002
+ list( $width, $height ) = image_constrain_size_for_editor( $width, $height, $size );
1003
+
1004
+ // Expose arguments to a filter before passing to ExactDN.
1005
+ $exactdn_args = array(
1006
+ 'fit' => $width . ',' . $height,
1007
+ );
1008
+
1009
+ $exactdn_args = $this->maybe_smart_crop( $exactdn_args, $attachment_id, $image_meta );
1010
+
1011
+ /**
1012
+ * Filter the ExactDN arguments added to an image, when the image size is an array of height and width values.
1013
+ *
1014
+ * @param array $exactdn_args ExactDN arguments/parameters.
1015
+ * @param array $args {
1016
+ * Array of image details.
1017
+ *
1018
+ * @type int $width Image width.
1019
+ * @type int $height Image height.
1020
+ * @type string $image_url Image URL.
1021
+ * @type int $attachment_id Attachment ID of the image.
1022
+ * }
1023
+ */
1024
+ $exactdn_args = apply_filters( 'exactdn_image_downsize_array', $exactdn_args, compact( 'width', 'height', 'image_url', 'attachment_id' ) );
1025
+
1026
+ // Generate ExactDN URL.
1027
+ $image = array(
1028
+ $this->generate_url( $image_url, $exactdn_args ),
1029
+ $has_size_meta ? $width : false,
1030
+ $has_size_meta ? $height : false,
1031
+ $intermediate,
1032
+ );
1033
+ }
1034
+ }
1035
+ if ( ! empty( $image[0] ) && is_string( $image[0] ) ) {
1036
+ ewwwio_debug_message( $image[0] );
1037
+ }
1038
+ ewwwio_debug_message( 'end image_downsize' );
1039
+ $elapsed_time = microtime( true ) - $started;
1040
+ ewwwio_debug_message( "parsing image_downsize took $elapsed_time seconds" );
1041
+ $this->elapsed_time += microtime( true ) - $started;
1042
+ return $image;
1043
+ }
1044
+
1045
+ /**
1046
+ * Filters an array of image `srcset` values, replacing each URL with its ExactDN equivalent.
1047
+ *
1048
+ * @param array $sources An array of image urls and widths.
1049
+ * @param array $size_array Array of width and height values in pixels.
1050
+ * @param string $image_src The 'src' of the image.
1051
+ * @param array $image_meta The image metadata as returned by 'wp_get_attachment_metadata()'.
1052
+ * @param int $attachment_id Image attachment ID or 0.
1053
+ * @uses this::validate_image_url, this::generate_url, this::parse_from_filename
1054
+ * @uses this::strip_image_dimensions_maybe, this::get_content_width
1055
+ * @return array An array of ExactDN image urls and widths.
1056
+ */
1057
+ public function filter_srcset_array( $sources = array(), $size_array = array(), $image_src = '', $image_meta = array(), $attachment_id = 0 ) {
1058
+ $started = microtime( true );
1059
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1060
+ // Don't foul up the admin side of things, unless a plugin wants to.
1061
+ if ( is_admin() &&
1062
+ /**
1063
+ * Provide plugins a way of running ExactDN for images in the WordPress Dashboard (wp-admin).
1064
+ *
1065
+ * @param bool false Stop ExactDN from being run on the Dashboard. Default to false, use true to run in wp-admin.
1066
+ * @param array $args {
1067
+ * Array of image details.
1068
+ *
1069
+ * @type string|bool $image Image URL or false.
1070
+ * @type int $attachment_id Attachment ID of the image.
1071
+ * }
1072
+ */
1073
+ false === apply_filters( 'exactdn_admin_allow_image_srcset', false, compact( 'image_src', 'attachment_id' ) )
1074
+ ) {
1075
+ return $sources;
1076
+ }
1077
+ if ( ! is_array( $sources ) ) {
1078
+ return $sources;
1079
+ }
1080
+ $upload_dir = wp_get_upload_dir();
1081
+ $resize_existing = defined( 'EXACTDN_RESIZE_EXISTING' ) && EXACTDN_RESIZE_EXISTING;
1082
+
1083
+ foreach ( $sources as $i => $source ) {
1084
+ if ( ! $this->validate_image_url( $source['url'] ) ) {
1085
+ continue;
1086
+ }
1087
+
1088
+ /** This filter is already documented in class-exactdn.php */
1089
+ if ( apply_filters( 'exactdn_skip_image', false, $source['url'], $source ) ) {
1090
+ continue;
1091
+ }
1092
+
1093
+ $url = $source['url'];
1094
+
1095
+ list( $width, $height ) = $this->parse_dimensions_from_filename( $url );
1096
+ if ( ! $resize_existing && 'w' === $source['descriptor'] && $source['value'] == $width ) {
1097
+ ewwwio_debug_message( "preventing further processing for $url" );
1098
+ $sources[ $i ]['url'] = $this->generate_url( $source['url'] );
1099
+ continue;
1100
+ }
1101
+ ewwwio_debug_message( 'continuing: ' . $width . ' vs. ' . $source['value'] );
1102
+
1103
+ // It's quicker to get the full size with the data we have already, if available.
1104
+ if ( ! empty( $attachment_id ) ) {
1105
+ $url = wp_get_attachment_url( $attachment_id );
1106
+ } else {
1107
+ $url = $this->strip_image_dimensions_maybe( $url );
1108
+ }
1109
+ ewwwio_debug_message( "building srcs from $url" );
1110
+
1111
+ $args = array();
1112
+ if ( 'w' === $source['descriptor'] ) {
1113
+ if ( $height && ( $source['value'] == $width ) ) {
1114
+ $args['resize'] = $width . ',' . $height;
1115
+ } else {
1116
+ $args['w'] = $source['value'];
1117
+ }
1118
+ }
1119
+
1120
+ $args = $this->maybe_smart_crop( $args, $attachment_id, $image_meta );
1121
+
1122
+ $sources[ $i ]['url'] = $this->generate_url( $url, $args );
1123
+ }
1124
+
1125
+ /**
1126
+ * At this point, $sources is the original srcset with ExactDN URLs.
1127
+ * Now, we're going to construct additional sizes based on multiples of the content_width.
1128
+ * TODO: Then we will also insert additional sizes from the ExactDN feedback loop.
1129
+ * This will reduce the gap between the largest defined size and the original image.
1130
+ */
1131
+
1132
+ /**
1133
+ * Filter the multiplier ExactDN uses to create new srcset items.
1134
+ * Return false to short-circuit and bypass auto-generation.
1135
+ *
1136
+ * @param array|bool $multipliers Array of multipliers to use or false to bypass.
1137
+ */
1138
+ $multipliers = apply_filters( 'exactdn_srcset_multipliers', array( .2, .4, .6, .8, 1, 2, 3 ) );
1139
+ $url = trailingslashit( $upload_dir['baseurl'] ) . $image_meta['file'];
1140
+
1141
+ if (
1142
+ /** Short-circuit via exactdn_srcset_multipliers filter. */
1143
+ is_array( $multipliers )
1144
+ /** This filter is already documented in class-exactdn.php */
1145
+ && ! apply_filters( 'exactdn_skip_image', false, $url, null )
1146
+ /** Verify basic meta is intact. */
1147
+ && isset( $image_meta['width'] ) && isset( $image_meta['height'] ) && isset( $image_meta['file'] )
1148
+ /** Verify we have the requested width/height. */
1149
+ && isset( $size_array[0] ) && isset( $size_array[1] )
1150
+ ) {
1151
+
1152
+ $fullwidth = $image_meta['width'];
1153
+ $fullheight = $image_meta['height'];
1154
+ $reqwidth = $size_array[0];
1155
+ $reqheight = $size_array[1];
1156
+ ewwwio_debug_message( "requested w $reqwidth h $reqheight full w $fullwidth full h $fullheight" );
1157
+
1158
+ $constrained_size = wp_constrain_dimensions( $fullwidth, $fullheight, $reqwidth );
1159
+ $expected_size = array( $reqwidth, $reqheight );
1160
+
1161
+ ewwwio_debug_message( $constrained_size[0] );
1162
+ ewwwio_debug_message( $constrained_size[1] );
1163
+ if ( abs( $constrained_size[0] - $expected_size[0] ) <= 1 && abs( $constrained_size[1] - $expected_size[1] ) <= 1 ) {
1164
+ $crop = 'soft';
1165
+ $base = $this->get_content_width() ? $this->get_content_width() : 1900; // Provide a default width if none set by the theme.
1166
+ } else {
1167
+ $crop = 'hard';
1168
+ $base = $reqwidth;
1169
+ }
1170
+ ewwwio_debug_message( "base width: $base" );
1171
+
1172
+ $currentwidths = array_keys( $sources );
1173
+ $newsources = null;
1174
+
1175
+ foreach ( $multipliers as $multiplier ) {
1176
+
1177
+ $newwidth = intval( $base * $multiplier );
1178
+ foreach ( $currentwidths as $currentwidth ) {
1179
+ // If a new width would be within 50 pixels of an existing one or larger than the full size image, skip.
1180
+ if ( abs( $currentwidth - $newwidth ) < 50 || ( $newwidth > $fullwidth ) ) {
1181
+ continue 2; // Back to the foreach ( $multipliers as $multiplier ).
1182
+ }
1183
+ } // foreach ( $currentwidths as $currentwidth ){
1184
+
1185
+ if ( 'soft' == $crop ) {
1186
+ $args = array(
1187
+ 'w' => $newwidth,
1188
+ );
1189
+ } else { // hard crop, e.g. add_image_size( 'example', 200, 200, true ).
1190
+ $args = array(
1191
+ 'zoom' => $multiplier,
1192
+ 'resize' => $reqwidth . ',' . $reqheight,
1193
+ );
1194
+ }
1195
+
1196
+ $args = $this->maybe_smart_crop( $args, $attachment_id, $image_meta );
1197
+
1198
+ $newsources[ $newwidth ] = array(
1199
+ 'url' => $this->generate_url( $url, $args ),
1200
+ 'descriptor' => 'w',
1201
+ 'value' => $newwidth,
1202
+ );
1203
+ } // foreach ( $multipliers as $multiplier )
1204
+ if ( is_array( $newsources ) ) {
1205
+ $sources = array_replace( $sources, $newsources );
1206
+ }
1207
+ } // if ( isset( $image_meta['width'] ) && isset( $image_meta['file'] ) )
1208
+ $elapsed_time = microtime( true ) - $started;
1209
+ ewwwio_debug_message( "parsing srcset took $elapsed_time seconds" );
1210
+ /* ewwwio_debug_message( print_r( $sources, true ) ); */
1211
+ $this->elapsed_time += microtime( true ) - $started;
1212
+ return $sources;
1213
+ }
1214
+
1215
+ /**
1216
+ * Filters an array of image `sizes` values, using $content_width instead of image's full size.
1217
+ *
1218
+ * @param array $sizes An array of media query breakpoints.
1219
+ * @param array $size Width and height of the image.
1220
+ * @uses this::get_content_width
1221
+ * @return array An array of media query breakpoints.
1222
+ */
1223
+ public function filter_sizes( $sizes, $size ) {
1224
+ $started = microtime( true );
1225
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1226
+ if ( ! doing_filter( 'the_content' ) ) {
1227
+ return $sizes;
1228
+ }
1229
+ $content_width = $this->get_content_width();
1230
+ if ( ! $content_width ) {
1231
+ $content_width = 1900;
1232
+ }
1233
+
1234
+ if ( ( is_array( $size ) && $size[0] < $content_width ) ) {
1235
+ return $sizes;
1236
+ }
1237
+
1238
+ $elapsed_time = microtime( true ) - $started;
1239
+ ewwwio_debug_message( "parsing sizes took $elapsed_time seconds" );
1240
+ $this->elapsed_time += microtime( true ) - $started;
1241
+ return sprintf( '(max-width: %1$dpx) 100vw, %1$dpx', $content_width );
1242
+ }
1243
+
1244
+ /**
1245
+ * Check for smart-cropping plugin to adjust cropping parameters.
1246
+ * Currently supports Theia Smart Thumbnails using the theiaSmartThumbnails_position meta.
1247
+ *
1248
+ * @param array $args The arguments that have been generated so far.
1249
+ * @param int $attachment_id The ID number for the current image.
1250
+ * @param array $meta Optional. The attachment (image) metadata. Default false.
1251
+ * @return array The arguments, possibly altered for smart cropping.
1252
+ */
1253
+ function maybe_smart_crop( $args, $attachment_id, $meta = false ) {
1254
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1255
+ if ( ! empty( $args['crop'] ) ) {
1256
+ ewwwio_debug_message( 'already cropped' );
1257
+ return $args;
1258
+ }
1259
+ // Doing something other than a hard crop, or we don't know what the ID is.
1260
+ if ( empty( $args['resize'] ) || empty( $attachment_id ) ) {
1261
+ ewwwio_debug_message( 'not resizing, so no custom crop' );
1262
+ return $args;
1263
+ }
1264
+ // TST is not active.
1265
+ if ( ! defined( 'TST_VERSION' ) ) {
1266
+ ewwwio_debug_message( 'no TST plugin' );
1267
+ return $args;
1268
+ }
1269
+ if ( ! class_exists( 'TstPostOptions' ) || ! defined( 'TstPostOptions::META_POSITION' ) ) {
1270
+ ewwwio_debug_message( 'no TstPostOptions class' );
1271
+ return $args;
1272
+ }
1273
+ if ( ! $meta || ! is_array( $meta ) || empty( $meta['sizes'] ) ) {
1274
+ // $focus_point = get_post_meta( $attachment_id, TstPostOptions::META_POSITION, true );
1275
+ $meta = wp_get_attachment_metadata( $attachment_id );
1276
+ if ( ! is_array( $meta ) || empty( $meta['width'] ) || empty( $meta['height'] ) ) {
1277
+ ewwwio_debug_message( 'unusable meta retrieved' );
1278
+ return $args;
1279
+ }
1280
+ $focus_point = TstPostOptions::get_meta( $attachment_id, $meta['width'], $meta['height'] );
1281
+ } elseif ( ! empty( $meta['tst_thumbnail_version'] ) ) {
1282
+ if ( empty( $meta['width'] ) || empty( $meta['height'] ) ) {
1283
+ ewwwio_debug_message( 'unusable meta passed' );
1284
+ return $args;
1285
+ }
1286
+ $focus_point = TstPostOptions::get_meta( $attachment_id, $meta['width'], $meta['height'] );
1287
+ } else {
1288
+ ewwwio_debug_message( 'unusable meta' );
1289
+ return $args;
1290
+ }
1291
+ if ( empty( $focus_point ) || ! is_array( $focus_point ) ) {
1292
+ ewwwio_debug_message( 'unusable focus point' );
1293
+ return $args;
1294
+ }
1295
+
1296
+ $dimensions = explode( ',', $args['resize'] );
1297
+
1298
+ $new_w = $dimensions[0];
1299
+ $new_h = $dimensions[1];
1300
+ ewwwio_debug_message( "full size dims: w{$meta['width']} h{$meta['height']}" );
1301
+ ewwwio_debug_message( "smart crop dims: w$new_w h$new_h" );
1302
+ if ( ! empty( $args['zoom'] ) ) {
1303
+ $new_w = round( $args['zoom'] * $new_w );
1304
+ $new_h = round( $args['zoom'] * $new_h );
1305
+ ewwwio_debug_message( "zooming: {$args['zoom']} w$new_w h$new_h" );
1306
+ }
1307
+ if ( ! $new_w || ! $new_h ) {
1308
+ ewwwio_debug_message( 'empty dimension, not cropping' );
1309
+ return $args;
1310
+ }
1311
+ $size_ratio = max( $new_w / $meta['width'], $new_h / $meta['height'] );
1312
+ $crop_w = round( $new_w / $size_ratio );
1313
+ $crop_h = round( $new_h / $size_ratio );
1314
+ $s_x = floor( ( $meta['width'] - $crop_w ) * $focus_point[0] );
1315
+ $s_y = floor( ( $meta['height'] - $crop_h ) * $focus_point[1] );
1316
+ ewwwio_debug_message( "doing the math with size_ratio of $size_ratio" );
1317
+
1318
+ $args = array( 'crop' => $s_x . 'px,' . $s_y . 'px,' . $crop_w . 'px,' . $crop_h . 'px' ) + $args;
1319
+ ewwwio_debug_message( $args['crop'] );
1320
+ return $args;
1321
+ }
1322
+
1323
+ /**
1324
+ * Make sure the image domain is on the list of approved domains.
1325
+ *
1326
+ * @param string $domain The hostname to validate.
1327
+ * @return bool True if the hostname is allowed, false otherwise.
1328
+ */
1329
+ public function allow_image_domain( $domain ) {
1330
+ $domain = trim( $domain );
1331
+ foreach ( $this->allowed_domains as $allowed ) {
1332
+ $allowed = trim( $allowed );
1333
+ if ( $domain === $allowed ) {
1334
+ return true;
1335
+ }
1336
+ }
1337
+ return false;
1338
+ }
1339
+
1340
+ /**
1341
+ * Ensure image URL is valid for ExactDN.
1342
+ * Though ExactDN functions address some of the URL issues, we should avoid unnecessary processing if we know early on that the image isn't supported.
1343
+ *
1344
+ * @param string $url The image url to be validated.
1345
+ * @param bool $exactdn_is_valid Optional. Whether an ExactDN URL should be considered valid. Default false.
1346
+ * @uses wp_parse_args
1347
+ * @return bool True if the url is considerd valid, false otherwise.
1348
+ */
1349
+ protected function validate_image_url( $url, $exactdn_is_valid = false ) {
1350
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1351
+ $parsed_url = parse_url( $url );
1352
+ // TODO: add a parameter to allow validation of exactdn urls.
1353
+ if ( ! $parsed_url ) {
1354
+ ewwwio_debug_message( 'could not parse' );
1355
+ return false;
1356
+ }
1357
+
1358
+ // Parse URL and ensure needed keys exist, since the array returned by `parse_url` only includes the URL components it finds.
1359
+ $url_info = wp_parse_args( $parsed_url, array(
1360
+ 'scheme' => null,
1361
+ 'host' => null,
1362
+ 'port' => null,
1363
+ 'path' => null,
1364
+ ) );
1365
+
1366
+ // Bail if scheme isn't http or port is set that isn't port 80.
1367
+ if (
1368
+ ( 'http' != $url_info['scheme'] || ! in_array( $url_info['port'], array( 80, null ) ) ) &&
1369
+ /**
1370
+ * Tells ExactDN to ignore images that are served via HTTPS.
1371
+ *
1372
+ * @param bool $reject_https Should ExactDN ignore images using the HTTPS scheme. Default to false.
1373
+ */
1374
+ apply_filters( 'exactdn_reject_https', false )
1375
+ ) {
1376
+ ewwwio_debug_message( 'rejected https via filter' );
1377
+ return false;
1378
+ }
1379
+
1380
+ // Bail if no host is found.
1381
+ if ( is_null( $url_info['host'] ) ) {
1382
+ ewwwio_debug_message( 'null host' );
1383
+ return false;
1384
+ }
1385
+
1386
+ // Bail if the image already went through ExactDN.
1387
+ if ( ! $exactdn_is_valid && strpos( $url_info['host'], '.exactdn.com' ) ) {
1388
+ ewwwio_debug_message( 'exactdn image' );
1389
+ return false;
1390
+ }
1391
+ if ( ! $exactdn_is_valid && strpos( $url_info['host'], '.exactdn.net' ) ) {
1392
+ ewwwio_debug_message( 'exactdn image' );
1393
+ return false;
1394
+ }
1395
+ if ( ! $exactdn_is_valid && strpos( $url_info['host'], '.exactcdn.com' ) ) {
1396
+ ewwwio_debug_message( 'exactdn image' );
1397
+ return false;
1398
+ }
1399
+ if ( ! $exactdn_is_valid && strpos( $url_info['host'], '.exactcdn.net' ) ) {
1400
+ ewwwio_debug_message( 'exactdn image' );
1401
+ return false;
1402
+ }
1403
+
1404
+ // Bail if the image already went through Photon to avoid conflicts.
1405
+ if ( preg_match( '#^i[\d]{1}.wp.com$#i', $url_info['host'] ) ) {
1406
+ ewwwio_debug_message( 'photon/wp.com image' );
1407
+ return false;
1408
+ }
1409
+
1410
+ // Bail if no path is found.
1411
+ if ( is_null( $url_info['path'] ) ) {
1412
+ ewwwio_debug_message( 'null path' );
1413
+ return false;
1414
+ }
1415
+
1416
+ // Ensure image extension is acceptable.
1417
+ if ( ! in_array( strtolower( pathinfo( $url_info['path'], PATHINFO_EXTENSION ) ), $this->extensions ) ) {
1418
+ ewwwio_debug_message( 'invalid extension' );
1419
+ return false;
1420
+ }
1421
+
1422
+ // Make sure this is an allowed image domain/hostname for ExactDN on this site.
1423
+ if ( ! $this->allow_image_domain( $url_info['host'] ) ) {
1424
+ ewwwio_debug_message( 'invalid host for ExactDN' );
1425
+ return false;
1426
+ }
1427
+
1428
+ // If we got this far, we should have an acceptable image URL,
1429
+ // but let folks filter to decline if they prefer.
1430
+ /**
1431
+ * Overwrite the results of the previous validation steps an image goes through to be considered valid for ExactDN.
1432
+ *
1433
+ * @param bool true Is the image URL valid and can it be used by ExactDN. Default to true.
1434
+ * @param string $url Image URL.
1435
+ * @param array $parsed_url Array of information about the image url.
1436
+ */
1437
+ return apply_filters( 'exactdn_validate_image_url', true, $url, $parsed_url );
1438
+ }
1439
+
1440
+ /**
1441
+ * Checks if the file exists before it passes the file to ExactDN.
1442
+ *
1443
+ * @param string $src The image URL.
1444
+ * @return string The possibly altered URL without dimensions.
1445
+ **/
1446
+ protected function strip_image_dimensions_maybe( $src ) {
1447
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1448
+ $stripped_src = $src;
1449
+
1450
+ // Build URL, first removing WP's resized string so we pass the original image to ExactDN.
1451
+ if ( preg_match( '#(-\d+x\d+)\.(' . implode( '|', $this->extensions ) . '){1}(?:\?.+)?$#i', $src, $src_parts ) ) {
1452
+ $stripped_src = str_replace( $src_parts[1], '', $src );
1453
+ $upload_dir = wp_get_upload_dir();
1454
+
1455
+ // Extracts the file path to the image minus the base url.
1456
+ $file_path = substr( $stripped_src, strlen( $upload_dir['baseurl'] ) );
1457
+
1458
+ if ( file_exists( $upload_dir['basedir'] . $file_path ) ) {
1459
+ $src = $stripped_src;
1460
+ }
1461
+ ewwwio_debug_message( 'stripped dims' );
1462
+ }
1463
+ return $src;
1464
+ }
1465
+
1466
+ /**
1467
+ * Provide an array of available image sizes and corresponding dimensions.
1468
+ * Similar to get_intermediate_image_sizes() except that it includes image sizes' dimensions, not just their names.
1469
+ *
1470
+ * @global $wp_additional_image_sizes
1471
+ * @uses get_option
1472
+ * @return array
1473
+ */
1474
+ protected function image_sizes() {
1475
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1476
+ if ( null == self::$image_sizes ) {
1477
+ global $_wp_additional_image_sizes;
1478
+
1479
+ // Populate an array matching the data structure of $_wp_additional_image_sizes so we have a consistent structure for image sizes.
1480
+ $images = array(
1481
+ 'thumb' => array(
1482
+ 'width' => intval( get_option( 'thumbnail_size_w' ) ),
1483
+ 'height' => intval( get_option( 'thumbnail_size_h' ) ),
1484
+ 'crop' => (bool) get_option( 'thumbnail_crop' ),
1485
+ ),
1486
+ 'medium' => array(
1487
+ 'width' => intval( get_option( 'medium_size_w' ) ),
1488
+ 'height' => intval( get_option( 'medium_size_h' ) ),
1489
+ 'crop' => false,
1490
+ ),
1491
+ 'large' => array(
1492
+ 'width' => intval( get_option( 'large_size_w' ) ),
1493
+ 'height' => intval( get_option( 'large_size_h' ) ),
1494
+ 'crop' => false,
1495
+ ),
1496
+ 'full' => array(
1497
+ 'width' => null,
1498
+ 'height' => null,
1499
+ 'crop' => false,
1500
+ ),
1501
+ );
1502
+
1503
+ // Compatibility mapping as found in wp-includes/media.php.
1504
+ $images['thumbnail'] = $images['thumb'];
1505
+
1506
+ // Update class variable, merging in $_wp_additional_image_sizes if any are set.
1507
+ if ( is_array( $_wp_additional_image_sizes ) && ! empty( $_wp_additional_image_sizes ) ) {
1508
+ self::$image_sizes = array_merge( $images, $_wp_additional_image_sizes );
1509
+ } else {
1510
+ self::$image_sizes = $images;
1511
+ }
1512
+ }
1513
+
1514
+ return is_array( self::$image_sizes ) ? self::$image_sizes : array();
1515
+ }
1516
+
1517
+ /**
1518
+ * Enqueue ExactDN helper script
1519
+ */
1520
+ public function action_wp_enqueue_scripts() {
1521
+ wp_enqueue_script( 'exactdn', plugins_url( 'includes/exactdn.js', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ), array( 'jquery' ), EWWW_IMAGE_OPTIMIZER_VERSION, true );
1522
+ }
1523
+
1524
+ /**
1525
+ * Suppress query args for certain files, typically for placholder images.
1526
+ *
1527
+ * @param array|string $args Array of ExactDN arguments.
1528
+ * @param string $image_url Image URL.
1529
+ * @param string|null $scheme Image scheme. Default to null.
1530
+ * @return array Empty if it matches our search, otherwise just $args untouched.
1531
+ */
1532
+ function exactdn_remove_args( $args, $image_url, $scheme ) {
1533
+ if ( strpos( $image_url, 'revslider/admin/assets/images/dummy.png' ) ) {
1534
+ return array();
1535
+ }
1536
+ if ( strpos( $image_url, 'lazy_placeholder.gif' ) ) {
1537
+ return array();
1538
+ }
1539
+ return $args;
1540
+ }
1541
+
1542
+ /**
1543
+ * Generates an ExactDN URL.
1544
+ *
1545
+ * @param string $image_url URL to the publicly accessible image you want to manipulate.
1546
+ * @param array|string $args An array of arguments, i.e. array( 'w' => '300', 'resize' => array( 123, 456 ) ), or in string form (w=123&h=456).
1547
+ * @param string $scheme Indicates http or https, other schemes are invalid.
1548
+ * @return string The raw final URL. You should run this through esc_url() before displaying it.
1549
+ */
1550
+ function generate_url( $image_url, $args = array(), $scheme = null ) {
1551
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1552
+ $image_url = trim( $image_url );
1553
+
1554
+ if ( is_null( $scheme ) ) {
1555
+ $site_url = get_home_url();
1556
+ $scheme = 'http';
1557
+ if ( strpos( $site_url, 'https://' ) !== false ) {
1558
+ $scheme = 'https';
1559
+ }
1560
+ }
1561
+
1562
+ /**
1563
+ * Disables ExactDN URL processing for local development.
1564
+ *
1565
+ * @param bool false default
1566
+ */
1567
+ if ( true === apply_filters( 'exactdn_development_mode', false ) ) {
1568
+ return $image_url;
1569
+ }
1570
+
1571
+ /**
1572
+ * Allow specific image URls to avoid going through ExactDN.
1573
+ *
1574
+ * @param bool false Should the image be returned as is, without going through ExactDN. Default to false.
1575
+ * @param string $image_url Image URL.
1576
+ * @param array|string $args Array of ExactDN arguments.
1577
+ * @param string|null $scheme Image scheme. Default to null.
1578
+ */
1579
+ if ( true === apply_filters( 'exactdn_skip_for_url', false, $image_url, $args, $scheme ) ) {
1580
+ return $image_url;
1581
+ }
1582
+
1583
+ // TODO: Not differentiated yet, but it will be, so stay tuned!
1584
+ $jpg_quality = apply_filters( 'jpeg_quality', null, 'image_resize' );
1585
+ $webp_quality = apply_filters( 'jpeg_quality', $jpg_quality, 'image/webp' );
1586
+
1587
+ $more_args = array();
1588
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) ) {
1589
+ $more_args['strip'] = 'all';
1590
+ }
1591
+ if ( ewww_image_optimizer_get_option( 'exactdn_lossy' ) ) {
1592
+ $more_args['lossy'] = is_numeric( ewww_image_optimizer_get_option( 'exactdn_lossy' ) ) ? (int) ewww_image_optimizer_get_option( 'exactdn_lossy' ) : 80;
1593
+ }
1594
+ if ( ! is_null( $jpg_quality ) && 82 != $jpg_quality ) {
1595
+ $more_args['quality'] = $jpg_quality;
1596
+ }
1597
+ // Merge given args with the automatic (option-based) args, and also makes sure args is an array if it was previously a string.
1598
+ $args = wp_parse_args( $args, $more_args );
1599
+
1600
+ /**
1601
+ * Filter the original image URL before it goes through ExactDN.
1602
+ *
1603
+ * @param string $image_url Image URL.
1604
+ * @param array|string $args Array of ExactDN arguments.
1605
+ * @param string|null $scheme Image scheme. Default to null.
1606
+ */
1607
+ $image_url = apply_filters( 'exactdn_pre_image_url', $image_url, $args, $scheme );
1608
+
1609
+ /**
1610
+ * Filter the ExactDN image parameters before they are applied to an image.
1611
+ *
1612
+ * @param array|string $args Array of ExactDN arguments.
1613
+ * @param string $image_url Image URL.
1614
+ * @param string|null $scheme Image scheme. Default to null.
1615
+ */
1616
+ $args = apply_filters( 'exactdn_pre_args', $args, $image_url, $scheme );
1617
+
1618
+ if ( empty( $image_url ) ) {
1619
+ return $image_url;
1620
+ }
1621
+
1622
+ $image_url_parts = $this->parse_url( $image_url );
1623
+
1624
+ // Unable to parse.
1625
+ if ( ! is_array( $image_url_parts ) || empty( $image_url_parts['host'] ) || empty( $image_url_parts['path'] ) ) {
1626
+ ewwwio_debug_message( 'src url no good' );
1627
+ return $image_url;
1628
+ }
1629
+
1630
+ if ( is_array( $args ) ) {
1631
+ // Convert values that are arrays into strings.
1632
+ foreach ( $args as $arg => $value ) {
1633
+ if ( is_array( $value ) ) {
1634
+ $args[ $arg ] = implode( ',', $value );
1635
+ }
1636
+ }
1637
+
1638
+ // Encode argument values.
1639
+ $args = rawurlencode_deep( $args );
1640
+ }
1641
+
1642
+ ewwwio_debug_message( $image_url_parts['host'] );
1643
+
1644
+ // Figure out which CDN (sub)domain to use.
1645
+ if ( empty( $this->exactdn_domain ) ) {
1646
+ ewwwio_debug_message( 'no exactdn domain configured' );
1647
+ return $image_url;
1648
+ }
1649
+
1650
+ // You can't run an ExactDN URL through again because query strings are stripped.
1651
+ // So if the image is already an ExactDN URL, append the new arguments to the existing URL.
1652
+ if ( $this->exactdn_domain === $image_url_parts['host'] ) {
1653
+ ewwwio_debug_message( 'url already has exactdn domain' );
1654
+ $exactdn_url = add_query_arg( $args, $image_url );
1655
+ return $this->url_scheme( $exactdn_url, $scheme );
1656
+ }
1657
+
1658
+ // ExactDN doesn't support query strings so we ignore them and look only at the path.
1659
+ // However some source images are served via PHP so check the no-query-string extension.
1660
+ // For future proofing, this is a blacklist of common issues rather than a whitelist.
1661
+ $extension = pathinfo( $image_url_parts['path'], PATHINFO_EXTENSION );
1662
+ if ( empty( $extension ) || in_array( $extension, array( 'php', 'ashx' ) ) ) {
1663
+ ewwwio_debug_message( 'bad extension' );
1664
+ return $image_url;
1665
+ }
1666
+
1667
+ $domain = 'http://' . $this->exactdn_domain . '/';
1668
+ $exactdn_url = $domain . ltrim( $image_url_parts['path'], '/' );
1669
+ ewwwio_debug_message( "bare exactdn url: $exactdn_url" );
1670
+
1671
+ /**
1672
+ * Add query strings to ExactDN URL.
1673
+ * By default, ExactDN doesn't support query strings so we ignore them.
1674
+ * This setting is ExactDN Server dependent.
1675
+ *
1676
+ * @param bool false Should query strings be added to the image URL. Default is false.
1677
+ * @param string $image_url_parts['host'] Image URL's host.
1678
+ */
1679
+ if ( isset( $image_url_parts['query'] ) && apply_filters( 'exactdn_add_query_string_to_domain', false, $image_url_parts['host'] ) ) {
1680
+ $exactdn_url .= '?q=' . rawurlencode( $image_url_parts['query'] );
1681
+ }
1682
+ // This is disabled, as I don't think we really need it.
1683
+ if ( false && ! empty( $image_url_parts['query'] ) && false !== strpos( $image_url_parts['query'], 'theia_smart' ) ) {
1684
+ $args = wp_parse_args( $image_url_parts['query'], $args );
1685
+ }
1686
+
1687
+ if ( $args ) {
1688
+ if ( is_array( $args ) ) {
1689
+ $exactdn_url = add_query_arg( $args, $exactdn_url );
1690
+ } else {
1691
+ // You can pass a query string for complicated requests, although this should have been converted to an array already.
1692
+ $exactdn_url .= '?' . $args;
1693
+ }
1694
+ }
1695
+ ewwwio_debug_message( "exactdn url with args: $exactdn_url" );
1696
+
1697
+ if ( isset( $image_url_parts['scheme'] ) && 'https' == $image_url_parts['scheme'] ) {
1698
+ $exactdn_url = add_query_arg(
1699
+ array(
1700
+ 'ssl' => 1,
1701
+ ),
1702
+ $exactdn_url
1703
+ );
1704
+ $scheme = 'https';
1705
+ }
1706
+
1707
+ return $this->url_scheme( $exactdn_url, $scheme );
1708
+ }
1709
+
1710
+ /**
1711
+ * Prepends schemeless urls or replaces non-http scheme with a valid scheme, defaults to 'http'.
1712
+ *
1713
+ * @param string $url The URL to parse.
1714
+ * @param string|null $scheme Retrieve specific URL component.
1715
+ * @return string Result of parse_url.
1716
+ */
1717
+ function url_scheme( $url, $scheme ) {
1718
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1719
+ if ( ! in_array( $scheme, array( 'http', 'https' ) ) ) {
1720
+ ewwwio_debug_message( 'not a valid scheme' );
1721
+ if ( preg_match( '#^(https?:)?//#', $url ) ) {
1722
+ ewwwio_debug_message( 'url has a valid scheme already' );
1723
+ return $url;
1724
+ }
1725
+ ewwwio_debug_message( 'invalid scheme provided, and url sucks, defaulting to http' );
1726
+ $scheme = 'http';
1727
+ }
1728
+ ewwwio_debug_message( "valid $scheme - $url" );
1729
+ return preg_replace( '#^([a-z:]+)?//#i', "$scheme://", $url );
1730
+ }
1731
+
1732
+ /**
1733
+ * A wrapper for PHP's parse_url, prepending assumed scheme for network path
1734
+ * URLs. PHP versions 5.4.6 and earlier do not correctly parse without scheme.
1735
+ *
1736
+ * @param string $url The URL to parse.
1737
+ * @param integer $component Retrieve specific URL component.
1738
+ * @return mixed Result of parse_url.
1739
+ */
1740
+ function parse_url( $url, $component = -1 ) {
1741
+ if ( 0 === strpos( $url, '//' ) ) {
1742
+ $url = ( is_ssl() ? 'https:' : 'http:' ) . $url;
1743
+ }
1744
+ return parse_url( $url, $component );
1745
+ }
1746
+
1747
+ /**
1748
+ * Adds link to header which enables DNS prefetching for faster speed.
1749
+ */
1750
+ function dns_prefetch() {
1751
+ if ( $this->exactdn_domain ) {
1752
+ echo "\r\n";
1753
+ printf( "<link rel='dns-prefetch' href='%s'>\r\n", '//' . esc_attr( $this->exactdn_domain ) );
1754
+ }
1755
+ }
1756
+ }
1757
+
1758
+ global $exactdn;
1759
+ $exactdn = new ExactDN();
common.php CHANGED
@@ -10,9 +10,8 @@
10
  * @package EWWW_Image_Optimizer
11
  */
12
 
13
- // TODO: use <picture> element to serve webp.
14
- // TODO: see if we can offer a rebuild option, to fill in missing thumbs.
15
- // TODO: so, if lazy loading support stinks, can we roll our own? that's an image "optimization", right?...
16
  // TODO: prevent bad ajax errors from firing when we click the toggle on the Optimization Log, and the plugin status from doing 403s...
17
  // TODO: use a transient to do health checks on the schedule optimizer.
18
  // TODO: add a column to track compression level used for each image, and later implement a way to (re)compress at a specific compression level.
@@ -20,19 +19,23 @@
20
  // 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.
21
  // TODO: implement a search for the bulk table, or maybe we should just move it to it's own page?
22
  // TODO: port bulk changes to NextGEN and FlaGallery.
23
- // TODO: make a bulk restore function.
24
  // TODO: Add a custom async function for parallel mode to store image as pending and use the row ID instead of relative path.
25
  // TODO: write some tests for update_table and check_table, find_already_opt, and remove_dups.
26
  // TODO: write some conversion tests.
27
  // TODO: do a bottom paginator for the show optimized images table.
28
  // TODO: check this patch, to see if the use of 'full' causes any issues: https://core.trac.wordpress.org/ticket/37840 .
29
- // TODO: perhaps have an optional footer thingy that says how many images have been optimized.
30
  // TODO: integrate AGR, since it's "abandoned", but possibly using gifsicle for better GIFs.
 
 
 
 
 
 
31
  if ( ! defined( 'ABSPATH' ) ) {
32
  exit;
33
  }
34
 
35
- define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '361.0' );
36
 
37
  // Initialize a couple globals.
38
  $ewww_debug = '';
@@ -124,6 +127,8 @@ add_action( 'plugins_loaded', 'ewww_image_optimizer_preinit' );
124
  add_action( 'init', 'ewww_image_optimizer_gallery_support' );
125
  // Initializes the plugin for admin interactions, like saving network settings and scheduling cron jobs.
126
  add_action( 'admin_init', 'ewww_image_optimizer_admin_init' );
 
 
127
  // Legacy (non-AJAX) action hook for manually optimizing an image.
128
  add_action( 'admin_action_ewww_image_optimizer_manual_optimize', 'ewww_image_optimizer_manual' );
129
  // Legacy (non-AJAX) action hook for manually restoring a converted image.
@@ -154,6 +159,8 @@ add_action( 'ewww_image_optimizer_auto', 'ewww_image_optimizer_auto' );
154
  add_action( 'wr2x_retina_file_added', 'ewww_image_optimizer_retina', 20, 2 );
155
  // AJAX action hook for inserting WebP rewrite rules into .htaccess.
156
  add_action( 'wp_ajax_ewww_webp_rewrite', 'ewww_image_optimizer_webp_rewrite' );
 
 
157
  // AJAX action hook for manually optimizing/converting an image.
158
  add_action( 'wp_ajax_ewww_manual_optimize', 'ewww_image_optimizer_manual' );
159
  // AJAX action hook for manually restoring a converted image.
@@ -177,10 +184,17 @@ register_uninstall_hook( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE, 'ewww_image_optimizer
177
  // add_action( 'shutdown', 'ewwwio_memory_output' );.
178
  // Makes sure we flush the debug info to the log on shutdown.
179
  add_action( 'shutdown', 'ewww_image_optimizer_debug_log' );
 
 
 
 
 
 
 
180
  // If Alt WebP Rewriting is enabled.
181
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) ) {
182
  // Start an output buffer before any output starts.
183
- add_action( 'template_redirect', 'ewww_image_optimizer_buffer_start' );
184
  if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
185
  // Load the non-minified, non-inline version of the webp rewrite script.
186
  add_action( 'wp_enqueue_scripts', 'ewww_image_optimizer_webp_debug_script' );
@@ -224,7 +238,9 @@ function ewww_image_optimizer_get_plugin_version( $plugin_file ) {
224
  $default_headers = array(
225
  'Version' => 'Version',
226
  );
 
227
  $plugin_data = get_file_data( $plugin_file, $default_headers, 'plugin' );
 
228
  return $plugin_data;
229
  }
230
 
@@ -245,10 +261,10 @@ function ewww_image_optimizer_ce_webp_enabled() {
245
  }
246
 
247
  /**
248
- * Starts an output buffer and registers the callback function to do WebP replacement. functions to capture all page output, replace image urls with webp derivatives, and add webp fallback
249
  */
250
- function ewww_image_optimizer_buffer_start() {
251
- ob_start( 'ewww_image_optimizer_filter_page_output' );
252
  }
253
 
254
  /**
@@ -290,6 +306,7 @@ function ewww_image_optimizer_webp_attr_copy( $image, &$nscript, $prefix = 'data
290
  'title',
291
  'translate',
292
  'sizes',
 
293
  'data-lazy-type',
294
  'data-attachment-id',
295
  'data-permalink',
@@ -298,6 +315,16 @@ function ewww_image_optimizer_webp_attr_copy( $image, &$nscript, $prefix = 'data
298
  'data-image-meta',
299
  'data-image-title',
300
  'data-image-description',
 
 
 
 
 
 
 
 
 
 
301
  );
302
  foreach ( $attributes as $attribute ) {
303
  if ( $image->getAttribute( $attribute ) ) {
@@ -316,7 +343,7 @@ function ewww_image_optimizer_webp_attr_copy( $image, &$nscript, $prefix = 'data
316
  */
317
  function ewww_image_optimizer_webp_srcset_replace( $srcset, $home_url, $valid_path ) {
318
  $srcset_urls = explode( ' ', $srcset );
319
- $found_webp = false;
320
  if ( ewww_image_optimizer_iterable( $srcset_urls ) ) {
321
  ewwwio_debug_message( 'found srcset urls' );
322
  foreach ( $srcset_urls as $srcurl ) {
@@ -326,7 +353,7 @@ function ewww_image_optimizer_webp_srcset_replace( $srcset, $home_url, $valid_pa
326
  $srcfilepath = ABSPATH . str_replace( $home_url, '', $srcurl );
327
  ewwwio_debug_message( "looking for srcurl on disk: $srcfilepath" );
328
  if ( $valid_path || is_file( $srcfilepath . '.webp' ) ) {
329
- $srcset = preg_replace( "|$srcurl|", $srcurl . '.webp', $srcset );
330
  $found_webp = true;
331
  ewwwio_debug_message( "replacing $srcurl in $srcset" );
332
  }
@@ -355,6 +382,7 @@ function ewww_image_optimizer_webp_jetpack_replace( $image, &$nscript, $home_url
355
  $nscript->setAttribute( 'data-webp-orig-file', $image->getAttribute( 'data-orig-file' ) . '.webp' );
356
  ewwwio_debug_message( "replacing $origfilepath in data-orig-file" );
357
  }
 
358
  }
359
  if ( $image->getAttribute( 'data-medium-file' ) ) {
360
  $mediumfilepath = ABSPATH . str_replace( $home_url, '', $image->getAttribute( 'data-medium-file' ) );
@@ -363,6 +391,7 @@ function ewww_image_optimizer_webp_jetpack_replace( $image, &$nscript, $home_url
363
  $nscript->setAttribute( 'data-webp-medium-file', $image->getAttribute( 'data-medium-file' ) . '.webp' );
364
  ewwwio_debug_message( "replacing $mediumfilepath in data-medium-file" );
365
  }
 
366
  }
367
  if ( $image->getAttribute( 'data-large-file' ) ) {
368
  $largefilepath = ABSPATH . str_replace( $home_url, '', $image->getAttribute( 'data-large-file' ) );
@@ -371,6 +400,36 @@ function ewww_image_optimizer_webp_jetpack_replace( $image, &$nscript, $home_url
371
  $nscript->setAttribute( 'data-webp-large-file', $image->getAttribute( 'data-large-file' ) . '.webp' );
372
  ewwwio_debug_message( "replacing $largefilepath in data-large-file" );
373
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
374
  }
375
  }
376
 
@@ -387,11 +446,12 @@ function ewww_image_optimizer_filter_amp_webp( $buffer ) {
387
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
388
  // Modify buffer here, and then return the updated code.
389
  if ( class_exists( 'DOMDocument' ) ) {
390
- $expanded_head = false;
391
  $html = new DOMDocument;
 
392
  $libxml_previous_error_reporting = libxml_use_internal_errors( true );
 
393
  $html->formatOutput = false;
394
- $html->encoding = 'utf-8';
395
  if ( defined( 'LIBXML_VERSION' ) && LIBXML_VERSION < 20800 ) {
396
  ewwwio_debug_message( 'libxml version too old for amp: ' . LIBXML_VERSION );
397
  return $buffer;
@@ -403,13 +463,13 @@ function ewww_image_optimizer_filter_amp_webp( $buffer ) {
403
  $html->loadHTML( $buffer );
404
  ewwwio_debug_message( 'parsing AMP as html' );
405
  $html->encoding = 'utf-8';
406
- $home_url = get_site_url();
407
- $webp_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' );
408
  if ( ! is_array( $webp_paths ) ) {
409
  $webp_paths = array();
410
  }
411
  $home_relative_url = preg_replace( '/https?:/', '', $home_url );
412
- $images = $html->getElementsByTagName( 'amp-img' );
413
  if ( ewww_image_optimizer_iterable( $images ) ) {
414
  foreach ( $images as $image ) {
415
  if ( 'amp-img' == $image->parentNode->tagName ) {
@@ -417,7 +477,7 @@ function ewww_image_optimizer_filter_amp_webp( $buffer ) {
417
  }
418
  $srcset = '';
419
  ewwwio_debug_message( 'parsing an AMP image' );
420
- $file = $image->getAttribute( 'src' );
421
  $valid_path = false;
422
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
423
  // Check for CDN paths within the img src attribute.
@@ -438,7 +498,7 @@ function ewww_image_optimizer_filter_amp_webp( $buffer ) {
438
  $parent_image = $image->cloneNode();
439
  $parent_image->setAttribute( 'src', $file . '.webp' );
440
  if ( $image->getAttribute( 'srcset' ) ) {
441
- $srcset = $image->getAttribute( 'srcset' );
442
  $srcset_webp = ewww_image_optimizer_webp_srcset_replace( $srcset, $home_url, $valid_path );
443
  if ( $srcset_webp ) {
444
  $parent_image->setAttribute( 'srcset', $srcset_webp );
@@ -483,7 +543,7 @@ function ewww_image_optimizer_filter_amp_webp( $buffer ) {
483
  * @param string $buffer The full HTML page generated since the output buffer was started.
484
  * @return string The altered buffer containing the full page with WebP images inserted.
485
  */
486
- function ewww_image_optimizer_filter_page_output( $buffer ) {
487
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
488
  // If this is an admin page, don't filter it.
489
  if ( ( empty( $buffer ) || is_admin() ) ) {
@@ -521,10 +581,13 @@ function ewww_image_optimizer_filter_page_output( $buffer ) {
521
  ewwwio_debug_message( 'AMP page processing' );
522
  return $buffer;
523
  }
 
524
  $html = new DOMDocument;
 
525
  $libxml_previous_error_reporting = libxml_use_internal_errors( true );
 
526
  $html->formatOutput = false;
527
- $html->encoding = 'utf-8';
528
  if ( defined( 'LIBXML_VERSION' ) && LIBXML_VERSION < 20800 && ewww_image_optimizer_function_exists( 'mb_convert_encoding' ) ) {
529
  ewwwio_debug_message( 'libxml version: ' . LIBXML_VERSION );
530
  // Converts the buffer from utf-8 to html-entities.
@@ -536,29 +599,39 @@ function ewww_image_optimizer_filter_page_output( $buffer ) {
536
  }
537
  if ( preg_match( '/<.DOCTYPE.+xhtml/', $buffer ) ) {
538
  $html->recover = true;
539
- $xhtml_parse = $html->loadXML( $buffer );
540
  ewwwio_debug_message( 'parsing as xhtml' );
541
  } elseif ( empty( $xhtml_parse ) ) {
542
  $html->loadHTML( $buffer );
543
  ewwwio_debug_message( 'parsing as html' );
544
  }
545
  $html->encoding = 'utf-8';
546
- $home_url = get_site_url();
 
 
 
 
 
 
 
 
 
 
547
  $webp_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' );
548
  if ( ! is_array( $webp_paths ) ) {
549
  $webp_paths = array();
550
  }
551
  $home_relative_url = preg_replace( '/https?:/', '', $home_url );
552
- $images = $html->getElementsByTagName( 'img' );
553
  if ( ewww_image_optimizer_iterable( $images ) ) {
554
  foreach ( $images as $image ) {
555
  if ( 'noscript' == $image->parentNode->tagName ) {
556
  continue;
557
  }
558
- $srcset = '';
 
559
  ewwwio_debug_message( 'parsing an image' );
560
  $file = $image->getAttribute( 'src' );
561
- $valid_path = false;
562
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
563
  // Check for CDN paths within the img src attribute.
564
  foreach ( $webp_paths as $webp_path ) {
@@ -579,7 +652,7 @@ function ewww_image_optimizer_filter_page_output( $buffer ) {
579
  $nscript->setAttribute( 'data-img', $file );
580
  $nscript->setAttribute( 'data-webp', $file . '.webp' );
581
  if ( $image->getAttribute( 'srcset' ) ) {
582
- $srcset = $image->getAttribute( 'srcset' );
583
  $srcset_webp = ewww_image_optimizer_webp_srcset_replace( $srcset, $home_url, $valid_path );
584
  if ( $srcset_webp ) {
585
  $nscript->setAttribute( 'data-srcset-webp', $srcset_webp );
@@ -589,6 +662,9 @@ function ewww_image_optimizer_filter_page_output( $buffer ) {
589
  if ( $image->getAttribute( 'data-orig-file' ) && $image->getAttribute( 'data-medium-file' ) && $image->getAttribute( 'data-large-file' ) ) {
590
  ewww_image_optimizer_webp_jetpack_replace( $image, $nscript, $home_url, $valid_path );
591
  }
 
 
 
592
  ewww_image_optimizer_webp_attr_copy( $image, $nscript );
593
  $nscript->setAttribute( 'class', 'ewww_webp' );
594
  $image->parentNode->replaceChild( $nscript, $image );
@@ -596,7 +672,7 @@ function ewww_image_optimizer_filter_page_output( $buffer ) {
596
  }
597
  // Look for NextGEN attributes that need to be altered.
598
  if ( empty( $file ) && $image->getAttribute( 'data-src' ) && $image->getAttribute( 'data-thumbnail' ) ) {
599
- $file = $image->getAttribute( 'data-src' );
600
  $thumb = $image->getAttribute( 'data-thumbnail' );
601
  ewwwio_debug_message( "checking webp for ngg data-src: $file" );
602
  $filepath = ABSPATH . str_replace( $home_url, '', $file );
@@ -644,7 +720,7 @@ function ewww_image_optimizer_filter_page_output( $buffer ) {
644
  // Hueman theme lazy-loads.
645
  if ( false && ! empty( $file ) && strpos( $file, 'image/gif;base64,R0lGOD' ) && $image->getAttribute( 'data-src' ) && $image->getAttribute( 'data-srcset' ) ) {
646
  $dummy = $file;
647
- $file = $image->getAttribute( 'data-src' );
648
  ewwwio_debug_message( "checking webp for hueman data-src: $file" );
649
  $filepath = ABSPATH . str_replace( $home_url, '', $file );
650
  if ( ! $valid_path && ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
@@ -663,7 +739,7 @@ function ewww_image_optimizer_filter_page_output( $buffer ) {
663
  $nscript->setAttribute( 'data-webp-src', $file . '.webp' );
664
  $image->setAttribute( 'src', $file );
665
  if ( $image->getAttribute( 'data-srcset' ) ) {
666
- $srcset = $image->getAttribute( 'data-srcset' );
667
  $srcset_webp = ewww_image_optimizer_webp_srcset_replace( $srcset, $home_url, $valid_path );
668
  if ( $srcset_webp ) {
669
  $nscript->setAttribute( 'data-srcset-webp', $srcset_webp );
@@ -678,7 +754,7 @@ function ewww_image_optimizer_filter_page_output( $buffer ) {
678
  }
679
  // Lazy Load plugin (and hopefully Cherry variant) and BJ Lazy Load.
680
  if ( false && ! empty( $file ) && ( strpos( $file, 'image/gif;base64,R0lGOD' ) || strpos( $file, 'lazy-load/images/1x1' ) ) && $image->getAttribute( 'data-lazy-src' ) && ! empty( $image->nextSibling ) && 'noscript' == $image->nextSibling->nodeName ) {
681
- $dummy = $file;
682
  $nimage = $html->createElement( 'img' );
683
  $nimage->setAttribute( 'src', $dummy );
684
  $file = $image->getAttribute( 'data-lazy-src' );
@@ -697,7 +773,7 @@ function ewww_image_optimizer_filter_page_output( $buffer ) {
697
  $nimage->setAttribute( 'data-lazy-img-src', $file );
698
  $nimage->setAttribute( 'data-lazy-webp-src', $file . '.webp' );
699
  if ( $image->getAttribute( 'srcset' ) ) {
700
- $srcset = $image->getAttribute( 'srcset' );
701
  $srcset_webp = ewww_image_optimizer_webp_srcset_replace( $srcset, $home_url, $valid_path );
702
  if ( $srcset_webp ) {
703
  $nimage->setAttribute( 'data-srcset-webp', $srcset_webp );
@@ -705,7 +781,7 @@ function ewww_image_optimizer_filter_page_output( $buffer ) {
705
  $nimage->setAttribute( 'data-srcset', $srcset );
706
  }
707
  if ( $image->getAttribute( 'data-lazy-srcset' ) ) {
708
- $srcset = $image->getAttribute( 'data-lazy-srcset' );
709
  $srcset_webp = ewww_image_optimizer_webp_srcset_replace( $srcset, $home_url, $valid_path );
710
  if ( $srcset_webp ) {
711
  $nimage->setAttribute( 'data-lazy-srcset-webp', $srcset_webp );
@@ -743,8 +819,8 @@ function ewww_image_optimizer_filter_page_output( $buffer ) {
743
  foreach ( $links as $link ) {
744
  ewwwio_debug_message( 'parsing a link' );
745
  if ( $link->getAttribute( 'data-src' ) && $link->getAttribute( 'data-thumbnail' ) ) {
746
- $file = $link->getAttribute( 'data-src' );
747
- $thumb = $link->getAttribute( 'data-thumbnail' );
748
  $valid_path = false;
749
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
750
  // Check the image for configured CDN paths.
@@ -775,7 +851,7 @@ function ewww_image_optimizer_filter_page_output( $buffer ) {
775
  foreach ( $listitems as $listitem ) {
776
  ewwwio_debug_message( 'parsing a listitem' );
777
  if ( $listitem->getAttribute( 'data-title' ) === 'Slide' && ( $listitem->getAttribute( 'data-lazyload' ) || $listitem->getAttribute( 'data-thumb' ) ) ) {
778
- $thumb = $listitem->getAttribute( 'data-thumb' );
779
  $valid_path = false;
780
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
781
  // Check the image for configured CDN paths.
@@ -811,13 +887,38 @@ function ewww_image_optimizer_filter_page_output( $buffer ) {
811
  }
812
  } // End foreach().
813
  } // End if().
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
814
  // Video elements, looking for poster attributes that are images.
815
  $videos = $html->getElementsByTagName( 'video' );
816
  if ( ewww_image_optimizer_iterable( $videos ) ) {
817
  foreach ( $videos as $video ) {
818
  ewwwio_debug_message( 'parsing a video element' );
819
  if ( $link->getAttribute( 'poster' ) ) {
820
- $file = $link->getAttribute( 'poster' );
821
  $valid_path = false;
822
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
823
  // Check the image for configured CDN paths.
@@ -1095,11 +1196,10 @@ function ewww_image_optimizer_admin_init() {
1095
  require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
1096
  }
1097
  if ( is_multisite() && is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) ) {
 
1098
  // Set the common network settings if they have been POSTed.
1099
- if ( isset( $_POST['ewww_image_optimizer_jpg_level'] ) && current_user_can( 'manage_network_options' ) && ! get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'ewww_image_optimizer_options-options' ) ) {
1100
- if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
1101
- ewwwio_debug_message( print_r( $_POST, true ) );
1102
- }
1103
  $_POST['ewww_image_optimizer_cloud_key'] = empty( $_POST['ewww_image_optimizer_cloud_key'] ) ? '' : $_POST['ewww_image_optimizer_cloud_key'];
1104
  update_site_option( 'ewww_image_optimizer_cloud_key', ewww_image_optimizer_cloud_key_sanitize( $_POST['ewww_image_optimizer_cloud_key'] ) );
1105
  $_POST['ewww_image_optimizer_debug'] = ( empty( $_POST['ewww_image_optimizer_debug'] ) ? false : true );
@@ -1140,6 +1240,8 @@ function ewww_image_optimizer_admin_init() {
1140
  update_site_option( 'ewww_image_optimizer_exclude_paths', ewww_image_optimizer_exclude_paths_sanitize( $_POST['ewww_image_optimizer_exclude_paths'] ) );
1141
  $_POST['ewww_image_optimizer_enable_cloudinary'] = ( empty( $_POST['ewww_image_optimizer_enable_cloudinary'] ) ? false : true );
1142
  update_site_option( 'ewww_image_optimizer_enable_cloudinary', $_POST['ewww_image_optimizer_enable_cloudinary'] );
 
 
1143
  $_POST['ewww_image_optimizer_maxmediawidth'] = empty( $_POST['ewww_image_optimizer_maxmediawidth'] ) ? 0 : $_POST['ewww_image_optimizer_maxmediawidth'];
1144
  update_site_option( 'ewww_image_optimizer_maxmediawidth', (int) $_POST['ewww_image_optimizer_maxmediawidth'] );
1145
  $_POST['ewww_image_optimizer_maxmediaheight'] = empty( $_POST['ewww_image_optimizer_maxmediaheight'] ) ? 0 : $_POST['ewww_image_optimizer_maxmediaheight'];
@@ -1171,6 +1273,7 @@ function ewww_image_optimizer_admin_init() {
1171
  update_site_option( 'ewww_image_optimizer_allow_tracking', $_POST['ewww_image_optimizer_allow_tracking'] );
1172
  add_action( 'network_admin_notices', 'ewww_image_optimizer_network_settings_saved' );
1173
  } elseif ( isset( $_POST['ewww_image_optimizer_allow_multisite_override_active'] ) && current_user_can( 'manage_network_options' ) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'ewww_image_optimizer_options-options' ) ) {
 
1174
  $_POST['ewww_image_optimizer_allow_multisite_override'] = empty( $_POST['ewww_image_optimizer_allow_multisite_override'] ) ? false : true;
1175
  update_site_option( 'ewww_image_optimizer_allow_multisite_override', $_POST['ewww_image_optimizer_allow_multisite_override'] );
1176
  global $ewwwio_tracking;
@@ -1210,17 +1313,18 @@ function ewww_image_optimizer_admin_init() {
1210
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_include_media_paths', 'boolval' );
1211
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_aux_paths', 'ewww_image_optimizer_aux_paths_sanitize' );
1212
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_exclude_paths', 'ewww_image_optimizer_exclude_paths_sanitize' );
 
 
 
 
 
1213
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxmediawidth', 'intval' );
1214
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxmediaheight', 'intval' );
1215
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxotherwidth', 'intval' );
1216
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxotherheight', 'intval' );
1217
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_resize_existing', 'boolval' );
1218
- register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_resize_detection', 'boolval' );
1219
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_disable_resizes', 'ewww_image_optimizer_disable_resizes_sanitize' );
1220
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_disable_resizes_opt', 'ewww_image_optimizer_disable_resizes_sanitize' );
1221
- global $ewwwio_tracking;
1222
- register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_allow_tracking', array( $ewwwio_tracking, 'check_for_settings_optin' ) );
1223
- register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_enable_help', 'boolval' );
1224
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_disable_convert_links', 'boolval' );
1225
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_delete_originals', 'boolval' );
1226
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_jpg_to_png', 'boolval' );
@@ -1250,6 +1354,16 @@ function ewww_image_optimizer_admin_init() {
1250
  // Alert user if multiple re-optimizations detected.
1251
  add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_reoptimization' );
1252
  add_action( 'admin_notices', 'ewww_image_optimizer_notice_reoptimization' );
 
 
 
 
 
 
 
 
 
 
1253
  ewww_image_optimizer_ajax_compat_check();
1254
  ewwwio_memory( __FUNCTION__ );
1255
  }
@@ -1299,22 +1413,29 @@ function ewww_image_optimizer_ajax_compat_check() {
1299
  if ( ! wp_doing_ajax() ) {
1300
  return;
1301
  }
1302
- // Check for (Force) Regenerate Thumbnails action (includes MLP regnerate).
 
1303
  if ( ! empty( $_REQUEST['action'] ) ) {
1304
  if ( 'regeneratethumbnail' == $_REQUEST['action'] ||
1305
  'meauh_save_image' == $_REQUEST['action'] ||
1306
  'hotspot_save' == $_REQUEST['action']
1307
  ) {
 
1308
  ewww_image_optimizer_image_sizes( false );
 
1309
  }
1310
  }
1311
  // Check for other MLP actions, including multi-regen.
1312
  if ( ! empty( $_REQUEST['action'] ) && class_exists( 'MaxGalleriaMediaLib' ) && ( 'regen_mlp_thumbnails' == $_REQUEST['action'] || 'move_media' == $_REQUEST['action'] || 'copy_media' == $_REQUEST['action'] || 'maxgalleria_rename_image' == $_REQUEST['action'] ) ) {
 
1313
  ewww_image_optimizer_image_sizes( false );
 
1314
  }
1315
  // Check for MLP upload.
1316
  if ( ! empty( $_REQUEST['action'] ) && class_exists( 'MaxGalleriaMediaLib' ) && ! empty( $_REQUEST['nonce'] ) && 'upload_attachment' == $_REQUEST['action'] ) {
 
1317
  ewww_image_optimizer_image_sizes( false );
 
1318
  }
1319
  }
1320
 
@@ -1333,6 +1454,20 @@ if ( ! function_exists( 'wp_doing_ajax' ) ) {
1333
  }
1334
  }
1335
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1336
  /**
1337
  * Disables all the local tools by setting their constants to false.
1338
  */
@@ -1353,8 +1488,8 @@ function ewww_image_optimizer_disable_tools() {
1353
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_PNGQUANT' ) ) {
1354
  define( 'EWWW_IMAGE_OPTIMIZER_PNGQUANT', false );
1355
  }
1356
- if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_WEBP' ) ) {
1357
- define( 'EWWW_IMAGE_OPTIMIZER_WEBP', false );
1358
  }
1359
  ewwwio_memory( __FUNCTION__ );
1360
  }
@@ -1435,7 +1570,7 @@ function ewww_image_optimizer_install_table() {
1435
  if ( strpos( $column_collate, 'utf8' ) === false ) {
1436
  ewwwio_debug_message( 'converting path column to utf8' );
1437
  $wpdb->query( "ALTER TABLE $wpdb->ewwwio_images CHANGE path path BLOB" );
1438
- if ( $wpdb->has_cap( 'utf8mb4_520' && strpos( $db_collation, 'utf8mb4' ) ) ) {
1439
  ewwwio_debug_message( 'using mb4 version 5.20' );
1440
  $wpdb->query( "ALTER TABLE $wpdb->ewwwio_images DROP INDEX path_image_size" );
1441
  $wpdb->query( "ALTER TABLE $wpdb->ewwwio_images CONVERT TO CHARACTER SET utf8mb4, CHANGE path path TEXT" );
@@ -1620,6 +1755,14 @@ function ewww_image_optimizer_network_settings_saved() {
1620
  echo "<div id='ewww-image-optimizer-settings-saved' class='updated fade'><p><strong>" . esc_html__( 'Settings saved', 'ewww-image-optimizer' ) . '.</strong></p></div>';
1621
  }
1622
 
 
 
 
 
 
 
 
 
1623
  /**
1624
  * Alert the user when 5 images have been re-optimized more than 10 times.
1625
  *
@@ -1647,7 +1790,7 @@ function ewww_image_optimizer_notice_reoptimization() {
1647
  // Do a check for 10+ optimizations on 5+ images.
1648
  if ( ! empty( $reoptimized ) && $reoptimized > 5 ) {
1649
  $debugging_page = admin_url( 'upload.php?page=ewww-image-optimizer-dynamic-debug' );
1650
- $reset_page = wp_nonce_url( $_SERVER['REQUEST_URI'], 'reset_reoptimization_counters', 'ewww_reset_reopt_nonce' );
1651
  // Display an alert, and let the user reset the warning if they wish.
1652
  echo "<div id='ewww-image-optimizer-warning-reoptimizations' class='error'><p>" .
1653
  sprintf(
@@ -1727,6 +1870,14 @@ function ewww_image_optimizer_restore_editor_hooks( $metadata = false ) {
1727
  remove_filter( 'wp_generate_attachment_metadata', 'wr2x_wp_generate_attachment_metadata' );
1728
  add_filter( 'wp_generate_attachment_metadata', 'ewww_image_optimizer_retina_wrapper' );
1729
  }
 
 
 
 
 
 
 
 
1730
  return $metadata;
1731
  }
1732
 
@@ -1777,7 +1928,14 @@ function ewww_image_optimizer_pte_check( $data ) {
1777
  */
1778
  function ewww_image_optimizer_retina_wrapper( $meta ) {
1779
  remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
1780
- $meta = wr2x_wp_generate_attachment_metadata( $meta );
 
 
 
 
 
 
 
1781
  add_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
1782
  return $meta;
1783
  }
@@ -1791,10 +1949,10 @@ function ewww_image_optimizer_retina_wrapper( $meta ) {
1791
  function ewww_image_optimizer_image_sizes_advanced( $sizes ) {
1792
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1793
  $disabled_sizes = get_option( 'ewww_image_optimizer_disable_resizes' );
1794
- $flipped = false;
1795
  if ( ! empty( $disabled_sizes ) ) {
1796
  if ( ! empty( $sizes[0] ) ) {
1797
- $sizes = array_flip( $sizes );
1798
  $flipped = true;
1799
  }
1800
  if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
@@ -1824,7 +1982,7 @@ function ewww_image_optimizer_image_sizes_advanced( $sizes ) {
1824
  function ewww_image_optimizer_fallback_sizes( $sizes ) {
1825
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1826
  $disabled_sizes = get_option( 'ewww_image_optimizer_disable_resizes' );
1827
- $flipped = false;
1828
  if ( ! empty( $disabled_sizes ) ) {
1829
  if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
1830
  ewwwio_debug_message( print_r( $sizes, true ) );
@@ -1909,22 +2067,22 @@ function ewww_image_optimizer_handle_upload( $params ) {
1909
  function ewww_image_optimizer_w3tc_update_files( $files ) {
1910
  global $ewww_attachment;
1911
  list( $file, $upload_path ) = ewww_image_optimizer_attachment_path( $ewww_attachment['meta'], $ewww_attachment['id'] );
1912
- $file_info = array();
1913
  if ( function_exists( 'w3_upload_info' ) ) {
1914
  $upload_info = w3_upload_info();
1915
  } else {
1916
  $upload_info = ewww_image_optimizer_upload_info();
1917
  }
 
1918
  if ( $upload_info ) {
1919
- $remote_file = ltrim( $upload_info['baseurlpath'] . $ewww_attachment['meta']['file'], '/' );
1920
- $home_url = get_site_url();
1921
  $original_url = $home_url . $file;
1922
- $file_info[] = array(
1923
- 'local_path' => $file,
1924
- 'remote_path' => $remote_file,
1925
  'original_url' => $original_url,
1926
  );
1927
- $files = array_merge( $files, $file_info );
1928
  }
1929
  return $files;
1930
  }
@@ -1994,7 +2152,7 @@ function ewww_image_optimizer_auto() {
1994
  $i = 0;
1995
  while ( $i < $count &&
1996
  $attachment = $ewwwdb->get_row( "SELECT id,path FROM $ewwwdb->ewwwio_images WHERE pending=1 LIMIT 1", ARRAY_A )
1997
- ) {
1998
  // If the nonce has changed since we started, bail out, since that means another aux scan/optimize is running.
1999
  // Do a direct query using $wpdb, because get_option() is cached.
2000
  $current_nonce = $wpdb->get_var( "SELECT option_value FROM $wpdb->options WHERE option_name = 'ewww_image_optimizer_aux_resume'" );
@@ -2050,7 +2208,9 @@ function ewww_image_optimizer_network_deactivate( $network_wide ) {
2050
  * Removes rules from .htaccess file added by EWWW for WebP rewriting.
2051
  */
2052
  function ewww_image_optimizer_uninstall() {
2053
- insert_with_markers( ewww_image_optimizer_htaccess_path(), 'EWWWIO', '' );
 
 
2054
  }
2055
 
2056
  /**
@@ -2062,14 +2222,14 @@ function ewww_image_optimizer_network_admin_menu() {
2062
  require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
2063
  }
2064
  if ( is_multisite() && is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) ) {
2065
- // Add options page to the settings menu.
2066
  $permissions = apply_filters( 'ewww_image_optimizer_superadmin_permissions', '' );
 
2067
  $ewww_network_options_page = add_submenu_page(
2068
- 'settings.php', // Slug of parent
2069
- 'EWWW Image Optimizer', // Page Title
2070
- 'EWWW Image Optimizer', // Menu title
2071
- $permissions, // Capability
2072
- EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE, // Slug
2073
  'ewww_image_optimizer_network_options' // Function to call.
2074
  );
2075
  }
@@ -2080,10 +2240,12 @@ function ewww_image_optimizer_network_admin_menu() {
2080
  */
2081
  function ewww_image_optimizer_resize_dup_check() {
2082
  $meta = wp_get_attachment_metadata( 34 );
 
2083
  list( $file, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, 34 );
2084
- $editor = wp_get_image_editor( $file );
 
2085
  $resized_image = $editor->resize( 150, 150, true );
2086
- $new_file = $editor->generate_filename();
2087
  echo $new_file;
2088
  if ( is_file( $new_file ) ) {
2089
  echo '<br>file already exists<br>';
@@ -2108,19 +2270,19 @@ function ewww_image_optimizer_admin_menu() {
2108
  if ( ! is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) ) {
2109
  // Add options page to the settings menu.
2110
  $ewww_options_page = add_options_page(
2111
- 'EWWW Image Optimizer', // Page title
2112
- 'EWWW Image Optimizer', // Menu title
2113
- apply_filters( 'ewww_image_optimizer_admin_permissions', 'manage_options' ), // Capability
2114
- EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE, // Slug
2115
  'ewww_image_optimizer_options' // Function to call.
2116
  );
2117
  } else {
2118
  // Add options page to the single-site settings menu.
2119
  $ewww_options_page = add_options_page(
2120
- 'EWWW Image Optimizer', // Page title
2121
- 'EWWW Image Optimizer', // Menu title
2122
- apply_filters( 'ewww_image_optimizer_admin_permissions', 'manage_options' ), // Capability
2123
- EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE, // Slug
2124
  'ewww_image_optimizer_network_singlesite_options' // Function to call.
2125
  );
2126
  }
@@ -2129,10 +2291,12 @@ function ewww_image_optimizer_admin_menu() {
2129
  add_media_page( esc_html__( 'Dynamic Image Debugging', 'ewww-image-optimizer' ), esc_html__( 'Dynamic Image Debugging', 'ewww-image-optimizer' ), $permissions, 'ewww-image-optimizer-dynamic-debug', 'ewww_image_optimizer_dynamic_image_debug' );
2130
  // Add Image Queue Debugging to allow clearing and checking queues.
2131
  add_media_page( esc_html__( 'Image Queue Debugging', 'ewww-image-optimizer' ), esc_html__( 'Image Queue Debugging', 'ewww-image-optimizer' ), $permissions, 'ewww-image-optimizer-queue-debug', 'ewww_image_optimizer_image_queue_debug' );
 
 
2132
  }
2133
  if ( is_plugin_active( 'image-store/ImStore.php' ) || is_plugin_active_for_network( 'image-store/ImStore.php' ) ) {
2134
  // Adds an optimize page for Image Store galleries and images.
2135
- $ims_menu = 'edit.php?post_type=ims_gallery';
2136
  $ewww_ims_page = add_submenu_page( $ims_menu, esc_html__( 'Image Store Optimize', 'ewww-image-optimizer' ), esc_html__( 'Optimize', 'ewww-image-optimizer' ), 'ims_change_settings', 'ewww-ims-optimize', 'ewww_image_optimizer_ims' );
2137
  }
2138
  }
@@ -2148,9 +2312,9 @@ function ewww_image_optimizer_retina( $id, $retina_path ) {
2148
  $file_info = pathinfo( $retina_path );
2149
  $extension = '.' . $file_info['extension'];
2150
  preg_match( '/-(\d+x\d+)@2x$/', $file_info['filename'], $fileresize );
2151
- $dimensions = explode( 'x', $fileresize[1] );
2152
  $no_ext_path = $file_info['dirname'] . '/' . preg_replace( '/\d+x\d+@2x$/', '', $file_info['filename'] ) . $dimensions[0] * 2 . 'x' . $dimensions[1] * 2 . '-tmp';
2153
- $temp_path = $no_ext_path . $extension;
2154
  ewwwio_debug_message( "temp path: $temp_path" );
2155
  // Check for any orphaned webp retina images, and fix their paths.
2156
  ewwwio_debug_message( "retina path: $retina_path" );
@@ -2173,9 +2337,9 @@ function ewww_image_optimizer_retina( $id, $retina_path ) {
2173
  // Replace the 'temp' path in the database with the real path.
2174
  $ewwwdb->update( $ewwwdb->ewwwio_images,
2175
  array(
2176
- 'path' => ewww_image_optimizer_relative_path_remove( $retina_path ),
2177
  'attachment_id' => $id,
2178
- 'gallery' => 'media',
2179
  ),
2180
  array(
2181
  'id' => $optimized_query['id'],
@@ -2201,7 +2365,7 @@ function ewww_image_optimizer_ims() {
2201
  echo '<p>' . esc_html__( 'Choose a gallery or', 'ewww-image-optimizer' ) . " <a href='upload.php?page=ewww-image-optimizer-bulk&ids=$gallery_string'>" . esc_html__( 'optimize all galleries', 'ewww-image-optimizer' ) . '</a></p>';
2202
  echo '<table class="wp-list-table widefat media" cellspacing="0"><thead><tr><th>' . esc_html__( 'Gallery ID', 'ewww-image-optimizer' ) . '</th><th>' . esc_html__( 'Gallery Name', 'ewww-image-optimizer' ) . '</th><th>' . esc_html__( 'Images', 'ewww-image-optimizer' ) . '</th><th>' . esc_html__( 'Image Optimizer', 'ewww-image-optimizer' ) . '</th></tr></thead>';
2203
  foreach ( $galleries as $gid ) {
2204
- $image_count = $wpdb->get_var( $wpdb->prepare( "SELECT count(ID) FROM $wpdb->posts WHERE post_type = 'ims_image' AND post_mime_type LIKE '%%image%%' AND post_parent = %d", $gid ) );
2205
  $gallery_name = get_the_title( $gid );
2206
  echo "<tr><td>$gid</td>";
2207
  echo "<td><a href='edit.php?post_type=ims_gallery&page=ewww-ims-optimize&ewww_gid=$gid'>$gallery_name</a></td>";
@@ -2213,8 +2377,8 @@ function ewww_image_optimizer_ims() {
2213
  echo '<p>' . esc_html__( 'No galleries found', 'ewww-image-optimizer' ) . '</p>';
2214
  }
2215
  } else {
2216
- $gid = (int) $_REQUEST['ewww_gid'];
2217
- $attachments = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type = 'ims_image' AND post_mime_type LIKE '%%image%%' AND post_parent = %d ORDER BY ID", $gid ) );
2218
  if ( ewww_image_optimizer_iterable( $attachments ) ) {
2219
  echo "<p><a href='upload.php?page=ewww-image-optimizer-bulk&ids=$gid'>" . esc_html__( 'Optimize Gallery', 'ewww-image-optimizer' ) . '</a></p>';
2220
  echo '<table class="wp-list-table widefat media" cellspacing="0"><thead><tr><th>ID</th><th>&nbsp;</th><th>' . esc_html__( 'Title', 'ewww-image-optimizer' ) . '</th><th>' . esc_html__( 'Gallery', 'ewww-image-optimizer' ) . '</th><th>' . esc_html__( 'Image Optimizer', 'ewww-image-optimizer' ) . '</th></tr></thead>';
@@ -2224,10 +2388,10 @@ function ewww_image_optimizer_ims() {
2224
  if ( empty( $meta['_wp_attachment_metadata'] ) ) {
2225
  continue;
2226
  }
2227
- $meta = maybe_unserialize( $meta['_wp_attachment_metadata'][0] );
2228
- $image_name = get_the_title( $id );
2229
  $gallery_name = get_the_title( $gid );
2230
- $image_url = esc_url( $meta['sizes']['mini']['url'] );
2231
  ?>
2232
  <tr
2233
  <?php
@@ -2296,7 +2460,7 @@ function ewww_image_optimizer_webp_load_jquery() {
2296
  if ( function_exists( 'wp_add_inline_script' ) && ( ! defined( 'EWWW_IMAGE_OPTIMIZER_WEBP_INLINE_FALLBACK' ) || ! EWWW_IMAGE_OPTIMIZER_WEBP_INLINE_FALLBACK ) ) {
2297
  ewwwio_debug_message( 'loading webp script with wp_add_inline_script' );
2298
  wp_add_inline_script( 'jquery-migrate',
2299
- 'function check_webp_feature(a,b){var c={alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"},d=!1,e=new Image;e.onload=function(){var a=e.width>0&&e.height>0;d=!0,b(a)},e.onerror=function(){d=!1,b(!1)},e.src="data:image/webp;base64,"+c[a]}function ewww_load_images(a){jQuery(document).arrive(".ewww_webp",function(){ewww_load_images(a)}),function(b){function d(a,d){for(var e=["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-attachment-id","data-permalink","data-orig-size","data-comments-opened","data-image-meta","data-image-title","data-image-description"],f=0,g=e.length;f<g;f++){var h=b(a).attr(c+e[f]);void 0!==h&&!1!==h&&b(d).attr(e[f],h)}return d}var c="data-";a&&(b(".batch-image img, .image-wrapper a, .ngg-pro-masonry-item a").each(function(){var a=b(this).attr("data-webp");void 0!==a&&!1!==a&&b(this).attr("data-src",a);var a=b(this).attr("data-webp-thumbnail");void 0!==a&&!1!==a&&b(this).attr("data-thumbnail",a)}),b(".image-wrapper a, .ngg-pro-masonry-item a").each(function(){var a=b(this).attr("data-webp");void 0!==a&&!1!==a&&b(this).attr("href",a)}),b(".rev_slider ul li").each(function(){var a=b(this).attr("data-webp-thumb");void 0!==a&&!1!==a&&b(this).attr("data-thumb",a);for(var c=1;c<11;){var a=b(this).attr("data-webp-param"+c);void 0!==a&&!1!==a&&b(this).attr("data-param"+c,a),c++}}),b(".rev_slider img").each(function(){var a=b(this).attr("data-webp-lazyload");void 0!==a&&!1!==a&&b(this).attr("data-lazyload",a)})),b("img.ewww_webp_lazy_retina").each(function(){if(a){var c=b(this).attr("data-srcset-webp");void 0!==c&&!1!==c&&b(this).attr("data-srcset",c)}else{var c=b(this).attr("data-srcset-img");void 0!==c&&!1!==c&&b(this).attr("data-srcset",c)}b(this).removeClass("ewww_webp_lazy_retina")}),b("video").each(function(){if(a){var c=b(this).attr("data-poster-webp");void 0!==c&&!1!==c&&b(this).attr("poster",c)}else{var c=b(this).attr("data-poster-image");void 0!==c&&!1!==c&&b(this).attr("poster",c)}}),b("img.ewww_webp_lazy_load").each(function(){if(a){b(this).attr("data-lazy-src",b(this).attr("data-lazy-webp-src"));var c=b(this).attr("data-srcset-webp");void 0!==c&&!1!==c&&b(this).attr("srcset",c);var c=b(this).attr("data-lazy-srcset-webp");void 0!==c&&!1!==c&&b(this).attr("data-lazy-srcset",c)}else{b(this).attr("data-lazy-src",b(this).attr("data-lazy-img-src"));var c=b(this).attr("data-srcset");void 0!==c&&!1!==c&&b(this).attr("srcset",c);var c=b(this).attr("data-lazy-srcset-img");void 0!==c&&!1!==c&&b(ewww_img).attr("data-lazy-srcset",c)}b(this).removeClass("ewww_webp_lazy_load")}),b(".ewww_webp_lazy_hueman").each(function(){var c=document.createElement("img");if(b(c).attr("src",b(this).attr("data-src")),a){b(c).attr("data-src",b(this).attr("data-webp-src"));var e=b(this).attr("data-srcset-webp");void 0!==e&&!1!==e&&b(c).attr("data-srcset",e)}else{b(c).attr("data-src",b(this).attr("data-img"));var e=b(this).attr("data-srcset-img");void 0!==e&&!1!==e&&b(c).attr("data-srcset",e)}c=d(this,c),b(this).after(c),b(this).removeClass("ewww_webp_lazy_hueman")}),b(".ewww_webp").each(function(){var c=document.createElement("img");if(a){b(c).attr("src",b(this).attr("data-webp"));var e=b(this).attr("data-srcset-webp");void 0!==e&&!1!==e&&b(c).attr("srcset",e);var e=b(this).attr("data-webp-orig-file");void 0!==e&&!1!==e&&b(c).attr("data-orig-file",e);var e=b(this).attr("data-webp-medium-file");void 0!==e&&!1!==e&&b(c).attr("data-medium-file",e);var e=b(this).attr("data-webp-large-file");void 0!==e&&!1!==e&&b(c).attr("data-large-file",e)}else{b(c).attr("src",b(this).attr("data-img"));var e=b(this).attr("data-srcset-img");void 0!==e&&!1!==e&&b(c).attr("srcset",e)}c=d(this,c),b(this).after(c),b(this).removeClass("ewww_webp")})}(jQuery),jQuery.fn.isotope&&jQuery.fn.imagesLoaded&&(jQuery(".fusion-posts-container-infinite").imagesLoaded(function(){jQuery(".fusion-posts-container-infinite").hasClass("isotope")&&jQuery(".fusion-posts-container-infinite").isotope()}),jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").imagesLoaded(function(){jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").isotope()}))}var Arrive=function(a,b,c){"use strict";function l(a,b,c){e.addMethod(b,c,a.unbindEvent),e.addMethod(b,c,a.unbindEventWithSelectorOrCallback),e.addMethod(b,c,a.unbindEventWithSelectorAndCallback)}function m(a){a.arrive=j.bindEvent,l(j,a,"unbindArrive"),a.leave=k.bindEvent,l(k,a,"unbindLeave")}if(a.MutationObserver&&"undefined"!=typeof HTMLElement){var d=0,e=function(){var b=HTMLElement.prototype.matches||HTMLElement.prototype.webkitMatchesSelector||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelector;return{matchesSelector:function(a,c){return a instanceof HTMLElement&&b.call(a,c)},addMethod:function(a,b,c){var d=a[b];a[b]=function(){return c.length==arguments.length?c.apply(this,arguments):"function"==typeof d?d.apply(this,arguments):void 0}},callCallbacks:function(a){for(var c,b=0;c=a[b];b++)c.callback.call(c.elem)},checkChildNodesRecursively:function(a,b,c,d){for(var g,f=0;g=a[f];f++)c(g,b,d)&&d.push({callback:b.callback,elem:g}),g.childNodes.length>0&&e.checkChildNodesRecursively(g.childNodes,b,c,d)},mergeArrays:function(a,b){var d,c={};for(d in a)c[d]=a[d];for(d in b)c[d]=b[d];return c},toElementsArray:function(b){return void 0===b||"number"==typeof b.length&&b!==a||(b=[b]),b}}}(),f=function(){var a=function(){this._eventsBucket=[],this._beforeAdding=null,this._beforeRemoving=null};return a.prototype.addEvent=function(a,b,c,d){var e={target:a,selector:b,options:c,callback:d,firedElems:[]};return this._beforeAdding&&this._beforeAdding(e),this._eventsBucket.push(e),e},a.prototype.removeEvent=function(a){for(var c,b=this._eventsBucket.length-1;c=this._eventsBucket[b];b--)a(c)&&(this._beforeRemoving&&this._beforeRemoving(c),this._eventsBucket.splice(b,1))},a.prototype.beforeAdding=function(a){this._beforeAdding=a},a.prototype.beforeRemoving=function(a){this._beforeRemoving=a},a}(),g=function(b,d){var g=new f,h=this,i={fireOnAttributesModification:!1};return g.beforeAdding(function(c){var i,e=c.target;c.selector,c.callback;e!==a.document&&e!==a||(e=document.getElementsByTagName("html")[0]),i=new MutationObserver(function(a){d.call(this,a,c)});var j=b(c.options);i.observe(e,j),c.observer=i,c.me=h}),g.beforeRemoving(function(a){a.observer.disconnect()}),this.bindEvent=function(a,b,c){b=e.mergeArrays(i,b);for(var d=e.toElementsArray(this),f=0;f<d.length;f++)g.addEvent(d[f],a,b,c)},this.unbindEvent=function(){var a=e.toElementsArray(this);g.removeEvent(function(b){for(var d=0;d<a.length;d++)if(this===c||b.target===a[d])return!0;return!1})},this.unbindEventWithSelectorOrCallback=function(a){var f,b=e.toElementsArray(this),d=a;f="function"==typeof a?function(a){for(var e=0;e<b.length;e++)if((this===c||a.target===b[e])&&a.callback===d)return!0;return!1}:function(d){for(var e=0;e<b.length;e++)if((this===c||d.target===b[e])&&d.selector===a)return!0;return!1},g.removeEvent(f)},this.unbindEventWithSelectorAndCallback=function(a,b){var d=e.toElementsArray(this);g.removeEvent(function(e){for(var f=0;f<d.length;f++)if((this===c||e.target===d[f])&&e.selector===a&&e.callback===b)return!0;return!1})},this},h=function(){function h(a){var b={attributes:!1,childList:!0,subtree:!0};return a.fireOnAttributesModification&&(b.attributes=!0),b}function i(a,b){a.forEach(function(a){var c=a.addedNodes,d=a.target,f=[];null!==c&&c.length>0?e.checkChildNodesRecursively(c,b,k,f):"attributes"===a.type&&k(d,b,f)&&f.push({callback:b.callback,elem:node}),e.callCallbacks(f)})}function k(a,b,f){if(e.matchesSelector(a,b.selector)&&(a._id===c&&(a._id=d++),-1==b.firedElems.indexOf(a._id))){if(b.options.onceOnly){if(0!==b.firedElems.length)return;b.me.unbindEventWithSelectorAndCallback.call(b.target,b.selector,b.callback)}b.firedElems.push(a._id),f.push({callback:b.callback,elem:a})}}var f={fireOnAttributesModification:!1,onceOnly:!1,existing:!1};j=new g(h,i);var l=j.bindEvent;return j.bindEvent=function(a,b,c){void 0===c?(c=b,b=f):b=e.mergeArrays(f,b);var d=e.toElementsArray(this);if(b.existing){for(var g=[],h=0;h<d.length;h++)for(var i=d[h].querySelectorAll(a),j=0;j<i.length;j++)g.push({callback:c,elem:i[j]});if(b.onceOnly&&g.length)return c.call(g[0].elem);setTimeout(e.callCallbacks,1,g)}l.call(this,a,b,c)},j},i=function(){function d(a){return{childList:!0,subtree:!0}}function f(a,b){a.forEach(function(a){var c=a.removedNodes,f=(a.target,[]);null!==c&&c.length>0&&e.checkChildNodesRecursively(c,b,h,f),e.callCallbacks(f)})}function h(a,b){return e.matchesSelector(a,b.selector)}var c={};k=new g(d,f);var i=k.bindEvent;return k.bindEvent=function(a,b,d){void 0===d?(d=b,b=c):b=e.mergeArrays(c,b),i.call(this,a,b,d)},k},j=new h,k=new i;b&&m(b.fn),m(HTMLElement.prototype),m(NodeList.prototype),m(HTMLCollection.prototype),m(HTMLDocument.prototype),m(Window.prototype);var n={};return l(j,n,"unbindAllArrive"),l(k,n,"unbindAllLeave"),n}}(window,"undefined"==typeof jQuery?null:jQuery,void 0);"undefined"!=typeof jQuery&&check_webp_feature("alpha",ewww_load_images);'
2300
  );
2301
  }
2302
  }
@@ -2310,11 +2474,11 @@ function ewww_image_optimizer_webp_inline_script() {
2310
  ewwwio_debug_message( 'loading webp script without wp_add_inline_script' );
2311
  ?>
2312
  <script>
2313
- function check_webp_feature(a,b){var c={alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"},d=!1,e=new Image;e.onload=function(){var a=e.width>0&&e.height>0;d=!0,b(a)},e.onerror=function(){d=!1,b(!1)},e.src="data:image/webp;base64,"+c[a]}function ewww_load_images(a){jQuery(document).arrive(".ewww_webp",function(){ewww_load_images(a)}),function(b){function d(a,d){for(var e=["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-attachment-id","data-permalink","data-orig-size","data-comments-opened","data-image-meta","data-image-title","data-image-description"],f=0,g=e.length;f<g;f++){var h=b(a).attr(c+e[f]);void 0!==h&&!1!==h&&b(d).attr(e[f],h)}return d}var c="data-";a&&(b(".batch-image img, .image-wrapper a, .ngg-pro-masonry-item a").each(function(){var a=b(this).attr("data-webp");void 0!==a&&!1!==a&&b(this).attr("data-src",a);var a=b(this).attr("data-webp-thumbnail");void 0!==a&&!1!==a&&b(this).attr("data-thumbnail",a)}),b(".image-wrapper a, .ngg-pro-masonry-item a").each(function(){var a=b(this).attr("data-webp");void 0!==a&&!1!==a&&b(this).attr("href",a)}),b(".rev_slider ul li").each(function(){var a=b(this).attr("data-webp-thumb");void 0!==a&&!1!==a&&b(this).attr("data-thumb",a);for(var c=1;c<11;){var a=b(this).attr("data-webp-param"+c);void 0!==a&&!1!==a&&b(this).attr("data-param"+c,a),c++}}),b(".rev_slider img").each(function(){var a=b(this).attr("data-webp-lazyload");void 0!==a&&!1!==a&&b(this).attr("data-lazyload",a)})),b("img.ewww_webp_lazy_retina").each(function(){if(a){var c=b(this).attr("data-srcset-webp");void 0!==c&&!1!==c&&b(this).attr("data-srcset",c)}else{var c=b(this).attr("data-srcset-img");void 0!==c&&!1!==c&&b(this).attr("data-srcset",c)}b(this).removeClass("ewww_webp_lazy_retina")}),b("video").each(function(){if(a){var c=b(this).attr("data-poster-webp");void 0!==c&&!1!==c&&b(this).attr("poster",c)}else{var c=b(this).attr("data-poster-image");void 0!==c&&!1!==c&&b(this).attr("poster",c)}}),b("img.ewww_webp_lazy_load").each(function(){if(a){b(this).attr("data-lazy-src",b(this).attr("data-lazy-webp-src"));var c=b(this).attr("data-srcset-webp");void 0!==c&&!1!==c&&b(this).attr("srcset",c);var c=b(this).attr("data-lazy-srcset-webp");void 0!==c&&!1!==c&&b(this).attr("data-lazy-srcset",c)}else{b(this).attr("data-lazy-src",b(this).attr("data-lazy-img-src"));var c=b(this).attr("data-srcset");void 0!==c&&!1!==c&&b(this).attr("srcset",c);var c=b(this).attr("data-lazy-srcset-img");void 0!==c&&!1!==c&&b(ewww_img).attr("data-lazy-srcset",c)}b(this).removeClass("ewww_webp_lazy_load")}),b(".ewww_webp_lazy_hueman").each(function(){var c=document.createElement("img");if(b(c).attr("src",b(this).attr("data-src")),a){b(c).attr("data-src",b(this).attr("data-webp-src"));var e=b(this).attr("data-srcset-webp");void 0!==e&&!1!==e&&b(c).attr("data-srcset",e)}else{b(c).attr("data-src",b(this).attr("data-img"));var e=b(this).attr("data-srcset-img");void 0!==e&&!1!==e&&b(c).attr("data-srcset",e)}c=d(this,c),b(this).after(c),b(this).removeClass("ewww_webp_lazy_hueman")}),b(".ewww_webp").each(function(){var c=document.createElement("img");if(a){b(c).attr("src",b(this).attr("data-webp"));var e=b(this).attr("data-srcset-webp");void 0!==e&&!1!==e&&b(c).attr("srcset",e);var e=b(this).attr("data-webp-orig-file");void 0!==e&&!1!==e&&b(c).attr("data-orig-file",e);var e=b(this).attr("data-webp-medium-file");void 0!==e&&!1!==e&&b(c).attr("data-medium-file",e);var e=b(this).attr("data-webp-large-file");void 0!==e&&!1!==e&&b(c).attr("data-large-file",e)}else{b(c).attr("src",b(this).attr("data-img"));var e=b(this).attr("data-srcset-img");void 0!==e&&!1!==e&&b(c).attr("srcset",e)}c=d(this,c),b(this).after(c),b(this).removeClass("ewww_webp")})}(jQuery),jQuery.fn.isotope&&jQuery.fn.imagesLoaded&&(jQuery(".fusion-posts-container-infinite").imagesLoaded(function(){jQuery(".fusion-posts-container-infinite").hasClass("isotope")&&jQuery(".fusion-posts-container-infinite").isotope()}),jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").imagesLoaded(function(){jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").isotope()}))}var Arrive=function(a,b,c){"use strict";function l(a,b,c){e.addMethod(b,c,a.unbindEvent),e.addMethod(b,c,a.unbindEventWithSelectorOrCallback),e.addMethod(b,c,a.unbindEventWithSelectorAndCallback)}function m(a){a.arrive=j.bindEvent,l(j,a,"unbindArrive"),a.leave=k.bindEvent,l(k,a,"unbindLeave")}if(a.MutationObserver&&"undefined"!=typeof HTMLElement){var d=0,e=function(){var b=HTMLElement.prototype.matches||HTMLElement.prototype.webkitMatchesSelector||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelector;return{matchesSelector:function(a,c){return a instanceof HTMLElement&&b.call(a,c)},addMethod:function(a,b,c){var d=a[b];a[b]=function(){return c.length==arguments.length?c.apply(this,arguments):"function"==typeof d?d.apply(this,arguments):void 0}},callCallbacks:function(a){for(var c,b=0;c=a[b];b++)c.callback.call(c.elem)},checkChildNodesRecursively:function(a,b,c,d){for(var g,f=0;g=a[f];f++)c(g,b,d)&&d.push({callback:b.callback,elem:g}),g.childNodes.length>0&&e.checkChildNodesRecursively(g.childNodes,b,c,d)},mergeArrays:function(a,b){var d,c={};for(d in a)c[d]=a[d];for(d in b)c[d]=b[d];return c},toElementsArray:function(b){return void 0===b||"number"==typeof b.length&&b!==a||(b=[b]),b}}}(),f=function(){var a=function(){this._eventsBucket=[],this._beforeAdding=null,this._beforeRemoving=null};return a.prototype.addEvent=function(a,b,c,d){var e={target:a,selector:b,options:c,callback:d,firedElems:[]};return this._beforeAdding&&this._beforeAdding(e),this._eventsBucket.push(e),e},a.prototype.removeEvent=function(a){for(var c,b=this._eventsBucket.length-1;c=this._eventsBucket[b];b--)a(c)&&(this._beforeRemoving&&this._beforeRemoving(c),this._eventsBucket.splice(b,1))},a.prototype.beforeAdding=function(a){this._beforeAdding=a},a.prototype.beforeRemoving=function(a){this._beforeRemoving=a},a}(),g=function(b,d){var g=new f,h=this,i={fireOnAttributesModification:!1};return g.beforeAdding(function(c){var i,e=c.target;c.selector,c.callback;e!==a.document&&e!==a||(e=document.getElementsByTagName("html")[0]),i=new MutationObserver(function(a){d.call(this,a,c)});var j=b(c.options);i.observe(e,j),c.observer=i,c.me=h}),g.beforeRemoving(function(a){a.observer.disconnect()}),this.bindEvent=function(a,b,c){b=e.mergeArrays(i,b);for(var d=e.toElementsArray(this),f=0;f<d.length;f++)g.addEvent(d[f],a,b,c)},this.unbindEvent=function(){var a=e.toElementsArray(this);g.removeEvent(function(b){for(var d=0;d<a.length;d++)if(this===c||b.target===a[d])return!0;return!1})},this.unbindEventWithSelectorOrCallback=function(a){var f,b=e.toElementsArray(this),d=a;f="function"==typeof a?function(a){for(var e=0;e<b.length;e++)if((this===c||a.target===b[e])&&a.callback===d)return!0;return!1}:function(d){for(var e=0;e<b.length;e++)if((this===c||d.target===b[e])&&d.selector===a)return!0;return!1},g.removeEvent(f)},this.unbindEventWithSelectorAndCallback=function(a,b){var d=e.toElementsArray(this);g.removeEvent(function(e){for(var f=0;f<d.length;f++)if((this===c||e.target===d[f])&&e.selector===a&&e.callback===b)return!0;return!1})},this},h=function(){function h(a){var b={attributes:!1,childList:!0,subtree:!0};return a.fireOnAttributesModification&&(b.attributes=!0),b}function i(a,b){a.forEach(function(a){var c=a.addedNodes,d=a.target,f=[];null!==c&&c.length>0?e.checkChildNodesRecursively(c,b,k,f):"attributes"===a.type&&k(d,b,f)&&f.push({callback:b.callback,elem:node}),e.callCallbacks(f)})}function k(a,b,f){if(e.matchesSelector(a,b.selector)&&(a._id===c&&(a._id=d++),-1==b.firedElems.indexOf(a._id))){if(b.options.onceOnly){if(0!==b.firedElems.length)return;b.me.unbindEventWithSelectorAndCallback.call(b.target,b.selector,b.callback)}b.firedElems.push(a._id),f.push({callback:b.callback,elem:a})}}var f={fireOnAttributesModification:!1,onceOnly:!1,existing:!1};j=new g(h,i);var l=j.bindEvent;return j.bindEvent=function(a,b,c){void 0===c?(c=b,b=f):b=e.mergeArrays(f,b);var d=e.toElementsArray(this);if(b.existing){for(var g=[],h=0;h<d.length;h++)for(var i=d[h].querySelectorAll(a),j=0;j<i.length;j++)g.push({callback:c,elem:i[j]});if(b.onceOnly&&g.length)return c.call(g[0].elem);setTimeout(e.callCallbacks,1,g)}l.call(this,a,b,c)},j},i=function(){function d(a){return{childList:!0,subtree:!0}}function f(a,b){a.forEach(function(a){var c=a.removedNodes,f=(a.target,[]);null!==c&&c.length>0&&e.checkChildNodesRecursively(c,b,h,f),e.callCallbacks(f)})}function h(a,b){return e.matchesSelector(a,b.selector)}var c={};k=new g(d,f);var i=k.bindEvent;return k.bindEvent=function(a,b,d){void 0===d?(d=b,b=c):b=e.mergeArrays(c,b),i.call(this,a,b,d)},k},j=new h,k=new i;b&&m(b.fn),m(HTMLElement.prototype),m(NodeList.prototype),m(HTMLCollection.prototype),m(HTMLDocument.prototype),m(Window.prototype);var n={};return l(j,n,"unbindAllArrive"),l(k,n,"unbindAllLeave"),n}}(window,"undefined"==typeof jQuery?null:jQuery,void 0);"undefined"!=typeof jQuery&&check_webp_feature("alpha",ewww_load_images);
2314
  </script>
2315
  <?php
2316
  } // End if().
2317
- // Current length 9473.
2318
  }
2319
 
2320
  /**
@@ -2336,7 +2500,7 @@ function ewww_image_optimizer_media_scripts( $hook ) {
2336
  'ewww_vars',
2337
  array(
2338
  'optimizing' => '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' /></p>",
2339
- 'restoring' => '<p>' . esc_html__( 'Restoring', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' /></p>",
2340
  )
2341
  );
2342
  }
@@ -2377,7 +2541,7 @@ function ewww_image_optimizer_gd_support() {
2377
  ewwwio_debug_message( 'GD found, supports:' );
2378
  if ( ewww_image_optimizer_iterable( $gd_support ) ) {
2379
  foreach ( $gd_support as $supports => $supported ) {
2380
- ewwwio_debug_message( "$supports: $supported" );
2381
  }
2382
  ewwwio_memory( __FUNCTION__ );
2383
  if ( ( ! empty( $gd_support['JPEG Support'] ) || ! empty( $gd_support['JPG Support'] ) ) && ! empty( $gd_support['PNG Support'] ) ) {
@@ -2448,7 +2612,7 @@ function ewww_image_optimizer_aux_paths_sanitize( $input ) {
2448
  return '';
2449
  }
2450
  $path_array = array();
2451
- $paths = explode( "\n", $input );
2452
  if ( ewww_image_optimizer_iterable( $paths ) ) {
2453
  $i = 0;
2454
  foreach ( $paths as $path ) {
@@ -2509,7 +2673,7 @@ function ewww_image_optimizer_exclude_paths_sanitize( $input ) {
2509
  return '';
2510
  }
2511
  $path_array = array();
2512
- $paths = explode( "\n", $input );
2513
  if ( ewww_image_optimizer_iterable( $paths ) ) {
2514
  $i = 0;
2515
  foreach ( $paths as $path ) {
@@ -2536,13 +2700,13 @@ function ewww_image_optimizer_webp_paths_sanitize( $paths ) {
2536
  return '';
2537
  }
2538
  $paths_entered = explode( "\n", $paths );
2539
- $paths_saved = array();
2540
  if ( ewww_image_optimizer_iterable( $paths_entered ) ) {
2541
  $i = 0;
2542
  foreach ( $paths_entered as $path ) {
2543
  $i++;
2544
  $original_path = esc_html( $path );
2545
- $path = esc_url( $path, null, 'db' );
2546
  if ( ! empty( $path ) ) {
2547
  if ( ! substr_count( $path, '.' ) ) {
2548
  add_settings_error( 'ewww_image_optimizer_webp_paths', "ewwwio-webp-paths-$i", sprintf(
@@ -2709,6 +2873,7 @@ function ewww_image_optimizer_manual() {
2709
  if ( ! wp_doing_ajax() ) {
2710
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
2711
  }
 
2712
  wp_die( json_encode( array(
2713
  'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
2714
  ) ) );
@@ -2719,6 +2884,7 @@ function ewww_image_optimizer_manual() {
2719
  if ( ! wp_doing_ajax() ) {
2720
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
2721
  }
 
2722
  wp_die( json_encode( array(
2723
  'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ),
2724
  ) ) );
@@ -2730,6 +2896,7 @@ function ewww_image_optimizer_manual() {
2730
  if ( ! wp_doing_ajax() ) {
2731
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
2732
  }
 
2733
  wp_die( json_encode( array(
2734
  'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
2735
  ) ) );
@@ -2749,6 +2916,7 @@ function ewww_image_optimizer_manual() {
2749
  if ( ! wp_doing_ajax() ) {
2750
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
2751
  }
 
2752
  wp_die( json_encode( array(
2753
  'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
2754
  ) ) );
@@ -2766,6 +2934,7 @@ function ewww_image_optimizer_manual() {
2766
  if ( ! wp_doing_ajax() ) {
2767
  wp_die( esc_html__( 'License exceeded', 'ewww-image-optimizer' ) );
2768
  }
 
2769
  wp_die( json_encode( array(
2770
  'error' => esc_html__( 'License exceeded', 'ewww-image-optimizer' ),
2771
  ) ) );
@@ -2783,8 +2952,9 @@ function ewww_image_optimizer_manual() {
2783
  return;
2784
  }
2785
  ewwwio_memory( __FUNCTION__ );
2786
- die( json_encode( array(
2787
- 'success' => $success,
 
2788
  'basename' => $basename,
2789
  ) ) );
2790
  }
@@ -2812,6 +2982,7 @@ function ewww_image_optimizer_restore_from_meta_data( $meta, $id ) {
2812
  if ( empty( $db_image ) || ! is_array( $db_image ) || empty( $db_image['path'] ) ) {
2813
  // Get the filepath based on the meta and id.
2814
  list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
 
2815
  $db_image = ewww_image_optimizer_find_already_optimized( $file_path );
2816
  if ( empty( $db_image ) || ! is_array( $db_image ) || empty( $db_image['path'] ) ) {
2817
  return $meta;
@@ -2857,6 +3028,7 @@ function ewww_image_optimizer_cloud_restore_single_image_handler() {
2857
  $permissions = apply_filters( 'ewww_image_optimizer_manual_permissions', '' );
2858
  if ( false === current_user_can( $permissions ) ) {
2859
  // Display error message if insufficient permissions.
 
2860
  wp_die( json_encode( array(
2861
  'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
2862
  ) ) );
@@ -2864,11 +3036,13 @@ function ewww_image_optimizer_cloud_restore_single_image_handler() {
2864
  // Make sure we didn't accidentally get to this page without an attachment to work on.
2865
  if ( empty( $_REQUEST['ewww_image_id'] ) ) {
2866
  // Display an error message since we don't have anything to work on.
 
2867
  wp_die( json_encode( array(
2868
  'error' => esc_html__( 'No image ID was provided.', 'ewww-image-optimizer' ),
2869
  ) ) );
2870
  }
2871
  if ( empty( $_REQUEST['ewww_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) ) {
 
2872
  wp_die( json_encode( array(
2873
  'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ),
2874
  ) ) );
@@ -2876,10 +3050,12 @@ function ewww_image_optimizer_cloud_restore_single_image_handler() {
2876
  session_write_close();
2877
  $image = (int) $_REQUEST['ewww_image_id'];
2878
  if ( ewww_image_optimizer_cloud_restore_single_image( $image ) ) {
 
2879
  wp_die( json_encode( array(
2880
  'success' => 1,
2881
  ) ) );
2882
  }
 
2883
  wp_die( json_encode( array(
2884
  'error' => esc_html__( 'Unable to restore image.', 'ewww-image-optimizer' ),
2885
  ) ) );
@@ -2910,19 +3086,19 @@ function ewww_image_optimizer_cloud_restore_single_image( $image ) {
2910
  $image['path'] = ewww_image_optimizer_relative_path_replace( $image['path'] );
2911
  }
2912
  $api_key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
2913
- $domain = parse_url( get_site_url(), PHP_URL_HOST );
2914
- $url = 'http://optimize.exactlywww.com/backup/restore.php';
2915
- $ssl = wp_http_supports( array( 'ssl' ) );
2916
  if ( $ssl ) {
2917
  $url = set_url_scheme( $url, 'https' );
2918
  }
2919
  $result = wp_remote_post( $url, array(
2920
- 'timeout' => 30,
2921
  'sslverify' => false,
2922
- 'body' => array(
2923
  'api_key' => $api_key,
2924
- 'domain' => $domain,
2925
- 'hash' => $image['backup'],
2926
  ),
2927
  ) );
2928
  if ( is_wp_error( $result ) ) {
@@ -2936,7 +3112,7 @@ function ewww_image_optimizer_cloud_restore_single_image( $image ) {
2936
  $new_type = ewww_image_optimizer_mimetype( $image['path'] . '.tmp', 'i' );
2937
  $old_type = '';
2938
  if ( is_file( $image['path'] ) ) {
2939
- $old_type = ewww_image_optimizer_mimetype( $image['path'] );
2940
  }
2941
  if ( ! in_array( $new_type, $enabled_types ) ) {
2942
  return false;
@@ -2971,6 +3147,7 @@ function ewww_image_optimizer_delete( $id ) {
2971
  } else {
2972
  $ewwwdb = $wpdb;
2973
  }
 
2974
  // Finds non-meta images to remove from disk, and from db, as well as converted originals.
2975
  if (
2976
  $optimized_images = $ewwwdb->get_results( "SELECT path,converted FROM $ewwwdb->ewwwio_images WHERE attachment_id = $id AND gallery = 'media'", ARRAY_A )
@@ -2980,6 +3157,9 @@ function ewww_image_optimizer_delete( $id ) {
2980
  if ( ! empty( $image['path'] ) ) {
2981
  $image['path'] = ewww_image_optimizer_relative_path_replace( $image['path'] );
2982
  }
 
 
 
2983
  if ( ! empty( $image['path'] ) && is_file( $image['path'] ) ) {
2984
  unlink( $image['path'] );
2985
  if ( is_file( $image['path'] . '.webp' ) ) {
@@ -3011,7 +3191,7 @@ function ewww_image_optimizer_delete( $id ) {
3011
  // Get the base filename.
3012
  $filename = basename( $file_path );
3013
  // Delete any residual webp versions.
3014
- $webpfile = $filename . '.webp';
3015
  $webpfileold = preg_replace( '/\.\w+$/', '.webp', $filename );
3016
  if ( is_file( $webpfile ) ) {
3017
  unlink( $webpfile );
@@ -3041,7 +3221,7 @@ function ewww_image_optimizer_delete( $id ) {
3041
  $base_dir = dirname( $file_path ) . '/';
3042
  foreach ( $meta['sizes'] as $size => $data ) {
3043
  // Delete any residual webp versions.
3044
- $webpfile = $base_dir . $data['file'] . '.webp';
3045
  $webpfileold = preg_replace( '/\.\w+$/', '.webp', $base_dir . $data['file'] );
3046
  if ( is_file( $webpfile ) ) {
3047
  unlink( $webpfile );
@@ -3058,7 +3238,7 @@ function ewww_image_optimizer_delete( $id ) {
3058
  // Retrieve the filename from the metadata.
3059
  $filename = $data['orig_file'];
3060
  // Retrieve any posts that link the image.
3061
- $esql = "SELECT ID, post_content FROM $ewwwdb->posts WHERE post_content LIKE '%$filename%' LIMIT 1";
3062
  $srows = $ewwwdb->get_row( $esql );
3063
  // If there are no posts containing links to the original, delete it.
3064
  if ( empty( $srows ) ) {
@@ -3198,7 +3378,7 @@ function ewww_image_optimizer_cloud_verify( $cache = true, $api_key = '' ) {
3198
  }
3199
  $result = ewww_image_optimizer_cloud_post_key( $url, $api_key );
3200
  if ( is_wp_error( $result ) ) {
3201
- $url = set_url_scheme( $url, 'http' );
3202
  $error_message = $result->get_error_message();
3203
  ewwwio_debug_message( "verification failed: $error_message" );
3204
  $result = ewww_image_optimizer_cloud_post_key( $url, $api_key );
@@ -3241,9 +3421,9 @@ function ewww_image_optimizer_cloud_verify( $cache = true, $api_key = '' ) {
3241
  */
3242
  function ewww_image_optimizer_cloud_post_key( $url, $key ) {
3243
  $result = wp_remote_post( $url, array(
3244
- 'timeout' => 5,
3245
  'sslverify' => false,
3246
- 'body' => array(
3247
  'api_key' => $key,
3248
  ),
3249
  ) );
@@ -3258,15 +3438,15 @@ function ewww_image_optimizer_cloud_post_key( $url, $key ) {
3258
  function ewww_image_optimizer_cloud_quota() {
3259
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
3260
  $api_key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
3261
- $url = 'http://optimize.exactlywww.com/quota/';
3262
- $ssl = wp_http_supports( array( 'ssl' ) );
3263
  if ( $ssl ) {
3264
  $url = set_url_scheme( $url, 'https' );
3265
  }
3266
  $result = wp_remote_post( $url, array(
3267
- 'timeout' => 5,
3268
  'sslverify' => false,
3269
- 'body' => array(
3270
  'api_key' => $api_key,
3271
  ),
3272
  ) );
@@ -3295,6 +3475,8 @@ function ewww_image_optimizer_cloud_quota() {
3295
  /* translators: 1: Number of images */
3296
  _n( '%1$d image credit remaining.', '%1$d image credits remaining.', $real_quota, 'ewww-image-optimizer' ), $real_quota
3297
  ) );
 
 
3298
  } else {
3299
  return esc_html( sprintf(
3300
  /* translators: 1: Number of image credits used 2: Number of image credits available 3: days until subscription renewal */
@@ -3340,7 +3522,7 @@ function ewww_image_optimizer_cloud_optimizer( $file, $type, $convert = false, $
3340
  ewww_image_optimizer_debug_log();
3341
  }
3342
  $ewww_status = get_transient( 'ewww_image_optimizer_cloud_status' );
3343
- $started = microtime( true );
3344
  if ( preg_match( '/exceeded/', $ewww_status ) ) {
3345
  if ( ! ewww_image_optimizer_cloud_verify() ) {
3346
  return array( $file, false, 'key verification failed', 0, '' );
@@ -3386,8 +3568,12 @@ function ewww_image_optimizer_cloud_optimizer( $file, $type, $convert = false, $
3386
  } else {
3387
  $lossy = 0;
3388
  }
 
 
 
 
3389
  if ( 'image/webp' == $newtype ) {
3390
- $webp = 1;
3391
  $jpg_quality = apply_filters( 'jpeg_quality', $jpg_quality, 'image/webp' );
3392
  } else {
3393
  $webp = 0;
@@ -3420,7 +3606,7 @@ function ewww_image_optimizer_cloud_optimizer( $file, $type, $convert = false, $
3420
  }
3421
  $domain = parse_url( get_site_url(), PHP_URL_HOST );
3422
  } else {
3423
- $hash = '';
3424
  $domain = parse_url( get_site_url(), PHP_URL_HOST );
3425
  }
3426
  ewwwio_debug_message( "file: $file " );
@@ -3432,8 +3618,8 @@ function ewww_image_optimizer_cloud_optimizer( $file, $type, $convert = false, $
3432
  ewwwio_debug_message( "jpg fill: $jpg_fill" );
3433
  ewwwio_debug_message( "jpg quality: $jpg_quality" );
3434
  $api_key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
3435
- $url = 'http://optimize.exactlywww.com/v2/';
3436
- $ssl = wp_http_supports( array( 'ssl' ) );
3437
  if ( $ssl ) {
3438
  $url = set_url_scheme( $url, 'https' );
3439
  }
@@ -3441,23 +3627,24 @@ function ewww_image_optimizer_cloud_optimizer( $file, $type, $convert = false, $
3441
 
3442
  $headers = array(
3443
  'content-type' => 'multipart/form-data; boundary=' . $boundary,
3444
- 'timeout' => 300,
3445
- 'httpversion' => '1.0',
3446
- 'blocking' => true,
3447
  );
 
3448
  $post_fields = array(
3449
- 'filename' => $file,
3450
- 'convert' => $convert,
3451
- 'metadata' => $metadata,
3452
- 'api_key' => $api_key,
3453
- 'jpg_fill' => $jpg_fill,
3454
- 'quality' => $jpg_quality,
3455
- 'compress' => $png_compress,
3456
- 'lossy' => $lossy,
3457
  'lossy_fast' => $lossy_fast,
3458
- 'webp' => $webp,
3459
- 'backup' => $hash,
3460
- 'domain' => $domain,
3461
  );
3462
 
3463
  $payload = '';
@@ -3484,10 +3671,10 @@ function ewww_image_optimizer_cloud_optimizer( $file, $type, $convert = false, $
3484
 
3485
  // Retrieve the time when the optimizer starts.
3486
  $response = wp_remote_post( $url, array(
3487
- 'timeout' => 300,
3488
- 'headers' => $headers,
3489
  'sslverify' => false,
3490
- 'body' => $payload,
3491
  ) );
3492
  if ( is_wp_error( $response ) ) {
3493
  $error_message = $response->get_error_message();
@@ -3497,10 +3684,10 @@ function ewww_image_optimizer_cloud_optimizer( $file, $type, $convert = false, $
3497
  $tempfile = $file . '.tmp';
3498
  file_put_contents( $tempfile, $response['body'] );
3499
  $orig_size = filesize( $file );
3500
- $newsize = $orig_size;
3501
  $converted = false;
3502
- $msg = '';
3503
- if ( preg_match( '/exceeded/', $response['body'] ) ) {
3504
  ewwwio_debug_message( 'License Exceeded' );
3505
  set_transient( 'ewww_image_optimizer_cloud_status', 'exceeded', 3600 );
3506
  $msg = 'exceeded';
@@ -3515,7 +3702,7 @@ function ewww_image_optimizer_cloud_optimizer( $file, $type, $convert = false, $
3515
  rename( $tempfile, $newfile );
3516
  } elseif ( ewww_image_optimizer_mimetype( $tempfile, 'i' ) == $newtype ) {
3517
  $converted = true;
3518
- $newsize = filesize( $tempfile );
3519
  ewwwio_debug_message( "cloud results: $newsize (new) vs. $orig_size (original)" );
3520
  rename( $tempfile, $newfile );
3521
  $file = $newfile;
@@ -3547,7 +3734,7 @@ function ewww_image_optimizer_cloud_autorotate( $file, $type ) {
3547
  ewww_image_optimizer_debug_log();
3548
  }
3549
  $ewww_status = get_transient( 'ewww_image_optimizer_cloud_status' );
3550
- $started = microtime( true );
3551
  if ( preg_match( '/exceeded/', $ewww_status ) ) {
3552
  if ( ! ewww_image_optimizer_cloud_verify() ) {
3553
  ewwwio_debug_message( 'cloud verify failed, image not rotated' );
@@ -3565,8 +3752,8 @@ function ewww_image_optimizer_cloud_autorotate( $file, $type ) {
3565
  ewwwio_debug_message( "file: $file " );
3566
  ewwwio_debug_message( "type: $type" );
3567
  $api_key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
3568
- $url = 'http://optimize.exactlywww.com/rotate/';
3569
- $ssl = wp_http_supports( array( 'ssl' ) );
3570
  if ( $ssl ) {
3571
  $url = set_url_scheme( $url, 'https' );
3572
  }
@@ -3574,13 +3761,14 @@ function ewww_image_optimizer_cloud_autorotate( $file, $type ) {
3574
 
3575
  $headers = array(
3576
  'content-type' => 'multipart/form-data; boundary=' . $boundary,
3577
- 'timeout' => 60,
3578
- 'httpversion' => '1.0',
3579
- 'blocking' => true,
3580
  );
 
3581
  $post_fields = array(
3582
  'filename' => $file,
3583
- 'api_key' => $api_key,
3584
  );
3585
 
3586
  $payload = '';
@@ -3606,10 +3794,10 @@ function ewww_image_optimizer_cloud_autorotate( $file, $type ) {
3606
  $payload .= '--' . $boundary . '--';
3607
 
3608
  $response = wp_remote_post( $url, array(
3609
- 'timeout' => 60,
3610
- 'headers' => $headers,
3611
  'sslverify' => false,
3612
- 'body' => $payload,
3613
  ) );
3614
  if ( is_wp_error( $response ) ) {
3615
  $error_message = $response->get_error_message();
@@ -3619,7 +3807,7 @@ function ewww_image_optimizer_cloud_autorotate( $file, $type ) {
3619
  $tempfile = $file . '.tmp';
3620
  file_put_contents( $tempfile, $response['body'] );
3621
  $orig_size = filesize( $file );
3622
- $newsize = $orig_size;
3623
  if ( preg_match( '/exceeded/', $response['body'] ) ) {
3624
  ewwwio_debug_message( 'License Exceeded' );
3625
  set_transient( 'ewww_image_optimizer_cloud_status', 'exceeded', 3600 );
@@ -3656,41 +3844,41 @@ function ewww_image_optimizer_db_init() {
3656
  }
3657
 
3658
  $ewwwdb->field_types = array(
3659
- 'post_author' => '%d',
3660
- 'post_parent' => '%d',
3661
- 'menu_order' => '%d',
3662
- 'term_id' => '%d',
3663
- 'term_group' => '%d',
3664
  'term_taxonomy_id' => '%d',
3665
- 'parent' => '%d',
3666
- 'count' => '%d',
3667
- 'object_id' => '%d',
3668
- 'term_order' => '%d',
3669
- 'ID' => '%d',
3670
- 'comment_ID' => '%d',
3671
- 'comment_post_ID' => '%d',
3672
- 'comment_parent' => '%d',
3673
- 'user_id' => '%d',
3674
- 'link_id' => '%d',
3675
- 'link_owner' => '%d',
3676
- 'link_rating' => '%d',
3677
- 'option_id' => '%d',
3678
- 'blog_id' => '%d',
3679
- 'meta_id' => '%d',
3680
- 'post_id' => '%d',
3681
- 'user_status' => '%d',
3682
- 'umeta_id' => '%d',
3683
- 'comment_karma' => '%d',
3684
- 'comment_count' => '%d',
3685
  // multisite.
3686
- 'active' => '%d',
3687
- 'cat_id' => '%d',
3688
- 'deleted' => '%d',
3689
- 'lang_id' => '%d',
3690
- 'mature' => '%d',
3691
- 'public' => '%d',
3692
- 'site_id' => '%d',
3693
- 'spam' => '%d',
3694
  );
3695
 
3696
  $prefix = $ewwwdb->set_prefix( $table_prefix );
@@ -3799,7 +3987,7 @@ function ewww_image_optimizer_update_table( $attachment, $opt_size, $orig_size,
3799
  // First check if the image was converted, so we don't orphan records.
3800
  if ( $original && $original != $attachment ) {
3801
  $already_optimized = ewww_image_optimizer_find_already_optimized( $original );
3802
- $converted = $original;
3803
  } else {
3804
  global $s3_uploads_image;
3805
  if ( class_exists( 'S3_Uploads' ) && ! empty( $s3_uploads_image ) && $s3_uploads_image != $attachment ) {
@@ -3826,12 +4014,12 @@ function ewww_image_optimizer_update_table( $attachment, $opt_size, $orig_size,
3826
  $results_msg = ewww_image_optimizer_image_results( $orig_size, $opt_size, $prev_string );
3827
 
3828
  $updates = array(
3829
- 'path' => ewww_image_optimizer_relative_path_remove( $attachment ),
3830
- 'converted' => $converted,
3831
  'image_size' => $opt_size,
3832
- 'results' => $results_msg,
3833
- 'updates' => 1,
3834
- 'backup' => preg_replace( '/[^\w]/', '', $backup_hash ),
3835
  );
3836
  if ( ! seems_utf8( $updates['path'] ) ) {
3837
  $updates['path'] = utf8_encode( $updates['path'] );
@@ -3849,7 +4037,7 @@ function ewww_image_optimizer_update_table( $attachment, $opt_size, $orig_size,
3849
  $updates['resize'] = $ewww_image->resize;
3850
  }
3851
  $updates['orig_size'] = $orig_size;
3852
- $updates['updated'] = date( 'Y-m-d H:i:s' );
3853
  $ewwwdb->insert( $ewwwdb->ewwwio_images, $updates );
3854
  } else {
3855
  if ( is_array( $already_optimized ) && empty( $already_optimized['orig_size'] ) ) {
@@ -3910,7 +4098,7 @@ function ewww_image_optimizer_image_results( $orig_size, $opt_size, $prev_string
3910
  $results_msg = __( 'No savings', 'ewww-image-optimizer' );
3911
  } else {
3912
  // Calculate how much space was saved.
3913
- $savings = intval( $orig_size ) - intval( $opt_size );
3914
  $savings_str = ewww_image_optimizer_size_format( $savings );
3915
  // Determine the percentage savings.
3916
  $percent = number_format_i18n( 100 - ( 100 * ( $opt_size / $orig_size ) ), 1 ) . '%';
@@ -3969,13 +4157,13 @@ function ewww_image_optimizer_aux_images_loop( $attachment = null, $auto = false
3969
  }
3970
  global $ewww_defer;
3971
  $ewww_defer = false;
3972
- $output = array();
3973
  // Verify that an authorized user has started the optimizer.
3974
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
3975
  if ( ! $auto && ( empty( $_REQUEST['ewww_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) ) {
3976
  $output['error'] = esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' );
3977
  echo json_encode( $output );
3978
- die();
3979
  }
3980
  session_write_close();
3981
  if ( ! empty( $_REQUEST['ewww_wpnonce'] ) ) {
@@ -3998,7 +4186,7 @@ function ewww_image_optimizer_aux_images_loop( $attachment = null, $auto = false
3998
  if ( empty( $attachment ) ) {
3999
  list( $id, $attachment ) = $ewwwdb->get_row( "SELECT id,path FROM $ewwwdb->ewwwio_images WHERE pending=1 LIMIT 1", ARRAY_N );
4000
  } else {
4001
- $id = $attachment['id'];
4002
  $attachment = $attachment['path'];
4003
  }
4004
  if ( $attachment ) {
@@ -4026,7 +4214,7 @@ function ewww_image_optimizer_aux_images_loop( $attachment = null, $auto = false
4026
  if ( $cli ) {
4027
  WP_CLI::error( __( 'License Exceeded', 'ewww-image-optimizer' ) );
4028
  }
4029
- die();
4030
  }
4031
  if ( ! $auto ) {
4032
  // Output the path.
@@ -4046,12 +4234,12 @@ function ewww_image_optimizer_aux_images_loop( $attachment = null, $auto = false
4046
  }
4047
  $next_file = ewww_image_optimizer_relative_path_replace( $wpdb->get_var( "SELECT path FROM $wpdb->ewwwio_images WHERE pending=1 LIMIT 1" ) );
4048
  if ( ! empty( $next_file ) ) {
4049
- $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
4050
  $output['next_file'] = '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . ' <b>' . esc_html( $next_file ) . "</b>&nbsp;<img src='$loading_image' alt='loading'/></p>";
4051
  }
4052
  echo json_encode( $output );
4053
  ewwwio_memory( __FUNCTION__ );
4054
- die();
4055
  }
4056
  if ( $cli ) {
4057
  return $results[1];
@@ -4072,7 +4260,7 @@ function ewww_image_optimizer_aux_images_loop( $attachment = null, $auto = false
4072
  function ewww_image_optimizer_hidpi_optimize( $orig_path, $return_path = false, $validate_file = true ) {
4073
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
4074
  $hidpi_suffix = apply_filters( 'ewww_image_optimizer_hidpi_suffix', '@2x' );
4075
- $pathinfo = pathinfo( $orig_path );
4076
  if ( empty( $pathinfo['dirname'] ) || empty( $pathinfo['filename'] ) || empty( $pathinfo['extension'] ) ) {
4077
  return;
4078
  }
@@ -4086,15 +4274,15 @@ function ewww_image_optimizer_hidpi_optimize( $orig_path, $return_path = false,
4086
  }
4087
  global $ewww_image;
4088
  if ( is_object( $ewww_image ) && $ewww_image instanceof EWWW_Image ) {
4089
- $id = $ewww_image->attachment_id;
4090
  $gallery = 'media';
4091
- $size = $ewww_image->resize;
4092
  } else {
4093
- $id = 0;
4094
  $gallery = '';
4095
- $size = null;
4096
  }
4097
- $ewww_image = new EWWW_Image( $id, $gallery, $hidpi_path );
4098
  $ewww_image->resize = $size . '-retina';
4099
  ewww_image_optimizer( $hidpi_path );
4100
  }
@@ -4131,7 +4319,7 @@ function ewww_image_optimizer_remote_fetch( $id, $meta ) {
4131
  $disabled_sizes = get_option( 'ewww_image_optimizer_disable_resizes_opt' );
4132
  ewwwio_debug_message( 'retrieving resizes' );
4133
  // Meta sizes don't contain a path, so we calculate one.
4134
- $base_dir = trailingslashit( dirname( $filename ) );
4135
  $processed = array();
4136
  foreach ( $meta['sizes'] as $size => $data ) {
4137
  ewwwio_debug_message( "processing size: $size" );
@@ -4156,7 +4344,7 @@ function ewww_image_optimizer_remote_fetch( $id, $meta ) {
4156
  // If this is a unique size.
4157
  if ( ! $dup_size ) {
4158
  $resize_path = $base_dir . $data['file'];
4159
- $resize_url = $as3cf->get_attachment_url( $id, null, $size, $meta );
4160
  ewwwio_debug_message( "fetching $resize_url to $resize_path" );
4161
  $temp_file = download_url( $resize_url );
4162
  if ( ! is_wp_error( $temp_file ) ) {
@@ -4164,7 +4352,7 @@ function ewww_image_optimizer_remote_fetch( $id, $meta ) {
4164
  }
4165
  }
4166
  // Store info on the sizes we've processed, so we can check the list for duplicate sizes.
4167
- $processed[ $size ]['width'] = $data['width'];
4168
  $processed[ $size ]['height'] = $data['height'];
4169
  }
4170
  } // End if().
@@ -4210,7 +4398,7 @@ function ewww_image_optimizer_remote_fetch( $id, $meta ) {
4210
  // If this is a unique size.
4211
  if ( ! $dup_size ) {
4212
  $resize_path = $base_dir . $data['file'];
4213
- $resize_url = $base_url . $data['file'];
4214
  ewwwio_debug_message( "fetching $resize_url to $resize_path" );
4215
  $temp_file = download_url( $resize_url );
4216
  if ( ! is_wp_error( $temp_file ) ) {
@@ -4218,11 +4406,12 @@ function ewww_image_optimizer_remote_fetch( $id, $meta ) {
4218
  }
4219
  }
4220
  // Store info on the sizes we've processed, so we can check the list for duplicate sizes.
4221
- $processed[ $size ]['width'] = $data['width'];
4222
  $processed[ $size ]['height'] = $data['height'];
4223
  }
4224
  } // End if().
4225
  } // End if().
 
4226
  if ( ! empty( $filename ) && is_file( $filename ) ) {
4227
  return $filename;
4228
  } else {
@@ -4250,7 +4439,7 @@ function ewww_image_optimizer_check_table_as3cf( $meta, $id, $s3_path ) {
4250
  ewwwio_debug_message( 'updating s3 resizes' );
4251
  // Meta sizes don't contain a path, so we calculate one.
4252
  $local_dir = trailingslashit( dirname( $local_path ) );
4253
- $s3_dir = trailingslashit( dirname( $s3_path ) );
4254
  $processed = array();
4255
  foreach ( $meta['sizes'] as $size => $data ) {
4256
  if ( strpos( $size, 'webp' ) === 0 ) {
@@ -4266,12 +4455,12 @@ function ewww_image_optimizer_check_table_as3cf( $meta, $id, $s3_path ) {
4266
  }
4267
  // If this is a unique size.
4268
  $local_resize_path = $local_dir . $data['file'];
4269
- $s3_resize_path = $s3_dir . $data['file'];
4270
  if ( $local_resize_path !== $s3_resize_path ) {
4271
  ewww_image_optimizer_update_table_as3cf( $local_resize_path, $s3_resize_path );
4272
  }
4273
  // Store info on the sizes we've processed, so we can check the list for duplicate sizes.
4274
- $processed[ $size ]['width'] = $data['width'];
4275
  $processed[ $size ]['height'] = $data['height'];
4276
  }
4277
  }
@@ -4320,7 +4509,7 @@ function ewww_image_optimizer_update_table_as3cf( $local_path, $s3_path ) {
4320
  $ewwwdb->update( $ewwwdb->ewwwio_images,
4321
  array(
4322
  'orig_size' => $s3_image['orig_size'],
4323
- 'results' => $s3_image['results'],
4324
  ),
4325
  array(
4326
  'id' => $found_local_image['id'],
@@ -4390,8 +4579,8 @@ function ewww_image_optimizer_autorotate( $file ) {
4390
  $jpeg = new PelJpeg( $file );
4391
  $exif = $jpeg->getExif();
4392
  if ( null != $exif ) {
4393
- $tiff = $exif->getTiff();
4394
- $ifd0 = $tiff->getIfd();
4395
  $orientation = $ifd0->getEntry( PelTag::ORIENTATION );
4396
  if ( null != $orientation ) {
4397
  ewwwio_debug_message( 'orientation being adjusted' );
@@ -4424,11 +4613,11 @@ function ewww_image_optimizer_resize_upload( $file ) {
4424
  wp_raise_memory_limit( 'image' );
4425
  }
4426
  if ( ! empty( $_REQUEST['post_id'] ) || ( ! empty( $_REQUEST['action'] ) && 'upload-attachment' === $_REQUEST['action'] ) || ( ! empty( $_SERVER['HTTP_REFERER'] ) && strpos( $_SERVER['HTTP_REFERER'], 'media-new.php' ) ) ) {
4427
- $maxwidth = ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' );
4428
  $maxheight = ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' );
4429
  ewwwio_debug_message( 'resizing image from media library or attached to post' );
4430
  } else {
4431
- $maxwidth = ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherwidth' );
4432
  $maxheight = ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherheight' );
4433
  ewwwio_debug_message( 'resizing images from somewhere else' );
4434
  }
@@ -4450,7 +4639,7 @@ function ewww_image_optimizer_resize_upload( $file ) {
4450
  if ( 0 == $maxwidth && 0 == $maxheight ) {
4451
  return false;
4452
  }
4453
- $maxwidth = $maxwidth ? $maxwidth : 999999;
4454
  $maxheight = $maxheight ? $maxheight : 999999;
4455
  // Check the file type.
4456
  $type = ewww_image_optimizer_mimetype( $file, 'i' );
@@ -4469,8 +4658,8 @@ function ewww_image_optimizer_resize_upload( $file ) {
4469
  }
4470
  $crop = false;
4471
  if ( $oldwidth > $maxwidth && $maxwidth && $oldheight > $maxheight && $maxheight && apply_filters( 'ewww_image_optimizer_crop_image', false ) ) {
4472
- $crop = true;
4473
- $newwidth = $maxwidth;
4474
  $newheight = $maxheight;
4475
  } else {
4476
  list( $newwidth, $newheight ) = wp_constrain_dimensions( $oldwidth, $oldheight, $maxwidth, $maxheight );
@@ -4488,15 +4677,17 @@ function ewww_image_optimizer_resize_upload( $file ) {
4488
  ewwwio_debug_message( 'no image editor function' );
4489
  return false;
4490
  }
 
 
4491
  remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
4492
  $editor = wp_get_image_editor( $file );
4493
  if ( is_wp_error( $editor ) ) {
4494
  ewwwio_debug_message( 'could not get image editor' );
4495
  return false;
4496
  }
4497
- // Rotation should not happen here anymore, so don't worry about it breaking the dimensions.
4498
  $orientation = ewww_image_optimizer_get_orientation( $file, $type );
4499
- $rotated = false;
4500
  switch ( $orientation ) {
4501
  case 3:
4502
  $editor->rotate( 180 );
@@ -4505,16 +4696,16 @@ function ewww_image_optimizer_resize_upload( $file ) {
4505
  case 6:
4506
  $editor->rotate( -90 );
4507
  $new_newwidth = $newwidth;
4508
- $newwidth = $newheight;
4509
- $newheight = $new_newwidth;
4510
- $rotated = true;
4511
  break;
4512
  case 8:
4513
  $editor->rotate( 90 );
4514
  $new_newwidth = $newwidth;
4515
- $newwidth = $newheight;
4516
- $newheight = $new_newwidth;
4517
- $rotated = true;
4518
  break;
4519
  }
4520
  $resized_image = $editor->resize( $newwidth, $newheight, $crop );
@@ -4522,7 +4713,7 @@ function ewww_image_optimizer_resize_upload( $file ) {
4522
  ewwwio_debug_message( 'error during resizing' );
4523
  return false;
4524
  }
4525
- $new_file = $editor->generate_filename( 'tmp' );
4526
  $orig_size = filesize( $file );
4527
  ewwwio_debug_message( "before resizing: $orig_size" );
4528
  $saved = $editor->save( $new_file );
@@ -4530,6 +4721,7 @@ function ewww_image_optimizer_resize_upload( $file ) {
4530
  ewwwio_debug_message( 'error saving resized image' );
4531
  }
4532
  add_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
 
4533
  $new_size = ewww_image_optimizer_filesize( $new_file );
4534
  if ( $new_size && $new_size < $orig_size ) {
4535
  // Use this action to perform any operations on the original file before it is overwritten with the new, smaller file.
@@ -4538,13 +4730,14 @@ function ewww_image_optimizer_resize_upload( $file ) {
4538
  // TODO: see if there is a way to just check that meta exists on the new image.
4539
  // 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.
4540
  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() ) {
 
4541
  $old_jpeg = new PelJpeg( $file );
4542
  $old_exif = $old_jpeg->getExif();
4543
  $new_jpeg = new PelJpeg( $new_file );
4544
  if ( null != $old_exif ) {
4545
  if ( $rotated ) {
4546
- $tiff = $old_exif->getTiff();
4547
- $ifd0 = $tiff->getIfd();
4548
  $orientation = $ifd0->getEntry( PelTag::ORIENTATION );
4549
  if ( null != $orientation ) {
4550
  $orientation->setValue( 1 );
@@ -4568,7 +4761,7 @@ function ewww_image_optimizer_resize_upload( $file ) {
4568
  if ( empty( $already_optimized ) ) {
4569
  $tmp_exists = $ewwwdb->update( $ewwwdb->ewwwio_images,
4570
  array(
4571
- 'path' => ewww_image_optimizer_relative_path_remove( $file ),
4572
  'orig_size' => $orig_size,
4573
  ),
4574
  array(
@@ -4578,7 +4771,7 @@ function ewww_image_optimizer_resize_upload( $file ) {
4578
  // If the tmp file didn't get optimized (and it shouldn't), then just insert a dummy record to be updated shortly.
4579
  if ( ! $tmp_exists ) {
4580
  $ewwwdb->insert( $ewwwdb->ewwwio_images, array(
4581
- 'path' => ewww_image_optimizer_relative_path_remove( $file ),
4582
  'orig_size' => $orig_size,
4583
  ) );
4584
  }
@@ -4647,8 +4840,8 @@ function ewww_image_optimizer_find_already_optimized( $attachment ) {
4647
  $ewwwdb = $wpdb;
4648
  }
4649
  $maybe_return_image = false;
4650
- $query = $ewwwdb->prepare( "SELECT * FROM $ewwwdb->ewwwio_images WHERE path = %s", ewww_image_optimizer_relative_path_remove( $attachment ) );
4651
- $optimized_query = $ewwwdb->get_results( $query, ARRAY_A );
4652
  if ( ewww_image_optimizer_iterable( $optimized_query ) ) {
4653
  foreach ( $optimized_query as $image ) {
4654
  $image['path'] = ewww_image_optimizer_relative_path_replace( $image['path'] );
@@ -4699,13 +4892,13 @@ function ewww_image_optimizer_remove_duplicate_records( $duplicates ) {
4699
  if ( ! is_array( $duplicates[0] ) ) {
4700
  // Retrieve records for the ID #s passed.
4701
  $duplicate_ids = implode( ',', array_map( 'intval', $duplicates ) );
4702
- $duplicates = $ewwwdb->get_results( "SELECT * FROM $ewwwdb->ewwwio_images WHERE id IN ($duplicate_ids)" ); // WPCS: unprepared SQL ok.
4703
  }
4704
  if ( ! is_array( $duplicates ) || ! is_array( $duplicates[0] ) ) {
4705
  return false;
4706
  }
4707
  $image_size = ewww_image_optimizer_filesize( $duplicates[0]['path'] );
4708
- $discard = array();
4709
  // First look for an image size match.
4710
  foreach ( $duplicates as $duplicate ) {
4711
  if ( empty( $keeper ) && ! empty( $duplicate['image_size'] ) && $image_size == $duplicate['image_size'] ) {
@@ -4727,7 +4920,7 @@ function ewww_image_optimizer_remove_duplicate_records( $duplicates ) {
4727
  }
4728
  // If we still have nothing, mark the 0 record as the primary and pull it off the stack.
4729
  if ( empty( $keeper ) ) {
4730
- $keeper = array_shift( $duplicates );
4731
  $discard = $duplicates;
4732
  }
4733
  if ( is_array( $keeper ) && is_array( $discard ) ) {
@@ -4953,7 +5146,7 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
4953
  }
4954
  }
4955
  ewwwio_debug_message( "retrieved file path: $file_path" );
4956
- $type = ewww_image_optimizer_mimetype( $file_path, 'i' );
4957
  $supported_types = array(
4958
  'image/jpeg',
4959
  'image/png',
@@ -4970,20 +5163,20 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
4970
  list( $maxw, $maxh ) = imsanity_get_max_width_height( IMSANITY_SOURCE_LIBRARY );
4971
  list( $oldw, $oldh ) = getimagesize( $file_path );
4972
  list( $neww, $newh ) = wp_constrain_dimensions( $oldw, $oldh, $maxw, $maxh );
4973
- $path_parts = pathinfo( $file_path );
4974
- $imsanity_path = trailingslashit( $path_parts['dirname'] ) . $path_parts['filename'] . '-' . $neww . 'x' . $newh . '.' . $path_parts['extension'];
4975
  ewwwio_debug_message( "imsanity path: $imsanity_path" );
4976
- $image_size = ewww_image_optimizer_filesize( $file_path );
4977
  $already_optimized = ewww_image_optimizer_find_already_optimized( $imsanity_path );
4978
  if ( is_array( $already_optimized ) ) {
4979
  ewwwio_debug_message( "updating existing record, path: $file_path, size: " . $image_size );
4980
  // Store info on the current image for future reference.
4981
  $ewwwdb->update( $ewwwdb->ewwwio_images,
4982
  array(
4983
- 'path' => ewww_image_optimizer_relative_path_remove( $file_path ),
4984
  'attachment_id' => $id,
4985
- 'resize' => 'full',
4986
- 'gallery' => 'media',
4987
  ),
4988
  array(
4989
  'id' => $already_optimized['id'],
@@ -4995,7 +5188,7 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
4995
  if ( ( empty( $new_image ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' ) ) && ! function_exists( 'imsanity_get_max_width_height' ) ) {
4996
  $new_dimensions = ewww_image_optimizer_resize_upload( $file_path );
4997
  if ( is_array( $new_dimensions ) ) {
4998
- $meta['width'] = $new_dimensions[0];
4999
  $meta['height'] = $new_dimensions[1];
5000
  }
5001
  }
@@ -5014,8 +5207,8 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5014
  }
5015
  ewwwio_debug_message( "backgrounding optimization for $id" );
5016
  $ewwwio_media_background->push_to_queue( array(
5017
- 'id' => $id,
5018
- 'new' => $new_image,
5019
  'type' => $type,
5020
  ) );
5021
  $ewwwio_media_background->save()->dispatch();
@@ -5032,7 +5225,7 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5032
  if ( apply_filters( 'ewww_image_optimizer_defer_resizing', false ) && ( ! empty( $new_image ) || ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' ) ) && ! function_exists( 'imsanity_get_max_width_height' ) ) {
5033
  $new_dimensions = ewww_image_optimizer_resize_upload( $file_path );
5034
  if ( is_array( $new_dimensions ) ) {
5035
- $meta['width'] = $new_dimensions[0];
5036
  $meta['height'] = $new_dimensions[1];
5037
  }
5038
  }
@@ -5057,8 +5250,10 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5057
  $ewwwio_async_optimize_media = new EWWWIO_Async_Request();
5058
  }
5059
  } else {
5060
- $ewww_image = new EWWW_Image( $id, 'media', $file_path );
5061
  $ewww_image->resize = 'full';
 
 
5062
  list( $file, $msg, $conv, $original ) = ewww_image_optimizer( $file_path, $gallery_type, false, $new_image, true );
5063
 
5064
  if ( false === $file ) {
@@ -5069,9 +5264,9 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5069
  if ( $conv ) {
5070
  $ewww_image->increment = $conv;
5071
  }
5072
- $ewww_image->file = $file;
5073
  $ewww_image->converted = $original;
5074
- $meta['file'] = trailingslashit( dirname( $meta['file'] ) ) . basename( $file );
5075
  $ewww_image->update_converted_attachment( $meta );
5076
  $meta = $ewww_image->convert_sizes( $meta );
5077
  ewwwio_debug_message( 'image was converted' );
@@ -5107,13 +5302,13 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5107
  }
5108
  if ( 6 === $gallery_type ) {
5109
  // We reset base_dir, because base_dir potentially gets overwritten with base_ims_dir.
5110
- $base_dir = trailingslashit( dirname( $file_path ) );
5111
  $image_path = $base_dir . $data['file'];
5112
- $ims_path = $base_ims_dir . $data['file'];
5113
  if ( is_file( $ims_path ) ) {
5114
  ewwwio_debug_message( 'ims resize already exists, wahoo' );
5115
  ewwwio_debug_message( "ims path: $ims_path" );
5116
- $image_size = ewww_image_optimizer_filesize( $ims_path );
5117
  $already_optimized = ewww_image_optimizer_find_already_optimized( $image_path );
5118
  if ( is_array( $already_optimized ) ) {
5119
  ewwwio_debug_message( "updating existing record, path: $ims_path, size: " . $image_size );
@@ -5146,12 +5341,12 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5146
  $size = 'pdf-full';
5147
  ewwwio_debug_message( 'processing full size pdf preview' );
5148
  }
5149
- // Run the optimization and store the results.
5150
  if ( $parallel_opt && is_file( $resize_path ) ) {
5151
  $parallel_sizes[ $size ] = $resize_path;
5152
  } else {
5153
- $ewww_image = new EWWW_Image( $id, 'media', $resize_path );
5154
  $ewww_image->resize = $size;
 
5155
  list( $optimized_file, $results, $resize_conv, $original ) = ewww_image_optimizer( $resize_path );
5156
  }
5157
  // Optimize retina images, if they exist.
@@ -5165,14 +5360,14 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5165
  $async_path = str_replace( $upload_path, '', $retina_path );
5166
  $ewwwio_async_optimize_media->data(
5167
  array(
5168
- 'ewwwio_id' => $id,
5169
  'ewwwio_path' => $async_path,
5170
  'ewwwio_size' => '',
5171
- 'ewww_force' => $force,
5172
  )
5173
  )->dispatch();
5174
  } else {
5175
- $ewww_image = new EWWW_Image( $id, 'media', $retina_path );
5176
  $ewww_image->resize = $size . '-retina';
5177
  ewww_image_optimizer( $retina_path );
5178
  }
@@ -5180,7 +5375,7 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5180
  ewww_image_optimizer_hidpi_optimize( $resize_path );
5181
  }
5182
  // Store info on the sizes we've processed, so we can check the list for duplicate sizes.
5183
- $processed[ $size ]['width'] = $data['width'];
5184
  $processed[ $size ]['height'] = $data['height'];
5185
  } // End foreach().
5186
  } // End if().
@@ -5188,17 +5383,17 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5188
  // Process size from a custom theme.
5189
  if ( isset( $meta['image_meta']['resized_images'] ) && ewww_image_optimizer_iterable( $meta['image_meta']['resized_images'] ) ) {
5190
  $imagemeta_resize_pathinfo = pathinfo( $file_path );
5191
- $imagemeta_resize_path = '';
5192
  foreach ( $meta['image_meta']['resized_images'] as $imagemeta_resize ) {
5193
  $imagemeta_resize_path = $imagemeta_resize_pathinfo['dirname'] . '/' . $imagemeta_resize_pathinfo['filename'] . '-' . $imagemeta_resize . '.' . $imagemeta_resize_pathinfo['extension'];
5194
  if ( $parallel_opt && is_file( $imagemeta_resize_path ) ) {
5195
  $async_path = str_replace( $upload_path, '', $imagemeta_resize_path );
5196
  $ewwwio_async_optimize_media->data(
5197
  array(
5198
- 'ewwwio_id' => $id,
5199
  'ewwwio_path' => $async_path,
5200
  'ewwwio_size' => '',
5201
- 'ewww_force' => $force,
5202
  )
5203
  )->dispatch();
5204
  } else {
@@ -5211,17 +5406,17 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5211
  // And another custom theme.
5212
  if ( isset( $meta['custom_sizes'] ) && ewww_image_optimizer_iterable( $meta['custom_sizes'] ) ) {
5213
  $custom_sizes_pathinfo = pathinfo( $file_path );
5214
- $custom_size_path = '';
5215
  foreach ( $meta['custom_sizes'] as $custom_size ) {
5216
  $custom_size_path = $custom_sizes_pathinfo['dirname'] . '/' . $custom_size['file'];
5217
  if ( $parallel_opt && file_exists( $custom_size_path ) ) {
5218
  $async_path = str_replace( $upload_path, '', $custom_size_path );
5219
  $ewwwio_async_optimize_media->data(
5220
  array(
5221
- 'ewwwio_id' => $id,
5222
  'ewwwio_path' => $async_path,
5223
  'ewwwio_size' => '',
5224
- 'ewww_force' => $force,
5225
  )
5226
  )->dispatch();
5227
  } else {
@@ -5232,11 +5427,11 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5232
  }
5233
 
5234
  if ( $parallel_opt && count( $parallel_sizes ) > 0 ) {
5235
- $max_threads = (int) apply_filters( 'ewww_image_optimizer_max_parallel_threads', 5 );
5236
- $processing = true;
5237
- $timer = (int) apply_filters( 'ewww_image_optimizer_background_timer_init', 1 );
5238
- $increment = (int) apply_filters( 'ewww_image_optimizer_background_timer_increment', 1 );
5239
- $timer_max = (int) apply_filters( 'ewww_image_optimizer_background_timer_max', 20 );
5240
  $processing_sizes = array();
5241
  if ( ! empty( $_REQUEST['ewww_force'] ) ) {
5242
  $force = true;
@@ -5270,10 +5465,10 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5270
  ewwwio_debug_message( "sending off $async_path in folder $upload_path" );
5271
  $ewwwio_async_optimize_media->data(
5272
  array(
5273
- 'ewwwio_id' => $id,
5274
  'ewwwio_path' => $async_path,
5275
  'ewwwio_size' => $size,
5276
- 'ewww_force' => $force,
5277
  )
5278
  )->dispatch();
5279
  $threads--;
@@ -5326,7 +5521,7 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5326
  unset( $meta['processing'] );
5327
 
5328
  global $ewww_attachment;
5329
- $ewww_attachment['id'] = $id;
5330
  $ewww_attachment['meta'] = $meta;
5331
  add_filter( 'w3tc_cdn_update_attachment_metadata', 'ewww_image_optimizer_w3tc_update_files' );
5332
 
@@ -5364,12 +5559,12 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
5364
  // Register the attachment in the database as a cloudinary attachment.
5365
  $old_url = wp_get_attachment_url( $id );
5366
  wp_update_post( array(
5367
- 'ID' => $id,
5368
  'guid' => $result['url'],
5369
  ) );
5370
  update_attached_file( $id, $result['url'] );
5371
  $meta['cloudinary'] = true;
5372
- $errors = array();
5373
  // Update the image location for the attachment.
5374
  CloudinaryPlugin::update_image_src_all( $id, $result, $old_url, $result['url'], true, $errors );
5375
  if ( count( $errors ) > 0 ) {
@@ -5399,7 +5594,7 @@ function ewww_image_optimizer_detect_wpsf_location_lock() {
5399
  if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
5400
  ewwwio_debug_message( print_r( $shield_user_man, true ) );
5401
  }
5402
- if ( 'Y' == $shield_user_man['session_lock_location'] ) {
5403
  return true;
5404
  }
5405
  }
@@ -5434,7 +5629,7 @@ function ewww_image_optimizer_update_attachment( $meta, $id ) {
5434
  return $meta;
5435
  }
5436
  // Retrieve any posts that link the image.
5437
- $esql = $wpdb->prepare( "SELECT ID, post_content FROM $wpdb->posts WHERE post_content LIKE '%%%s%%'", $old_guid );
5438
  ewwwio_debug_message( "using query: $esql" );
5439
  // While there are posts to process.
5440
  $rows = $wpdb->get_results( $esql, ARRAY_A ); // WPCS: unprepared SQL ok.
@@ -5477,7 +5672,7 @@ function ewww_image_optimizer_update_attachment( $meta, $id ) {
5477
  continue;
5478
  }
5479
  // Retrieve any posts that link the resize.
5480
- $rows = $wpdb->get_results( $wpdb->prepare( "SELECT ID, post_content FROM $wpdb->posts WHERE post_content LIKE '%%%s%%'", $old_sguid ), ARRAY_A );
5481
  // While there are posts to process.
5482
  if ( ewww_image_optimizer_iterable( $rows ) ) {
5483
  foreach ( $rows as $row ) {
@@ -5510,7 +5705,7 @@ function ewww_image_optimizer_update_attachment( $meta, $id ) {
5510
  }
5511
  // Update the attachment post with the new mimetype and id.
5512
  wp_update_post( array(
5513
- 'ID' => $id,
5514
  'post_mime_type' => $mime,
5515
  ) );
5516
  ewww_image_optimizer_debug_log();
@@ -5536,14 +5731,14 @@ function ewww_image_optimizer_attachment_path( $meta, $id, $file = '', $refresh_
5536
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
5537
 
5538
  // Retrieve the location of the WordPress upload folder.
5539
- $upload_dir = wp_upload_dir( null, false, $refresh_cache );
5540
  $upload_path = trailingslashit( $upload_dir['basedir'] );
5541
  if ( ! $file ) {
5542
  $file = get_post_meta( $id, '_wp_attached_file', true );
5543
  } else {
5544
  ewwwio_debug_message( 'using prefetched _wp_attached_file' );
5545
  }
5546
- $file_path = ( 0 !== strpos( $file, '/' ) && ! preg_match( '|^.:\\\|', $file ) ? $upload_path . $file : $file );
5547
  $filtered_file_path = apply_filters( 'get_attached_file', $file_path, $id );
5548
  ewwwio_debug_message( "WP (filtered) thinks the file is at: $filtered_file_path" );
5549
  if ( ( strpos( $filtered_file_path, 's3' ) === false || in_array( 's3', stream_get_wrappers() ) ) && is_file( $filtered_file_path ) ) {
@@ -5557,16 +5752,16 @@ function ewww_image_optimizer_attachment_path( $meta, $id, $file = '', $refresh_
5557
  ewwwio_debug_message( "finding path for IMS image: $id " );
5558
  if ( is_dir( $file_path ) && is_file( $file_path . $meta['file'] ) ) {
5559
  // Generate the absolute path.
5560
- $file_path = $file_path . $meta['file'];
5561
  $upload_path = ewww_image_optimizer_upload_path( $file_path, $upload_path );
5562
  ewwwio_debug_message( "found path for IMS image: $file_path" );
5563
  } elseif ( is_file( $meta['file'] ) ) {
5564
- $file_path = $meta['file'];
5565
  $upload_path = ewww_image_optimizer_upload_path( $file_path, $upload_path );
5566
  ewwwio_debug_message( "found path for IMS image: $file_path" );
5567
  } else {
5568
  $upload_path = trailingslashit( WP_CONTENT_DIR );
5569
- $file_path = $upload_path . ltrim( $meta['file'], '/' );
5570
  ewwwio_debug_message( "checking path for IMS image: $file_path" );
5571
  if ( ! file_exists( $file_path ) ) {
5572
  $file_path = '';
@@ -5589,7 +5784,7 @@ function ewww_image_optimizer_attachment_path( $meta, $id, $file = '', $refresh_
5589
  return array( $file_path, $upload_path );
5590
  }
5591
  $upload_path = trailingslashit( WP_CONTENT_DIR ) . 'uploads/';
5592
- $file_path = $upload_path . $meta['file'];
5593
  ewwwio_debug_message( "one last shot, using the wp-content/ constant: $file_path" );
5594
  if ( is_file( $file_path ) ) {
5595
  return array( $file_path, $upload_path );
@@ -5723,7 +5918,7 @@ function ewww_image_optimizer_unique_filename( $file, $fileext ) {
5723
  $filenum = apply_filters( 'ewww_image_optimizer_converted_filename_suffix', 1 );
5724
  // But it must be only letters, numbers, or underscores.
5725
  $filenum = ( preg_match( '/^[\w\d]*$/', $filenum ) ? $filenum : 1 );
5726
- $suffix = ( ! empty( $filenum ) ? '-' . $filenum : '' );
5727
  // While a file exists with the current increment.
5728
  while ( file_exists( $filename . $suffix . $fileext ) ) {
5729
  // Increment the increment...
@@ -5789,7 +5984,7 @@ function ewww_image_optimizer_png_alpha( $filename ) {
5789
  for ( $y = 0; $y < $height; $y++ ) {
5790
  for ( $x = 0; $x < $width; $x++ ) {
5791
  $color = imagecolorat( $image, $x, $y );
5792
- $rgb = imagecolorsforindex( $image, $color );
5793
  if ( $rgb['alpha'] > 0 ) {
5794
  ewwwio_debug_message( 'transparency found' );
5795
  return true;
@@ -5821,7 +6016,7 @@ function ewww_image_optimizer_is_animated( $filename ) {
5821
  $count = 0;
5822
  // We read through the file til we reach the end of the file, or we've found at least 2 frame headers.
5823
  while ( ! feof( $fh ) && $count < 2 ) {
5824
- $chunk = fread( $fh, 1024 * 100 ); // Read 100kb at a time.
5825
  $count += preg_match_all( '#\x00\x21\xF9\x04.{4}\x00(\x2C|\x21)#s', $chunk, $matches );
5826
  }
5827
  fclose( $fh );
@@ -5841,7 +6036,7 @@ function ewww_image_optimizer_resize_count( $sizes ) {
5841
  return 0;
5842
  }
5843
  $size_count = 0;
5844
- $processed = array();
5845
  foreach ( $sizes as $size => $data ) {
5846
  if ( strpos( $size, 'webp' ) === 0 ) {
5847
  continue;
@@ -5859,7 +6054,7 @@ function ewww_image_optimizer_resize_count( $sizes ) {
5859
  // If this is a unique size.
5860
  $size_count++;
5861
  // Sore info on the sizes we've processed, so we can check the list for duplicate sizes.
5862
- $processed[ $size ]['width'] = $data['width'];
5863
  $processed[ $size ]['height'] = $data['height'];
5864
  }
5865
  return $size_count;
@@ -5901,9 +6096,9 @@ function ewww_image_optimizer_custom_column( $column_name, $id, $meta = null, $r
5901
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) && ! $return_output && ewww_image_optimizer_function_exists( 'print_r' ) ) {
5902
  $print_meta = print_r( $meta, true );
5903
  $print_meta = preg_replace( array( '/ /', '/\n+/' ), array( '&nbsp;', '<br />' ), $print_meta );
5904
- $output .= '<div style="background-color:#ffff99;font-size: 10px;padding: 10px;margin:-10px -10px 10px;line-height: 1.1em">' . $print_meta . '</div>';
5905
  }
5906
- $output .= "<div id='ewww-media-status-$id'>";
5907
  $ewww_cdn = false;
5908
  if ( is_array( $meta ) && ! empty( $meta['cloudinary'] ) ) {
5909
  $output .= esc_html__( 'Cloudinary image', 'ewww-image-optimizer' ) . '</div>';
@@ -5914,15 +6109,15 @@ function ewww_image_optimizer_custom_column( $column_name, $id, $meta = null, $r
5914
  return;
5915
  }
5916
  if ( is_array( $meta ) & class_exists( 'WindowsAzureStorageUtil' ) && ! empty( $meta['url'] ) ) {
5917
- $output .= '<div>' . esc_html__( 'Azure Storage image', 'ewww-image-optimizer' ) . '</div>';
5918
  $ewww_cdn = true;
5919
  }
5920
  if ( is_array( $meta ) && class_exists( 'Amazon_S3_And_CloudFront' ) && preg_match( '/^(http|s3)\w*:/', get_attached_file( $id ) ) ) {
5921
- $output .= '<div>' . esc_html__( 'Amazon S3 image', 'ewww-image-optimizer' ) . '</div>';
5922
  $ewww_cdn = true;
5923
  }
5924
  if ( is_array( $meta ) && class_exists( 'S3_Uploads' ) && preg_match( '/^(http|s3)\w*:/', get_attached_file( $id ) ) ) {
5925
- $output .= '<div>' . esc_html__( 'Amazon S3 image', 'ewww-image-optimizer' ) . '</div>';
5926
  $ewww_cdn = true;
5927
  }
5928
  list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
@@ -5939,7 +6134,7 @@ function ewww_image_optimizer_custom_column( $column_name, $id, $meta = null, $r
5939
  if ( is_array( $meta ) && ( ! empty( $meta['ewww_image_optimizer'] ) || ! empty( $meta['converted'] ) ) ) {
5940
  $meta = ewww_image_optimizer_migrate_meta_to_db( $id, $meta );
5941
  }
5942
- $msg = '';
5943
  $convert_desc = '';
5944
  $convert_link = '';
5945
  if ( $ewww_cdn ) {
@@ -6027,26 +6222,26 @@ function ewww_image_optimizer_custom_column( $column_name, $id, $meta = null, $r
6027
  }
6028
  $ewww_manual_nonce = wp_create_nonce( 'ewww-manual' );
6029
  global $wpdb;
6030
- $in_progress = false;
6031
- $migrated = false;
6032
  $optimized_images = false;
6033
  $backup_available = false;
6034
- $file_parts = pathinfo( $file_path );
6035
- $basename = $file_parts['filename'];
6036
  // If necessary, use get_post_meta( $post_id, '_wp_attachment_backup_sizes', true ); to only use basename for edited attachments, but that requires extra queries, so kiss for now.
6037
  if ( $ewww_cdn ) {
6038
  if ( get_transient( 'ewwwio-background-in-progress-' . $id ) ) {
6039
- $output .= '<div>' . esc_html__( 'In Progress', 'ewww-image-optimizer' ) . '</div>';
6040
  $in_progress = true;
6041
  }
6042
  if ( ! $in_progress ) {
6043
- $optimized_images = $wpdb->get_results( $wpdb->prepare( "SELECT image_size,orig_size,resize,converted,level,backup,updated FROM $wpdb->ewwwio_images WHERE attachment_id = %d AND gallery = 'media' AND image_size <> 0 AND path LIKE '%%%s%%' ORDER BY orig_size DESC", $id, $basename ), ARRAY_A );
6044
  if ( ! $optimized_images ) {
6045
  // Attempt migration, but only if the original image is in the db, $migrated will be metadata on success, false on failure.
6046
  $migrated = ewww_image_optimizer_migrate_meta_to_db( $id, $meta, true );
6047
  }
6048
  if ( $migrated ) {
6049
- $optimized_images = $wpdb->get_results( $wpdb->prepare( "SELECT image_size,orig_size,resize,converted,level,backup,updated FROM $wpdb->ewwwio_images WHERE attachment_id = %d AND gallery = 'media' AND image_size <> 0 AND path LIKE '%%%s%%' ORDER BY orig_size DESC", $id, $basename ), ARRAY_A );
6050
  }
6051
  }
6052
  // If optimizer data exists in the db.
@@ -6072,7 +6267,7 @@ function ewww_image_optimizer_custom_column( $column_name, $id, $meta = null, $r
6072
  // Give the user the option to optimize the image right now.
6073
  if ( isset( $meta['sizes'] ) && ewww_image_optimizer_iterable( $meta['sizes'] ) ) {
6074
  $sizes_to_opt = ewww_image_optimizer_count_unoptimized_sizes( $meta['sizes'] ) + 1;
6075
- $output .= '<div>' . sprintf( esc_html(
6076
  /* translators: %d: The number of resize/thumbnail images */
6077
  _n( '%d size to compress', '%d sizes to compress', $sizes_to_opt, 'ewww-image-optimizer' )
6078
  ), $sizes_to_opt ) . '</div>';
@@ -6088,17 +6283,17 @@ function ewww_image_optimizer_custom_column( $column_name, $id, $meta = null, $r
6088
  } // End if().
6089
  // End of output for CDN images.
6090
  if ( get_transient( 'ewwwio-background-in-progress-' . $id ) ) {
6091
- $output .= esc_html__( 'In Progress', 'ewww-image-optimizer' );
6092
  $in_progress = true;
6093
  }
6094
  if ( ! $in_progress ) {
6095
- $optimized_images = $wpdb->get_results( $wpdb->prepare( "SELECT image_size,orig_size,resize,converted,level,backup,updated FROM $wpdb->ewwwio_images WHERE attachment_id = %d AND gallery = 'media' AND image_size <> 0 AND path LIKE '%%%s%%' ORDER BY orig_size DESC", $id, $basename ), ARRAY_A );
6096
  if ( ! $optimized_images ) {
6097
  // Attempt migration, but only if the original image is in the db, $migrated will be metadata on success, false on failure.
6098
  $migrated = ewww_image_optimizer_migrate_meta_to_db( $id, $meta, true );
6099
  }
6100
  if ( $migrated ) {
6101
- $optimized_images = $wpdb->get_results( $wpdb->prepare( "SELECT image_size,orig_size,resize,converted,level,backup,updated FROM $wpdb->ewwwio_images WHERE attachment_id = %d AND gallery = 'media' AND image_size <> 0 AND path LIKE '%%%s%%' ORDER BY orig_size DESC", $id, $basename ), ARRAY_A );
6102
  }
6103
  }
6104
  // If optimizer data exists.
@@ -6113,13 +6308,13 @@ function ewww_image_optimizer_custom_column( $column_name, $id, $meta = null, $r
6113
  }
6114
 
6115
  // Determine filepath for webp.
6116
- $webpfile = $file_path . '.webp';
6117
  $webp_size = ewww_image_optimizer_filesize( $webpfile );
6118
  if ( $webp_size ) {
6119
  // Get a human readable filesize.
6120
  $webp_size = ewww_image_optimizer_size_format( $webp_size );
6121
- $webpurl = esc_url( wp_get_attachment_url( $id ) . '.webp' );
6122
- $output .= "<div>WebP: <a href='$webpurl'>$webp_size</a></div>";
6123
  }
6124
 
6125
  if ( empty( $msg ) && current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
@@ -6154,7 +6349,7 @@ function ewww_image_optimizer_custom_column( $column_name, $id, $meta = null, $r
6154
  // Otherwise, this must be an image we haven't processed.
6155
  if ( isset( $meta['sizes'] ) && ewww_image_optimizer_iterable( $meta['sizes'] ) ) {
6156
  $sizes_to_opt = ewww_image_optimizer_count_unoptimized_sizes( $meta['sizes'] ) + 1;
6157
- $output .= '<div>' . sprintf( esc_html(
6158
  /* translators: %d: The number of resize/thumbnail images */
6159
  _n( '%d size to compress', '%d sizes to compress', $sizes_to_opt, 'ewww-image-optimizer' )
6160
  ), $sizes_to_opt ) . '</div>';
@@ -6200,7 +6395,7 @@ function ewww_image_optimizer_count_unoptimized_sizes( $sizes ) {
6200
  ewwwio_debug_message( 'unoptimized sizes cannot be counted' );
6201
  return 0;
6202
  }
6203
- $sizes_to_opt = 0;
6204
  $disabled_sizes = get_option( 'ewww_image_optimizer_disable_resizes_opt' );
6205
 
6206
  // To keep track of the ones we have already processed.
@@ -6231,7 +6426,7 @@ function ewww_image_optimizer_count_unoptimized_sizes( $sizes ) {
6231
  }
6232
  $sizes_to_opt++;
6233
  // Store info on the sizes we've processed, so we can check the list for duplicate sizes.
6234
- $processed[ $size ]['width'] = $data['width'];
6235
  $processed[ $size ]['height'] = $data['height'];
6236
  } // End foreach().
6237
  return $sizes_to_opt;
@@ -6254,22 +6449,22 @@ function ewww_image_optimizer_custom_column_results( $id, $optimized_images ) {
6254
  if ( empty( $id ) || empty( $optimized_images ) || ! is_array( $optimized_images ) ) {
6255
  return array( '', false, false );
6256
  }
6257
- $orig_size = 0;
6258
- $opt_size = 0;
6259
- $level = 0;
6260
- $converted = false;
6261
  $backup_available = false;
6262
- $sizes_to_opt = 0;
6263
- $output = '';
6264
- $detail_output = '<table class="striped"><tr><th>&nbsp;</th><th>' . esc_html__( 'Image Size', 'ewww-image-optimizer' ) . '</th><th>' . esc_html__( 'Savings', 'ewww-image-optimizer' ) . '</th></tr>';
6265
  foreach ( $optimized_images as $optimized_image ) {
6266
  if ( ! empty( $optimized_image['attachment_id'] ) ) {
6267
  $id = $optimized_image['attachment_id'];
6268
  }
6269
  $orig_size += $optimized_image['orig_size'];
6270
- $opt_size += $optimized_image['image_size'];
6271
  if ( 'full' == $optimized_image['resize'] ) {
6272
- $level = $optimized_image['level'];
6273
  $updated_time = strtotime( $optimized_image['updated'] );
6274
  if ( DAY_IN_SECONDS * 30 + $updated_time > time() ) {
6275
  $backup_available = $optimized_image['backup'];
@@ -6282,7 +6477,7 @@ function ewww_image_optimizer_custom_column_results( $id, $optimized_images ) {
6282
  }
6283
  $sizes_to_opt++;
6284
  if ( ! empty( $optimized_image['resize'] ) ) {
6285
- $display_size = ewww_image_optimizer_size_format( $optimized_image['image_size'] );
6286
  $detail_output .= '<tr><td><strong>' . ucfirst( $optimized_image['resize'] ) . "</strong></td><td>$display_size</td><td>" . esc_html( ewww_image_optimizer_image_results( $optimized_image['orig_size'], $optimized_image['image_size'] ) ) . '</td></tr>';
6287
  }
6288
  }
@@ -6292,10 +6487,10 @@ function ewww_image_optimizer_custom_column_results( $id, $optimized_images ) {
6292
  /* translators: %d: number of resizes/thumbnails compressed */
6293
  _n( '%d size compressed', '%d sizes compressed', $sizes_to_opt, 'ewww-image-optimizer' )
6294
  ), $sizes_to_opt );
6295
- $output .= " <a href='#TB_inline?width=550&height=450&inlineId=ewww-attachment-detail-$id' class='thickbox'>(+)</a></div>";
6296
  $results_msg = ewww_image_optimizer_image_results( $orig_size, $opt_size );
6297
  // Output the optimizer results.
6298
- $output .= '<div>' . esc_html( $results_msg ) . '</div>';
6299
  $display_size = ewww_image_optimizer_size_format( $opt_size );
6300
  // Output the total filesize.
6301
  $detail_output .= '<div><strong>' . sprintf(
@@ -6422,7 +6617,7 @@ function ewww_image_optimizer_migrate_meta_to_db( $id, $meta, $bail_early = fals
6422
  // TODO: ditto.
6423
  return $meta;
6424
  }
6425
- $converted = ( is_array( $meta ) && ! empty( $meta['converted'] ) && ! empty( $meta['orig_file'] ) ? trailingslashit( dirname( $file_path ) ) . basename( $meta['orig_file'] ) : false );
6426
  $full_size_update = ewww_image_optimizer_update_file_from_meta( $file_path, 'media', $id, 'full', $converted );
6427
  if ( ! $full_size_update && $bail_early ) {
6428
  ewwwio_debug_message( "bailing early for migration of $id" );
@@ -6456,7 +6651,7 @@ function ewww_image_optimizer_migrate_meta_to_db( $id, $meta, $bail_early = fals
6456
  }
6457
 
6458
  $resize_path = $base_dir . $data['file'];
6459
- $converted = ( is_array( $data ) && ! empty( $data['converted'] ) && ! empty( $data['orig_file'] ) ? trailingslashit( dirname( $resize_path ) ) . basename( $data['orig_file'] ) : false );
6460
  ewww_image_optimizer_update_file_from_meta( $resize_path, 'media', $id, $size, $converted );
6461
  // Search for retina images.
6462
  if ( function_exists( 'wr2x_get_retina' ) ) {
@@ -6473,7 +6668,7 @@ function ewww_image_optimizer_migrate_meta_to_db( $id, $meta, $bail_early = fals
6473
  // Search sizes from a custom theme...
6474
  if ( isset( $meta['image_meta']['resized_images'] ) && ewww_image_optimizer_iterable( $meta['image_meta']['resized_images'] ) ) {
6475
  $imagemeta_resize_pathinfo = pathinfo( $file_path );
6476
- $imagemeta_resize_path = '';
6477
  foreach ( $meta['image_meta']['resized_images'] as $index => $imagemeta_resize ) {
6478
  $imagemeta_resize_path = $imagemeta_resize_pathinfo['dirname'] . '/' . $imagemeta_resize_pathinfo['filename'] . '-' . $imagemeta_resize . '.' . $imagemeta_resize_pathinfo['extension'];
6479
  ewww_image_optimizer_update_file_from_meta( $imagemeta_resize_path, 'media', $id, 'resized-images-' . $index );
@@ -6483,7 +6678,7 @@ function ewww_image_optimizer_migrate_meta_to_db( $id, $meta, $bail_early = fals
6483
  // and another custom theme.
6484
  if ( isset( $meta['custom_sizes'] ) && ewww_image_optimizer_iterable( $meta['custom_sizes'] ) ) {
6485
  $custom_sizes_pathinfo = pathinfo( $file_path );
6486
- $custom_size_path = '';
6487
  foreach ( $meta['custom_sizes'] as $dimensions => $custom_size ) {
6488
  $custom_size_path = $custom_sizes_pathinfo['dirname'] . '/' . $custom_size['file'];
6489
  ewww_image_optimizer_update_file_from_meta( $custom_size_path, 'media', $id, 'custom-size-' . $dimensions );
@@ -6543,10 +6738,10 @@ function ewww_image_optimizer_bulk_action_handler() {
6543
  $ids = implode( ',', array_map( 'intval', $_REQUEST['media'] ) );
6544
  wp_redirect( add_query_arg(
6545
  array(
6546
- 'page' => 'ewww-image-optimizer-bulk',
6547
  '_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-bulk' ),
6548
- 'goback' => 1,
6549
- 'ids' => $ids,
6550
  ),
6551
  admin_url( 'upload.php' )
6552
  ) );
@@ -6613,7 +6808,7 @@ function ewww_image_optimizer_set_option( $option_name, $option_value ) {
6613
  function ewww_image_optimizer_get_bad_attachments() {
6614
  $bad_attachment = get_transient( 'ewww_image_optimizer_rebuilding_attachment' );
6615
  if ( $bad_attachment ) {
6616
- $bad_attachments = (array) ewww_image_optimizer_get_option( 'ewww_image_optimizer_bad_attachments' );
6617
  $bad_attachments[] = $bad_attachment;
6618
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_bad_attachments', $bad_attachments, false );
6619
  } else {
@@ -6631,7 +6826,7 @@ function ewww_image_optimizer_get_bad_attachments() {
6631
  function ewww_image_optimizer_settings_script( $hook ) {
6632
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
6633
  // Make sure we are being called from the settings page.
6634
- if ( strpos( $hook,'settings_page_ewww-image-optimizer' ) !== 0 ) {
6635
  return;
6636
  }
6637
  wp_enqueue_script( 'ewwwbulkscript', plugins_url( '/includes/eio.js', __FILE__ ), array( 'jquery' ), EWWW_IMAGE_OPTIMIZER_VERSION );
@@ -6676,7 +6871,7 @@ function ewww_image_optimizer_savings() {
6676
  ewwwio_debug_message( 'retrieving list of sites the easy way (pre 4.6)' );
6677
  $blogs = wp_get_sites( array(
6678
  'network_id' => $wpdb->siteid,
6679
- 'limit' => 1000,
6680
  ) );
6681
  }
6682
  $total_savings = 0;
@@ -6690,6 +6885,7 @@ function ewww_image_optimizer_savings() {
6690
  switch_to_blog( $blog_id );
6691
  ewwwio_debug_message( "getting savings for site: $blog_id" );
6692
  $table_name = $wpdb->prefix . 'ewwwio_images';
 
6693
  if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name ) ) != $table_name ) {
6694
  ewww_image_optimizer_install_table();
6695
  }
@@ -6705,7 +6901,8 @@ function ewww_image_optimizer_savings() {
6705
  } else {
6706
  ewwwio_debug_message( 'querying savings for single site' );
6707
  $total_savings = 0;
6708
- $table_name = $wpdb->ewwwio_images;
 
6709
  if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name ) ) != $table_name ) {
6710
  ewww_image_optimizer_install_table();
6711
  }
@@ -6730,9 +6927,11 @@ function ewww_image_optimizer_htaccess_path() {
6730
  $newhtpath = trailingslashit( $htpath . $path_diff ) . '.htaccess';
6731
  if ( is_file( $newhtpath ) ) {
6732
  ewwwio_debug_message( 'subdir install confirmed' );
 
6733
  return $newhtpath;
6734
  }
6735
  }
 
6736
  return $htpath . '.htaccess';
6737
  }
6738
 
@@ -6740,6 +6939,8 @@ function ewww_image_optimizer_htaccess_path() {
6740
  * Called via AJAX, adds WebP rewrite rules to the .htaccess file.
6741
  */
6742
  function ewww_image_optimizer_webp_rewrite() {
 
 
6743
  // Verify that the user is properly authorized.
6744
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-settings' ) ) {
6745
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
@@ -6752,23 +6953,49 @@ function ewww_image_optimizer_webp_rewrite() {
6752
  esc_html_e( 'Insertion failed', 'ewww-image-optimizer' );
6753
  }
6754
  }
6755
- die();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6756
  }
6757
 
6758
  /**
6759
  * If rules are present, stay silent, otherwise, gives us some rules to insert!
 
 
6760
  */
6761
  function ewww_image_optimizer_webp_rewrite_verify() {
6762
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
6763
- $current_rules = extract_from_markers( ewww_image_optimizer_htaccess_path(), 'EWWWIO' );
6764
- $ewww_rules = array(
 
 
 
 
 
 
6765
  '<IfModule mod_rewrite.c>',
6766
  'RewriteEngine On',
6767
  'RewriteCond %{HTTP_ACCEPT} image/webp',
6768
  'RewriteCond %{REQUEST_FILENAME} (.*)\.(jpe?g|png)$',
6769
  'RewriteCond %{REQUEST_FILENAME}.webp -f',
6770
  'RewriteCond %{QUERY_STRING} !type=original',
6771
- 'RewriteRule (.+)\.(jpe?g|png)$ %{REQUEST_FILENAME}.webp [T=image/webp,E=accept:1,L]',
6772
  '</IfModule>',
6773
  '<IfModule mod_headers.c>',
6774
  'Header append Vary Accept env=REDIRECT_accept',
@@ -6782,14 +7009,50 @@ function ewww_image_optimizer_webp_rewrite_verify() {
6782
  ! ewww_image_optimizer_array_search( 'Header append Vary Accept', $current_rules ) ||
6783
  ! ewww_image_optimizer_array_search( 'AddType image/webp', $current_rules )
6784
  ) {
6785
- ewwwio_memory( __FUNCTION__ );
6786
  return $ewww_rules;
6787
  } else {
6788
- ewwwio_memory( __FUNCTION__ );
6789
  return;
6790
  }
6791
  }
6792
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6793
  /**
6794
  * Looks for a certain string within all array elements.
6795
  *
@@ -6812,6 +7075,15 @@ function ewww_image_optimizer_array_search( $needle, $haystack ) {
6812
  return false;
6813
  }
6814
 
 
 
 
 
 
 
 
 
 
6815
  /**
6816
  * Retrieves a list of registered image sizes.
6817
  *
@@ -6822,7 +7094,7 @@ function ewww_image_optimizer_array_search( $needle, $haystack ) {
6822
  function ewww_image_optimizer_get_image_sizes() {
6823
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
6824
  global $_wp_additional_image_sizes;
6825
- $sizes = array();
6826
  $image_sizes = get_intermediate_image_sizes();
6827
  if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
6828
  ewwwio_debug_message( print_r( $image_sizes, true ) );
@@ -6833,7 +7105,7 @@ function ewww_image_optimizer_get_image_sizes() {
6833
  if ( ewww_image_optimizer_iterable( $image_sizes ) ) {
6834
  foreach ( $image_sizes as $_size ) {
6835
  if ( in_array( $_size, array( 'thumbnail', 'medium', 'medium_large', 'large' ) ) ) {
6836
- $sizes[ $_size ]['width'] = get_option( $_size . '_size_w' );
6837
  $sizes[ $_size ]['height'] = get_option( $_size . '_size_h' );
6838
  if ( 'medium_large' === $_size && 0 == $sizes[ $_size ]['width'] ) {
6839
  $sizes[ $_size ]['width'] = '768';
@@ -6843,14 +7115,14 @@ function ewww_image_optimizer_get_image_sizes() {
6843
  }
6844
  } elseif ( isset( $_wp_additional_image_sizes[ $_size ] ) ) {
6845
  $sizes[ $_size ] = array(
6846
- 'width' => $_wp_additional_image_sizes[ $_size ]['width'],
6847
  'height' => $_wp_additional_image_sizes[ $_size ]['height'],
6848
  );
6849
  }
6850
  }
6851
  }
6852
  $sizes['pdf-full'] = array(
6853
- 'width' => 99999,
6854
  'height' => 99999,
6855
  );
6856
 
@@ -6896,6 +7168,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
6896
  ewwwio_debug_message( 'WP_CONTENT_DIR: ' . WP_CONTENT_DIR );
6897
  ewwwio_debug_message( 'home url: ' . get_home_url() );
6898
  ewwwio_debug_message( 'site url: ' . get_site_url() );
 
6899
  $network_class = $network;
6900
  if ( empty( $network ) ) {
6901
  $network_class = 'singlesite';
@@ -6911,7 +7184,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
6911
  if ( is_multisite() && is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) && ! get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) ) {
6912
  $network_class = 'network-multisite';
6913
  }
6914
- $output = array();
6915
  $output[] = "<script type='text/javascript'>\n" .
6916
  'jQuery(document).ready(function($) {$(".fade").fadeTo(5000,1).fadeOut(3000);});' . "\n" .
6917
  "</script>\n";
@@ -6938,7 +7211,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
6938
  } else {
6939
  $bulk_link = '<a href="upload.php?page=ewww-image-optimizer-bulk">' . esc_html__( 'Bulk Optimize', 'ewww-image-optimizer' ) . '</a>';
6940
  }
6941
- $s3_link = '<a href="https://ewww.io/downloads/s3-image-optimizer/">' . esc_html__( 'S3 Image Optimizer', 'ewww-image-optimizer' ) . '</a>';
6942
  $output[] = '<p>' .
6943
  sprintf(
6944
  /* translators: %s: Bulk Optimize (link) */
@@ -6967,21 +7240,43 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
6967
  if ( preg_match( '/great/', $verify_cloud ) ) {
6968
  $status_output .= '<span style="color: green">' . esc_html__( 'Verified,', 'ewww-image-optimizer' ) . ' </span>' . ewww_image_optimizer_cloud_quota();
6969
  } elseif ( preg_match( '/exceeded/', $verify_cloud ) ) {
6970
- $status_output .= '<span style="color: orange">' . esc_html__( 'Verified,', 'ewww-image-optimizer' ) . ' </span>' . ewww_image_optimizer_cloud_quota();
6971
- $collapsible = false;
6972
  } else {
6973
  $status_output .= '<span style="color: red">' . esc_html__( 'Not Verified', 'ewww-image-optimizer' ) . '</span>';
6974
- $collapsible = false;
6975
  }
6976
  $status_output .= "</p>\n";
6977
- $disable_level = '';
6978
  } else {
6979
  $disable_level = "disabled='disabled'";
6980
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6981
  if ( ! ewww_image_optimizer_full_cloud() && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
6982
  list ( $jpegtran_src, $optipng_src, $gifsicle_src, $jpegtran_dst, $optipng_dst, $gifsicle_dst ) = ewww_image_optimizer_install_paths();
6983
  }
6984
- $skip = ewww_image_optimizer_skip_tools();
6985
  $status_output .= "<p>\n";
6986
  if ( ! $skip['jpegtran'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
6987
  $status_output .= '<b>jpegtran:</b> ';
@@ -6995,7 +7290,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
6995
  $status_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span>&emsp;' . esc_html__( 'version', 'ewww-image-optimizer' ) . ': ' . $jpegtran_installed . "<br />\n";
6996
  } else {
6997
  $status_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span><br />' . "\n";
6998
- $collapsible = false;
6999
  }
7000
  }
7001
  if ( ! $skip['optipng'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
@@ -7010,7 +7305,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7010
  $status_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span>&emsp;' . esc_html__( 'version', 'ewww-image-optimizer' ) . ': ' . $optipng_version . "<br />\n";
7011
  } else {
7012
  $status_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span><br />' . "\n";
7013
- $collapsible = false;
7014
  }
7015
  }
7016
  if ( ! $skip['pngout'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
@@ -7025,7 +7320,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7025
  $status_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span>&emsp;' . esc_html__( 'version', 'ewww-image-optimizer' ) . ': ' . preg_replace( '/PNGOUT \[.*\)\s*?/', '', $pngout_version ) . "<br />\n";
7026
  } else {
7027
  $status_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span>&emsp;' . esc_html__( 'Install', 'ewww-image-optimizer' ) . ' <a href="admin.php?action=ewww_image_optimizer_install_pngout">' . esc_html__( 'automatically', 'ewww-image-optimizer' ) . '</a> | <a href="http://advsys.net/ken/utils.htm">' . esc_html__( 'manually', 'ewww-image-optimizer' ) . '</a> - ' . esc_html__( 'Pngout is free closed-source software that can produce drastically reduced filesizes for PNGs, but can be very time consuming to process images', 'ewww-image-optimizer' ) . "<br />\n";
7028
- $collapsible = false;
7029
  }
7030
  }
7031
  if ( ! $skip['gifsicle'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
@@ -7040,7 +7335,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7040
  $status_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span>&emsp;' . esc_html__( 'version', 'ewww-image-optimizer' ) . ': ' . $gifsicle_version . "<br />\n";
7041
  } else {
7042
  $status_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span><br />' . "\n";
7043
- $collapsible = false;
7044
  }
7045
  }
7046
  if ( ! $skip['pngquant'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
@@ -7055,34 +7350,34 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7055
  $status_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span>&emsp;' . esc_html__( 'version', 'ewww-image-optimizer' ) . ': ' . $pngquant_version . "<br />\n";
7056
  } else {
7057
  $status_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span><br />' . "\n";
7058
- $collapsible = false;
7059
  }
7060
  }
7061
- if ( EWWW_IMAGE_OPTIMIZER_WEBP && ! $skip['webp'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
7062
  $status_output .= '<b>webp:</b> ';
7063
- if ( EWWW_IMAGE_OPTIMIZER_WEBP ) {
7064
- $webp_version = ewww_image_optimizer_tool_found( EWWW_IMAGE_OPTIMIZER_WEBP, 'w' );
7065
  if ( ! $webp_version ) {
7066
- $webp_version = ewww_image_optimizer_tool_found( EWWW_IMAGE_OPTIMIZER_WEBP, 'wb' );
7067
  }
7068
  }
7069
  if ( ! empty( $webp_version ) ) {
7070
  $status_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span>&emsp;' . esc_html__( 'version', 'ewww-image-optimizer' ) . ': ' . $webp_version . "<br />\n";
7071
  } else {
7072
  $status_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span><br />' . "\n";
7073
- $collapsible = false;
7074
  }
7075
  }
7076
  if ( ! ewww_image_optimizer_full_cloud() ) {
7077
  if ( ewww_image_optimizer_safemode_check() ) {
7078
  $status_output .= 'safe mode: <span style="color: red; font-weight: bolder">' . esc_html__( 'On', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7079
- $collapsible = false;
7080
  } else {
7081
  $status_output .= 'safe mode: <span style="color: green; font-weight: bolder">' . esc_html__( 'Off', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7082
  }
7083
  if ( ewww_image_optimizer_exec_check() ) {
7084
  $status_output .= 'exec(): <span style="color: red; font-weight: bolder">' . esc_html__( 'Disabled', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7085
- $collapsible = false;
7086
  } else {
7087
  $status_output .= 'exec(): <span style="color: green; font-weight: bolder">' . esc_html__( 'Enabled', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7088
  }
@@ -7095,10 +7390,10 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7095
  '<b>' . __( 'Graphics libraries', 'ewww-image-optimizer' ) . '</b> - '
7096
  );
7097
  $toolkit_output .= '<br>';
7098
- $toolkit_found = false;
7099
  if ( ewww_image_optimizer_gd_support() ) {
7100
  $toolkit_output .= 'GD: <span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' );
7101
- $toolkit_found = true;
7102
  } else {
7103
  $toolkit_output .= 'GD: <span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' );
7104
  }
@@ -7106,7 +7401,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7106
  'Gmagick: ';
7107
  if ( ewww_image_optimizer_gmagick_support() ) {
7108
  $toolkit_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' );
7109
- $toolkit_found = true;
7110
  } else {
7111
  $toolkit_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' );
7112
  }
@@ -7114,7 +7409,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7114
  'Imagick: ';
7115
  if ( ewww_image_optimizer_imagick_support() ) {
7116
  $toolkit_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' );
7117
- $toolkit_found = true;
7118
  } else {
7119
  $toolkit_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' );
7120
  }
@@ -7125,15 +7420,19 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7125
  $toolkit_output = str_replace( 'color: red', 'color: gray', $toolkit_output );
7126
  }
7127
  $status_output .= $toolkit_output;
 
 
 
 
7128
  } // End if().
7129
  $mimetype_output = '<b>' . esc_html__( 'Only need one of these:', 'ewww-image-optimizer' ) . ' </b><br>';
7130
  // Initialize this variable to check for the 'file' command if we don't have any php libraries we can use.
7131
  $file_command_check = true;
7132
- $mimetype_tool = '';
7133
  if ( function_exists( 'finfo_file' ) ) {
7134
- $mimetype_output .= 'fileinfo: <span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7135
  $file_command_check = false;
7136
- $mimetype_tool = 'fileinfo';
7137
  } else {
7138
  $mimetype_output .= 'fileinfo: <span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7139
  }
@@ -7147,9 +7446,9 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7147
  $mimetype_output .= 'getimagesize(): <span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7148
  }
7149
  if ( function_exists( 'mime_content_type' ) ) {
7150
- $mimetype_output .= 'mime_content_type(): <span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span><br />' . "\n";
7151
  $file_command_check = false;
7152
- $mimetype_tool = empty( $mimetype_tool ) ? 'mime_content_type' : $mimetype_tool;
7153
  } else {
7154
  $mimetype_output .= 'mime_content_type(): <span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span><br />' . "\n";
7155
  }
@@ -7157,7 +7456,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7157
  if ( PHP_OS != 'WINNT' && ! ewww_image_optimizer_full_cloud() && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
7158
  if ( $file_command_check && ! ewww_image_optimizer_find_nix_binary( 'file', 'f' ) ) {
7159
  $extra_tool_output .= '<span style="color: red; font-weight: bolder">file: ' . esc_html__( 'command not found on your system', 'ewww-image-optimizer' ) . '</span><br />';
7160
- $collapsible = false;
7161
  } elseif ( empty( $mimetype_tool ) ) {
7162
  $mimetype_tool = 'file'; // So that we know a mimetype library was found.
7163
  }
@@ -7166,7 +7465,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7166
  }
7167
  if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_pngout' ) && ! $skip['pngout'] && PHP_OS != 'SunOS' && ! ewww_image_optimizer_find_nix_binary( 'tar', 't' ) ) {
7168
  $extra_tool_output .= '<span style="color: red; font-weight: bolder">tar: ' . esc_html__( 'command not found on your system', 'ewww-image-optimizer' ) . ' (' . esc_html__( 'required for automatic pngout installer', 'ewww-image-optimizer' ) . ')</span><br />';
7169
- $collapsible = false;
7170
  }
7171
  } elseif ( $file_command_check ) {
7172
  $collapsible = false;
@@ -7219,6 +7518,9 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7219
  $output[] = "<input type='hidden' name='option_page' value='ewww_image_optimizer_options' />\n";
7220
  $output[] = "<input type='hidden' name='action' value='update' />\n";
7221
  $output[] = wp_nonce_field( 'ewww_image_optimizer_options-options', '_wpnonce', true, false ) . "\n";
 
 
 
7222
  $output[] = "<div id='ewww-general-settings'>\n";
7223
  $output[] = "<table class='form-table'>\n";
7224
  if ( is_multisite() ) {
@@ -7227,6 +7529,9 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7227
  $output[] = "<tr><th><label for='ewww_image_optimizer_allow_tracking'>" . esc_html__( 'Allow Usage Tracking?', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_allow_tracking' name='ewww_image_optimizer_allow_tracking' value='true' " . ( get_site_option( 'ewww_image_optimizer_allow_tracking' ) == true ? "checked='true'" : '' ) . ' /> ' .
7228
  esc_html__( 'Allow EWWW Image Optimizer to anonymously track how this plugin is used and help us make the plugin better. Opt-in to tracking and receive 500 API image credits free. No sensitive data is tracked.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7229
  $output[] = "<input type='hidden' id='ewww_image_optimizer_allow_multisite_override_active' name='ewww_image_optimizer_allow_multisite_override_active' value='0'>";
 
 
 
7230
  foreach ( $output as $line ) {
7231
  echo $line;
7232
  }
@@ -7237,11 +7542,11 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7237
  }
7238
  }
7239
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
7240
- $blog_id = get_current_blog_id();
7241
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_cloud_notkey'>" . esc_html__( 'Cloud optimization API Key', 'ewww-image-optimizer' ) . "</label></th><td><input type='text' id='ewww_image_optimizer_cloud_notkey' name='ewww_image_optimizer_cloud_notkey' readonly='readonly' value='****************************" . substr( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ), 28 ) . "' size='32' /> <a href='admin.php?action=ewww_image_optimizer_remove_cloud_key&site=$blog_id'>" . esc_html__( 'Remove API key.', 'ewww-image-optimizer' ) . "</a></td></tr>\n";
7242
  $output[] = "<input type='hidden' id='ewww_image_optimizer_cloud_key' name='ewww_image_optimizer_cloud_key' value='" . ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) . "' />\n";
7243
  } else {
7244
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_cloud_key'>" . esc_html__( 'Cloud optimization API Key', 'ewww-image-optimizer' ) . "</label></th><td><input type='text' id='ewww_image_optimizer_cloud_key' name='ewww_image_optimizer_cloud_key' value='' size='32' /> " . esc_html__( 'API Key will be validated when you save your settings.', 'ewww-image-optimizer' ) . " <a href='https://ewww.io/plans/'>" . esc_html__( 'Purchase an API key.', 'ewww-image-optimizer' ) . "</a></td></tr>\n";
7245
  }
7246
  $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_debug'>" . esc_html__( 'Debugging', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_debug' name='ewww_image_optimizer_debug' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Use this to provide information for support purposes, or if you feel comfortable digging around in the code to fix a problem you are experiencing.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7247
  $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_jpegtran_copy'>" . esc_html__( 'Remove metadata', 'ewww-image-optimizer' ) . "</label></th>\n" .
@@ -7284,8 +7589,8 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7284
  $disable_pdf_level = $disable_level;
7285
  if ( 'getimagesize' == $mimetype_tool ) {
7286
  $disable_pdf_level = "disabled='disabled'";
7287
- $output[] = "<tr class='$network_class'><th>&nbsp;</th><td>";
7288
- $output[] = "<p class='$network_class description'>" . esc_html__( '*PDF optimization cannot be enabled because the fileinfo extension is missing.', 'ewww-image-optimizer' ) . "</p></td></tr>\n";
7289
  }
7290
  $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_pdf_level'>" . esc_html__( 'PDF Optimization Level', 'ewww-image-optimizer' ) . "</label></th>\n" .
7291
  "<td><span><select id='ewww_image_optimizer_pdf_level' name='ewww_image_optimizer_pdf_level'>\n" .
@@ -7319,13 +7624,13 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7319
  $media_include_disable = '';
7320
  if ( get_option( 'ewww_image_optimizer_disable_resizes_opt' ) ) {
7321
  $media_include_disable = 'disabled="disabled"';
7322
- $output[] = "<tr class='$network_class'><th>&nbsp;</th><td>" .
7323
  '<p><span style="color: green">' . esc_html__( '*Include Media Library Folders has been disabled because it will cause the scanner to ignore the disabled resizes.', 'ewww-image-optimizer' ) . "</span></p></td></tr>\n";
7324
  }
7325
  $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_include_media_paths'>" . esc_html__( 'Include Media Library Folders', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_include_media_paths' name='ewww_image_optimizer_include_media_paths' $media_include_disable value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_include_media_paths' ) == true && ! get_option( 'ewww_image_optimizer_disable_resizes_opt' ) ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Scan all images from the latest two folders of the Media Library during the Bulk Optimizer and Scheduled Optimization.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7326
  ewwwio_debug_message( 'include media library: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_include_media_paths' ) == true ? 'on' : 'off' ) );
7327
  $aux_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_aux_paths' ) ? esc_html( implode( "\n", ewww_image_optimizer_get_option( 'ewww_image_optimizer_aux_paths' ) ) ) : '';
7328
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_aux_paths'>" . esc_html__( 'Folders to optimize', 'ewww-image-optimizer' ) . '</label></th><td>' .
7329
  /* translators: %s: the folder where WordPress is installed */
7330
  sprintf( esc_html__( 'One path per line, must be within %s. Use full paths, not relative paths.', 'ewww-image-optimizer' ), ABSPATH ) . "<br>\n" .
7331
  "<textarea id='ewww_image_optimizer_aux_paths' name='ewww_image_optimizer_aux_paths' rows='3' cols='60'>$aux_paths</textarea>\n" .
@@ -7334,7 +7639,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7334
  ewwwio_debug_message( $aux_paths );
7335
 
7336
  $exclude_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_exclude_paths' ) ? esc_html( implode( "\n", ewww_image_optimizer_get_option( 'ewww_image_optimizer_exclude_paths' ) ) ) : '';
7337
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_exclude_paths'>" . esc_html__( 'Folders to ignore', 'ewww-image-optimizer' ) . '</label></th><td>' . esc_html__( 'One path per line, partial paths allowed, but no urls.', 'ewww-image-optimizer' ) . "<br>\n" .
7338
  "<textarea id='ewww_image_optimizer_exclude_paths' name='ewww_image_optimizer_exclude_paths' rows='3' cols='60'>$exclude_paths</textarea>\n" .
7339
  "<p class='description'>" . esc_html__( 'A file that matches any pattern or path provided will not be optimized.', 'ewww-image-optimizer' ) . "</p></td></tr>\n";
7340
  ewwwio_debug_message( 'folders to ignore:' );
@@ -7353,8 +7658,20 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7353
 
7354
  $output[] = "<div id='ewww-resize-settings'>\n";
7355
  $output[] = "<table class='form-table'>\n";
7356
- // $output[] = "<tr><th><label for='ewww_image_optimizer_resize_detection'>" . esc_html__( 'Resize Detection', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_resize_detection' name='ewww_image_optimizer_resize_detection' value='true' " . ( ewww_image_optimizer_get_option('ewww_image_optimizer_resize_detection') == TRUE ? "checked='true'" : "" ) . " /> " . esc_html__( 'Will highlight images that need to be resized because the browser is scaling them down. Only visible for Admin users and adds a button to the admin bar to detect scaled images that have been lazy loaded.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7357
- // ewwwio_debug_message( 'resize detection: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_detection' ) == TRUE ? 'on' : 'off' ) );
 
 
 
 
 
 
 
 
 
 
 
 
7358
  if ( function_exists( 'imsanity_get_max_width_height' ) ) {
7359
  $output[] = "<tr class='$network_class'><th>&nbsp;</th><td>" .
7360
  '<p><span style="color: green">' . esc_html__( '*Imsanity settings override the EWWW resize dimensions.', 'ewww-image-optimizer' ) . "</span></p></td></tr>\n";
@@ -7364,25 +7681,25 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7364
  "</td></tr>\n";
7365
  ewwwio_debug_message( 'max media dimensions: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' ) . ' x ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' ) );
7366
  $output[] = "<tr class='$network_class'><th>" . esc_html__( 'Resize Other Images', 'ewww-image-optimizer' ) . "</th><td><label for='ewww_image_optimizer_maxotherwidth'>" . esc_html__( 'Max Width', 'ewww-image-optimizer' ) . "</label> <input type='number' step='1' min='0' class='small-text' id='ewww_image_optimizer_maxotherwidth' name='ewww_image_optimizer_maxotherwidth' value='" . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherwidth' ) . ( function_exists( 'imsanity_get_max_width_height' ) ? "' disabled='disabled" : '' ) . "' /> <label for='ewww_image_optimizer_maxotherheight'>" . esc_html__( 'Max Height', 'ewww-image-optimizer' ) . "</label> <input type='number' step='1' min='0' class='small-text' id='ewww_image_optimizer_maxotherheight' name='ewww_image_optimizer_maxotherheight' value='" . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherheight' ) . ( function_exists( 'imsanity_get_max_width_height' ) ? "' disabled='disabled" : '' ) . "' /> " . esc_html__( 'in pixels', 'ewww-image-optimizer' ) . "\n" .
7367
- "<p class='description'>" . esc_html__( 'Resizes images uploaded indirectly to the Media Library, like theme images or front-end uploads.', 'ewww-image-optimizer' ) .
7368
  "</td></tr>\n";
7369
  ewwwio_debug_message( 'max other dimensions: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherwidth' ) . ' x ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherheight' ) );
7370
  $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_resize_existing'>" . esc_html__( 'Resize Existing Images', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_resize_existing' name='ewww_image_optimizer_resize_existing' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Allow resizing of existing Media Library images.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7371
  ewwwio_debug_message( 'resize existing images: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' ) == true ? 'on' : 'off' ) );
7372
 
7373
- $output[] = '<tr class="network-singlesite"><th>' . esc_html__( 'Disable Resizes', 'ewww-image-optimizer' ) . '</th><td><p>' . esc_html__( 'WordPress, your theme, and other plugins generate various image sizes. You may disable optimization for certain sizes, or completely prevent those sizes from being created.', 'ewww-image-optimizer' ) . "</p>\n";
7374
- $image_sizes = ewww_image_optimizer_get_image_sizes();
7375
- $disabled_sizes = get_option( 'ewww_image_optimizer_disable_resizes' );
7376
  $disabled_sizes_opt = get_option( 'ewww_image_optimizer_disable_resizes_opt' );
7377
- $output[] = '<table><tr class="network-singlesite"><th>' . esc_html__( 'Disable Optimization', 'ewww-image-optimizer' ) . '</th><th>' . esc_html__( 'Disable Creation', 'ewww-image-optimizer' ) . "</th></tr>\n";
7378
  ewwwio_debug_message( 'disabled resizes:' );
7379
  foreach ( $image_sizes as $size => $dimensions ) {
7380
  if ( 'thumbnail' == $size ) {
7381
- $output [] = "<tr class='network-singlesite'><td><input type='checkbox' id='ewww_image_optimizer_disable_resizes_opt_$size' name='ewww_image_optimizer_disable_resizes_opt[$size]' value='true' " . ( ! empty( $disabled_sizes_opt[ $size ] ) ? "checked='true'" : '' ) . " /></td><td><input type='checkbox' id='ewww_image_optimizer_disable_resizes_$size' name='ewww_image_optimizer_disable_resizes[$size]' value='true' disabled /></td><td><label for='ewww_image_optimizer_disable_resizes_$size'>$size - {$dimensions['width']}x{$dimensions['height']}</label></td></tr>\n";
7382
  } elseif ( 'pdf-full' == $size ) {
7383
- $output [] = "<tr class='network-singlesite'><td><input type='checkbox' id='ewww_image_optimizer_disable_resizes_opt_$size' name='ewww_image_optimizer_disable_resizes_opt[$size]' value='true' " . ( ! empty( $disabled_sizes_opt[ $size ] ) ? "checked='true'" : '' ) . " /></td><td><input type='checkbox' id='ewww_image_optimizer_disable_resizes_$size' name='ewww_image_optimizer_disable_resizes[$size]' value='true' " . ( ! empty( $disabled_sizes[ $size ] ) ? "checked='true'" : '' ) . " /></td><td><label for='ewww_image_optimizer_disable_resizes_$size'>$size - <span class='description'>" . esc_html__( 'Disabling creation of the full-size preview for PDF files will disable all PDF preview sizes', 'ewww-image-optimizer' ) . "</span></label></td></tr>\n";
7384
  } else {
7385
- $output [] = "<tr class='network-singlesite'><td><input type='checkbox' id='ewww_image_optimizer_disable_resizes_opt_$size' name='ewww_image_optimizer_disable_resizes_opt[$size]' value='true' " . ( ! empty( $disabled_sizes_opt[ $size ] ) ? "checked='true'" : '' ) . " /></td><td><input type='checkbox' id='ewww_image_optimizer_disable_resizes_$size' name='ewww_image_optimizer_disable_resizes[$size]' value='true' " . ( ! empty( $disabled_sizes[ $size ] ) ? "checked='true'" : '' ) . " /></td><td><label for='ewww_image_optimizer_disable_resizes_$size'>$size - {$dimensions['width']}x{$dimensions['height']}</label></td></tr>\n";
7386
  }
7387
  ewwwio_debug_message( $size . ': ' . ( ! empty( $disabled_sizes_opt[ $size ] ) ? 'optimization=disabled ' : 'optimization=enabled ' ) . ( ! empty( $disabled_sizes[ $size ] ) ? 'creation=disabled' : 'creation=enabled' ) );
7388
  }
@@ -7432,7 +7749,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7432
  ewwwio_debug_message( 'forced webp: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) == true ? 'on' : 'off' ) );
7433
  if ( ! ewww_image_optimizer_ce_webp_enabled() ) {
7434
  $webp_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' ) ? esc_html( implode( "\n", ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' ) ) ) : '';
7435
- $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_webp_paths'>" . esc_html__( 'WebP URLs', 'ewww-image-optimizer' ) . '</label></th><td>' . esc_html__( 'If Force WebP is enabled, enter URL patterns that should be permitted for Alternative WebP Rewriting. One pattern per line, may be partial URLs, but must include the domain name.', 'ewww-image-optimizer' ) . '<br>' .
7436
  "<textarea id='ewww_image_optimizer_webp_paths' name='ewww_image_optimizer_webp_paths' rows='3' cols='60'>$webp_paths</textarea></td></tr>\n";
7437
  ewwwio_debug_message( 'webp paths:' );
7438
  ewwwio_debug_message( $webp_paths );
@@ -7448,12 +7765,17 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7448
  $output[] = "</table>\n</div>\n";
7449
  $output[] = "<p class='submit'><input type='submit' class='button-primary' value='" . esc_attr__( 'Save Changes', 'ewww-image-optimizer' ) . "' /></p>\n";
7450
  $output[] = "</form>\n";
7451
- if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) && ! ewww_image_optimizer_ce_webp_enabled() ) {
 
 
 
 
7452
  $output[] = "<form id='ewww-webp-rewrite'>\n";
7453
  $output[] = '<p>' . esc_html__( 'There are many ways to serve WebP images to visitors with supported browsers. You may choose any you wish, but it is recommended to serve them with an .htaccess file using mod_rewrite and mod_headers. The plugin can insert the rules for you if the file is writable, or you can edit .htaccess yourself.', 'ewww-image-optimizer' ) . "</p>\n";
7454
  if ( ! ewww_image_optimizer_webp_rewrite_verify() ) {
7455
  $output[] = "<img id='webp-image' src='" . plugins_url( '/images/test.png', __FILE__ ) . "' style='float: right; padding: 0 0 10px 10px;'>\n" .
7456
- "<p id='ewww-webp-rewrite-status'><b>" . esc_html__( 'Rules verified successfully', 'ewww-image-optimizer' ) . "</b></p>\n";
 
7457
  ewwwio_debug_message( 'webp .htaccess rewriting enabled' );
7458
  } else {
7459
  $output[] = "<pre id='webp-rewrite-rules' style='background: white; font-color: black; border: 1px solid black; clear: both; padding: 10px;'>\n" .
@@ -7471,14 +7793,14 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7471
  "AddType image/webp .webp</pre>\n" .
7472
  "<img id='webp-image' src='" . plugins_url( '/images/test.png', __FILE__ ) . "' style='float: right; padding-left: 10px;'>\n" .
7473
  "<p id='ewww-webp-rewrite-status'>" . esc_html__( 'The image to the right will display a WebP image with WEBP in white text, if your site is serving WebP images and your browser supports WebP.', 'ewww-image-optimizer' ) . "</p>\n" .
7474
- "<button type='submit' class='button-secondary action'>" . esc_html__( 'Insert Rewrite Rules', 'ewww-image-optimizer' ) . "</button>\n";
7475
  ewwwio_debug_message( 'webp .htaccess rules not detected' );
7476
  }
7477
  $output[] = "</form>\n";
7478
  } elseif ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) && ! ewww_image_optimizer_ce_webp_enabled() ) {
7479
  $test_webp_image = plugins_url( '/images/test.png.webp', __FILE__ );
7480
- $test_png_image = plugins_url( '/images/test.png', __FILE__ );
7481
- $output[] = "<noscript data-img='$test_png_image' data-webp='$test_webp_image' data-style='float: right; padding: 0 0 10px 10px;' class='ewww_webp'><img src='$test_png_image' style='float: right; padding: 0 0 10px 10px;'></noscript>\n";
7482
  }
7483
  $output[] = "</div><!-- end container left -->\n";
7484
  $output[] = "<div id='ewww-container-right' style='border: 1px solid #e5e5e5; float: right; margin-left: -215px; padding: 0em 1.5em 1em; background-color: #fff; box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04); display: inline-block; width: 174px;'>\n" .
@@ -7487,16 +7809,11 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7487
  "<p><a href='https://translate.wordpress.org/projects/wp-plugins/ewww-image-optimizer/'>" . esc_html__( 'Help translate EWWW I.O.', 'ewww-image-optimizer' ) . "</a></p>\n" .
7488
  "<p><a href='https://wordpress.org/support/view/plugin-reviews/ewww-image-optimizer#postform'>" . esc_html__( 'Write a review.', 'ewww-image-optimizer' ) . "</a></p>\n" .
7489
  /* translators: %s: Paypal (link) */
7490
- '<p>' . sprintf( esc_html__( 'Contribute directly via %s.', 'ewww-image-optimizer' ), "<a href='https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=MKMQKCBFFG3WW'>Paypal</a>" ) . "</p>\n" .
7491
- '<p>' . esc_html__( 'Use any of these referral links to show your appreciation:', 'ewww-image-optimizer' ) . "</p>\n" .
7492
- '<p><b>' . esc_html__( 'Web Hosting:', 'ewww-image-optimizer' ) . "</b><br>\n" .
7493
- "<a href='http://www.a2hosting.com/?aid=b6322137'>A2 Hosting:</a> " . esc_html_x( 'with automatic EWWW IO setup', 'A2 Hosting:', 'ewww-image-optimizer' ) . "<br>\n" .
7494
- "<a href='http://www.shareasale.com/r.cfm?b=394686&u=1481701&m=41388&urllink='>WP Engine</a><br>\n" .
7495
- "</p>\n" .
7496
- '<p><b>' . esc_html_x( 'VPS:', 'abbreviation for Virtual Private Server', 'ewww-image-optimizer' ) . "</b><br>\n" .
7497
- "<a href='https://www.digitalocean.com/?refcode=89ef0197ec7e'>DigitalOcean</a><br>\n" .
7498
- "</p>\n" .
7499
- '<p><b>' . esc_html_x( 'CDN:', 'abbreviation for Content Delivery Network', 'ewww-image-optimizer' ) . "</b><br><a target='_blank' href='http://tracking.maxcdn.com/c/91625/36539/378'>" . esc_html__( 'Add MaxCDN to increase website speeds dramatically! Sign Up Now and Save 25%.', 'ewww-image-optimizer' ) . "</a></p>\n" .
7500
  "</div>\n" .
7501
  "</div>\n";
7502
  ewwwio_debug_message( 'max_execution_time: ' . ini_get( 'max_execution_time' ) );
@@ -7547,23 +7864,23 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
7547
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_help' ) ) {
7548
  /* $help_instructions = esc_html__( 'Please turn on the Debugging option. Then copy and paste the Debug Information from the bottom of the settings page. This will allow us to assist you more quickly.', 'ewww-image-optimizer' ); */
7549
  $current_user = wp_get_current_user();
7550
- $help_email = $current_user->user_email;
7551
- $hs_config = array(
7552
- 'color' => '#3eadc9',
7553
- 'icon' => 'buoy',
7554
- 'instructions' => $help_instructions,
7555
- 'poweredBy' => false,
7556
  'showContactFields' => true,
7557
- 'showSubject' => true,
7558
- 'topArticles' => true,
7559
- 'zIndex' => 100000,
7560
  );
7561
- $hs_identify = array(
7562
  'email' => $help_email,
7563
  );
7564
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
7565
  $ewww_debug_array = explode( '<br>', $ewww_debug );
7566
- $ewww_debug_i = 0;
7567
  foreach ( $ewww_debug_array as $ewww_debug_line ) {
7568
  $hs_identify[ 'debug_info_' . $ewww_debug_i ] = $ewww_debug_line;
7569
  $ewww_debug_i++;
@@ -7662,6 +7979,8 @@ function ewww_image_optimizer_remove_cloud_key() {
7662
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ) > 0 ) {
7663
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_pdf_level', 0 );
7664
  }
 
 
7665
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_backup_files', '' );
7666
  $sendback = wp_get_referer();
7667
  wp_redirect( esc_url_raw( $sendback ) );
@@ -7678,6 +7997,23 @@ function ewww_image_optimizer_resize_detection_script() {
7678
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_detection' ) ) {
7679
  wp_enqueue_script( 'ewww-resize-detection', plugins_url( '/includes/resize_detection.js', __FILE__ ), array(), EWWW_IMAGE_OPTIMIZER_VERSION );
7680
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7681
  }
7682
 
7683
  /**
@@ -7725,9 +8061,9 @@ function ewwwio_debug_message( $message ) {
7725
  ewwwio_debug_version_info();
7726
  $ewww_version_dumped = true;
7727
  }
7728
- $message = str_replace( "\n\n\n", '<br>', $message );
7729
- $message = str_replace( "\n\n", '<br>', $message );
7730
- $message = str_replace( "\n", '<br>', $message );
7731
  $ewww_debug .= "$message<br>";
7732
  } else {
7733
  global $ewww_debug;
@@ -7736,6 +8072,19 @@ function ewwwio_debug_message( $message ) {
7736
  }
7737
  }
7738
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7739
  /**
7740
  * Saves the in-memory debug log to a logfile in the plugin folder.
7741
  *
@@ -7796,8 +8145,8 @@ function ewwwio_debug_version_info() {
7796
 
7797
  // Check the WP version.
7798
  global $wp_version;
7799
- $my_version = substr( $wp_version, 0, 3 );
7800
- $ewww_debug .= "WP version: $wp_version<br>" ;
7801
 
7802
  if ( defined( 'PHP_VERSION_ID' ) ) {
7803
  $ewww_debug .= 'PHP version: ' . PHP_VERSION_ID . '<br>';
@@ -7861,7 +8210,7 @@ function ewww_image_optimizer_dynamic_image_debug() {
7861
  $i++;
7862
  }
7863
  } else {
7864
- esc_html_e( 'Cannot display trace', 'ewww-image-optimizer' );
7865
  }
7866
  echo '</p>';
7867
  }
@@ -7913,9 +8262,9 @@ function ewww_image_optimizer_image_queue_debug() {
7913
  echo "<div class='wrap'><h1>" . esc_html__( 'Image Queue Debugging', 'ewww-image-optimizer' ) . '</h1>';
7914
  global $wpdb;
7915
 
7916
- $table = $wpdb->options;
7917
 
7918
- $key = 'wp_ewwwio_media_optimize_batch_%';
7919
  $queues = $wpdb->get_results(
7920
  $wpdb->prepare( "
7921
  SELECT *
@@ -7938,7 +8287,7 @@ function ewww_image_optimizer_image_queue_debug() {
7938
  foreach ( $items as $item ) {
7939
  echo "{$item['id']} - {$item['type']}<br>";
7940
  $all_ids[] = $item['id'];
7941
- $ids[] = $item['id'];
7942
  }
7943
  $ids = implode( ',', $ids );
7944
  ?>
@@ -7975,7 +8324,7 @@ function ewwwio_memory_limit() {
7975
  if ( ! defined( 'EWWW_MEMORY_LIMIT' ) ) {
7976
  // Conservative default, current usage + 16M.
7977
  $current_memory = memory_get_usage( true );
7978
- $memory_limit = round( $current_memory / ( 1024 * 1024 ) ) + 16;
7979
  define( 'EWWW_MEMORY_LIMIT', $memory_limit );
7980
  }
7981
  }
10
  * @package EWWW_Image_Optimizer
11
  */
12
 
13
+ // TODO: use <picture> element to serve webp (#54).
14
+ // TODO: attempt lazy load support with a3 plugin and one from automattic for starters.
 
15
  // TODO: prevent bad ajax errors from firing when we click the toggle on the Optimization Log, and the plugin status from doing 403s...
16
  // TODO: use a transient to do health checks on the schedule optimizer.
17
  // TODO: add a column to track compression level used for each image, and later implement a way to (re)compress at a specific compression level.
19
  // TODO: need to make the scheduler so it can resume without having to re-run the queue population, and then we can probably also flush the queue when scheduled opt starts, but later it would be nice to implement the bulk_loop as the aux_loop so that it could handle media properly.
20
  // TODO: implement a search for the bulk table, or maybe we should just move it to it's own page?
21
  // TODO: port bulk changes to NextGEN and FlaGallery.
 
22
  // TODO: Add a custom async function for parallel mode to store image as pending and use the row ID instead of relative path.
23
  // TODO: write some tests for update_table and check_table, find_already_opt, and remove_dups.
24
  // TODO: write some conversion tests.
25
  // TODO: do a bottom paginator for the show optimized images table.
26
  // TODO: check this patch, to see if the use of 'full' causes any issues: https://core.trac.wordpress.org/ticket/37840 .
 
27
  // TODO: integrate AGR, since it's "abandoned", but possibly using gifsicle for better GIFs.
28
+ // TODO: use this: https://codex.wordpress.org/AJAX_in_Plugins#The_post-load_JavaScript_Event .
29
+ // TODO: on images without srscet, add 2x and 3x versions anyway.
30
+ // TODO: check what happens to WebP images when restoring original from backups.
31
+ // TODO: use got_mod_rewrite to warn folks not to bother with webp htaccess.
32
+ // TODO: fix ExactDN failure after multisite save settings.
33
+ // TODO: add ExactDN compat with A3 lazy.
34
  if ( ! defined( 'ABSPATH' ) ) {
35
  exit;
36
  }
37
 
38
+ define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '406.0' );
39
 
40
  // Initialize a couple globals.
41
  $ewww_debug = '';
127
  add_action( 'init', 'ewww_image_optimizer_gallery_support' );
128
  // Initializes the plugin for admin interactions, like saving network settings and scheduling cron jobs.
129
  add_action( 'admin_init', 'ewww_image_optimizer_admin_init' );
130
+ // Checks to see if thumb regen or other similar operation is running via REST API.
131
+ add_action( 'rest_api_init', 'ewww_image_optimizer_restapi_compat_check' );
132
  // Legacy (non-AJAX) action hook for manually optimizing an image.
133
  add_action( 'admin_action_ewww_image_optimizer_manual_optimize', 'ewww_image_optimizer_manual' );
134
  // Legacy (non-AJAX) action hook for manually restoring a converted image.
159
  add_action( 'wr2x_retina_file_added', 'ewww_image_optimizer_retina', 20, 2 );
160
  // AJAX action hook for inserting WebP rewrite rules into .htaccess.
161
  add_action( 'wp_ajax_ewww_webp_rewrite', 'ewww_image_optimizer_webp_rewrite' );
162
+ // AJAX action hook for removing WebP rewrite rules from .htaccess.
163
+ add_action( 'wp_ajax_ewww_webp_unwrite', 'ewww_image_optimizer_webp_unwrite' );
164
  // AJAX action hook for manually optimizing/converting an image.
165
  add_action( 'wp_ajax_ewww_manual_optimize', 'ewww_image_optimizer_manual' );
166
  // AJAX action hook for manually restoring a converted image.
184
  // add_action( 'shutdown', 'ewwwio_memory_output' );.
185
  // Makes sure we flush the debug info to the log on shutdown.
186
  add_action( 'shutdown', 'ewww_image_optimizer_debug_log' );
187
+ // If ExactDN is enabled.
188
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
189
+ /**
190
+ * ExactDN class for parsing image urls and rewriting them.
191
+ */
192
+ require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-exactdn.php' );
193
+ }
194
  // If Alt WebP Rewriting is enabled.
195
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) ) {
196
  // Start an output buffer before any output starts.
197
+ add_action( 'template_redirect', 'ewww_image_optimizer_webp_buffer_start' );
198
  if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
199
  // Load the non-minified, non-inline version of the webp rewrite script.
200
  add_action( 'wp_enqueue_scripts', 'ewww_image_optimizer_webp_debug_script' );
238
  $default_headers = array(
239
  'Version' => 'Version',
240
  );
241
+
242
  $plugin_data = get_file_data( $plugin_file, $default_headers, 'plugin' );
243
+
244
  return $plugin_data;
245
  }
246
 
261
  }
262
 
263
  /**
264
+ * Starts an output buffer and registers the callback function to do WebP replacement.
265
  */
266
+ function ewww_image_optimizer_webp_buffer_start() {
267
+ ob_start( 'ewww_image_optimizer_filter_webp_page_output' );
268
  }
269
 
270
  /**
306
  'title',
307
  'translate',
308
  'sizes',
309
+ 'data-caption',
310
  'data-lazy-type',
311
  'data-attachment-id',
312
  'data-permalink',
315
  'data-image-meta',
316
  'data-image-title',
317
  'data-image-description',
318
+ 'data-event-trigger',
319
+ 'data-highlight-color',
320
+ 'data-highlight-opacity',
321
+ 'data-highlight-border-color',
322
+ 'data-highlight-border-width',
323
+ 'data-highlight-border-opacity',
324
+ 'data-no-lazy',
325
+ 'data-lazy',
326
+ 'data-large_image_width',
327
+ 'data-large_image_height',
328
  );
329
  foreach ( $attributes as $attribute ) {
330
  if ( $image->getAttribute( $attribute ) ) {
343
  */
344
  function ewww_image_optimizer_webp_srcset_replace( $srcset, $home_url, $valid_path ) {
345
  $srcset_urls = explode( ' ', $srcset );
346
+ $found_webp = false;
347
  if ( ewww_image_optimizer_iterable( $srcset_urls ) ) {
348
  ewwwio_debug_message( 'found srcset urls' );
349
  foreach ( $srcset_urls as $srcurl ) {
353
  $srcfilepath = ABSPATH . str_replace( $home_url, '', $srcurl );
354
  ewwwio_debug_message( "looking for srcurl on disk: $srcfilepath" );
355
  if ( $valid_path || is_file( $srcfilepath . '.webp' ) ) {
356
+ $srcset = preg_replace( "|$srcurl|", $srcurl . '.webp', $srcset );
357
  $found_webp = true;
358
  ewwwio_debug_message( "replacing $srcurl in $srcset" );
359
  }
382
  $nscript->setAttribute( 'data-webp-orig-file', $image->getAttribute( 'data-orig-file' ) . '.webp' );
383
  ewwwio_debug_message( "replacing $origfilepath in data-orig-file" );
384
  }
385
+ $nscript->setAttribute( 'data-orig-file', $image->getAttribute( 'data-orig-file' ) );
386
  }
387
  if ( $image->getAttribute( 'data-medium-file' ) ) {
388
  $mediumfilepath = ABSPATH . str_replace( $home_url, '', $image->getAttribute( 'data-medium-file' ) );
391
  $nscript->setAttribute( 'data-webp-medium-file', $image->getAttribute( 'data-medium-file' ) . '.webp' );
392
  ewwwio_debug_message( "replacing $mediumfilepath in data-medium-file" );
393
  }
394
+ $nscript->setAttribute( 'data-medium-file', $image->getAttribute( 'data-medium-file' ) );
395
  }
396
  if ( $image->getAttribute( 'data-large-file' ) ) {
397
  $largefilepath = ABSPATH . str_replace( $home_url, '', $image->getAttribute( 'data-large-file' ) );
400
  $nscript->setAttribute( 'data-webp-large-file', $image->getAttribute( 'data-large-file' ) . '.webp' );
401
  ewwwio_debug_message( "replacing $largefilepath in data-large-file" );
402
  }
403
+ $nscript->setAttribute( 'data-large-file', $image->getAttribute( 'data-large-file' ) );
404
+ }
405
+ }
406
+
407
+ /**
408
+ * Replaces images with the WooCommerce data attributes with their .webp derivatives.
409
+ *
410
+ * @param object $image A DOMElement (extension of DOMNode) representing an img element.
411
+ * @param object $nscript Passed by reference, a DOMElement that will be assigned the WooCommerce data attributes.
412
+ * @param string $home_url The 'home' url for the WordPress site.
413
+ * @param bool $valid_path True if a CDN path has been specified and matches the img element.
414
+ */
415
+ function ewww_image_optimizer_webp_woocommerce_replace( $image, &$nscript, $home_url, $valid_path ) {
416
+ if ( $image->getAttribute( 'data-large_image' ) ) {
417
+ $largefilepath = ABSPATH . str_replace( $home_url, '', $image->getAttribute( 'data-large_image' ) );
418
+ ewwwio_debug_message( "looking for data-large_image on disk: $largefilepath" );
419
+ if ( $valid_path || is_file( $largefilepath . '.webp' ) ) {
420
+ $nscript->setAttribute( 'data-webp-large_image', $image->getAttribute( 'data-large_image' ) . '.webp' );
421
+ ewwwio_debug_message( "replacing $largefilepath in data-large_image" );
422
+ }
423
+ $nscript->setAttribute( 'data-large_image', $image->getAttribute( 'data-large_image' ) );
424
+ }
425
+ if ( $image->getAttribute( 'data-src' ) ) {
426
+ $srcpath = ABSPATH . str_replace( $home_url, '', $image->getAttribute( 'data-src' ) );
427
+ ewwwio_debug_message( "looking for data-src on disk: $srcpath" );
428
+ if ( $valid_path || is_file( $srcpath . '.webp' ) ) {
429
+ $nscript->setAttribute( 'data-webp-src', $image->getAttribute( 'data-src' ) . '.webp' );
430
+ ewwwio_debug_message( "replacing $srcpath in data-src" );
431
+ }
432
+ $nscript->setAttribute( 'data-src', $image->getAttribute( 'data-src' ) );
433
  }
434
  }
435
 
446
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
447
  // Modify buffer here, and then return the updated code.
448
  if ( class_exists( 'DOMDocument' ) ) {
 
449
  $html = new DOMDocument;
450
+
451
  $libxml_previous_error_reporting = libxml_use_internal_errors( true );
452
+
453
  $html->formatOutput = false;
454
+ $html->encoding = 'utf-8';
455
  if ( defined( 'LIBXML_VERSION' ) && LIBXML_VERSION < 20800 ) {
456
  ewwwio_debug_message( 'libxml version too old for amp: ' . LIBXML_VERSION );
457
  return $buffer;
463
  $html->loadHTML( $buffer );
464
  ewwwio_debug_message( 'parsing AMP as html' );
465
  $html->encoding = 'utf-8';
466
+ $home_url = get_site_url();
467
+ $webp_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' );
468
  if ( ! is_array( $webp_paths ) ) {
469
  $webp_paths = array();
470
  }
471
  $home_relative_url = preg_replace( '/https?:/', '', $home_url );
472
+ $images = $html->getElementsByTagName( 'amp-img' );
473
  if ( ewww_image_optimizer_iterable( $images ) ) {
474
  foreach ( $images as $image ) {
475
  if ( 'amp-img' == $image->parentNode->tagName ) {
477
  }
478
  $srcset = '';
479
  ewwwio_debug_message( 'parsing an AMP image' );
480
+ $file = $image->getAttribute( 'src' );
481
  $valid_path = false;
482
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
483
  // Check for CDN paths within the img src attribute.
498
  $parent_image = $image->cloneNode();
499
  $parent_image->setAttribute( 'src', $file . '.webp' );
500
  if ( $image->getAttribute( 'srcset' ) ) {
501
+ $srcset = $image->getAttribute( 'srcset' );
502
  $srcset_webp = ewww_image_optimizer_webp_srcset_replace( $srcset, $home_url, $valid_path );
503
  if ( $srcset_webp ) {
504
  $parent_image->setAttribute( 'srcset', $srcset_webp );
543
  * @param string $buffer The full HTML page generated since the output buffer was started.
544
  * @return string The altered buffer containing the full page with WebP images inserted.
545
  */
546
+ function ewww_image_optimizer_filter_webp_page_output( $buffer ) {
547
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
548
  // If this is an admin page, don't filter it.
549
  if ( ( empty( $buffer ) || is_admin() ) ) {
581
  ewwwio_debug_message( 'AMP page processing' );
582
  return $buffer;
583
  }
584
+
585
  $html = new DOMDocument;
586
+
587
  $libxml_previous_error_reporting = libxml_use_internal_errors( true );
588
+
589
  $html->formatOutput = false;
590
+ $html->encoding = 'utf-8';
591
  if ( defined( 'LIBXML_VERSION' ) && LIBXML_VERSION < 20800 && ewww_image_optimizer_function_exists( 'mb_convert_encoding' ) ) {
592
  ewwwio_debug_message( 'libxml version: ' . LIBXML_VERSION );
593
  // Converts the buffer from utf-8 to html-entities.
599
  }
600
  if ( preg_match( '/<.DOCTYPE.+xhtml/', $buffer ) ) {
601
  $html->recover = true;
602
+ $xhtml_parse = $html->loadXML( $buffer );
603
  ewwwio_debug_message( 'parsing as xhtml' );
604
  } elseif ( empty( $xhtml_parse ) ) {
605
  $html->loadHTML( $buffer );
606
  ewwwio_debug_message( 'parsing as html' );
607
  }
608
  $html->encoding = 'utf-8';
609
+ $home_url = get_site_url();
610
+ ewwwio_debug_message( "home url: $home_url" );
611
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
612
+ global $exactdn;
613
+ $exactdn_domain = $exactdn->get_exactdn_domain();
614
+ $home_url_parts = $exactdn->parse_url( $home_url );
615
+ if ( ! empty( $home_url_parts['host'] ) && $exactdn_domain ) {
616
+ $home_url = str_replace( $home_url_parts['host'], $exactdn_domain, $home_url );
617
+ ewwwio_debug_message( "new home url: $home_url" );
618
+ }
619
+ }
620
  $webp_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' );
621
  if ( ! is_array( $webp_paths ) ) {
622
  $webp_paths = array();
623
  }
624
  $home_relative_url = preg_replace( '/https?:/', '', $home_url );
625
+ $images = $html->getElementsByTagName( 'img' );
626
  if ( ewww_image_optimizer_iterable( $images ) ) {
627
  foreach ( $images as $image ) {
628
  if ( 'noscript' == $image->parentNode->tagName ) {
629
  continue;
630
  }
631
+ $srcset = '';
632
+ $valid_path = false;
633
  ewwwio_debug_message( 'parsing an image' );
634
  $file = $image->getAttribute( 'src' );
 
635
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
636
  // Check for CDN paths within the img src attribute.
637
  foreach ( $webp_paths as $webp_path ) {
652
  $nscript->setAttribute( 'data-img', $file );
653
  $nscript->setAttribute( 'data-webp', $file . '.webp' );
654
  if ( $image->getAttribute( 'srcset' ) ) {
655
+ $srcset = $image->getAttribute( 'srcset' );
656
  $srcset_webp = ewww_image_optimizer_webp_srcset_replace( $srcset, $home_url, $valid_path );
657
  if ( $srcset_webp ) {
658
  $nscript->setAttribute( 'data-srcset-webp', $srcset_webp );
662
  if ( $image->getAttribute( 'data-orig-file' ) && $image->getAttribute( 'data-medium-file' ) && $image->getAttribute( 'data-large-file' ) ) {
663
  ewww_image_optimizer_webp_jetpack_replace( $image, $nscript, $home_url, $valid_path );
664
  }
665
+ if ( $image->getAttribute( 'data-large_image' ) && $image->getAttribute( 'data-src' ) ) {
666
+ ewww_image_optimizer_webp_woocommerce_replace( $image, $nscript, $home_url, $valid_path );
667
+ }
668
  ewww_image_optimizer_webp_attr_copy( $image, $nscript );
669
  $nscript->setAttribute( 'class', 'ewww_webp' );
670
  $image->parentNode->replaceChild( $nscript, $image );
672
  }
673
  // Look for NextGEN attributes that need to be altered.
674
  if ( empty( $file ) && $image->getAttribute( 'data-src' ) && $image->getAttribute( 'data-thumbnail' ) ) {
675
+ $file = $image->getAttribute( 'data-src' );
676
  $thumb = $image->getAttribute( 'data-thumbnail' );
677
  ewwwio_debug_message( "checking webp for ngg data-src: $file" );
678
  $filepath = ABSPATH . str_replace( $home_url, '', $file );
720
  // Hueman theme lazy-loads.
721
  if ( false && ! empty( $file ) && strpos( $file, 'image/gif;base64,R0lGOD' ) && $image->getAttribute( 'data-src' ) && $image->getAttribute( 'data-srcset' ) ) {
722
  $dummy = $file;
723
+ $file = $image->getAttribute( 'data-src' );
724
  ewwwio_debug_message( "checking webp for hueman data-src: $file" );
725
  $filepath = ABSPATH . str_replace( $home_url, '', $file );
726
  if ( ! $valid_path && ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
739
  $nscript->setAttribute( 'data-webp-src', $file . '.webp' );
740
  $image->setAttribute( 'src', $file );
741
  if ( $image->getAttribute( 'data-srcset' ) ) {
742
+ $srcset = $image->getAttribute( 'data-srcset' );
743
  $srcset_webp = ewww_image_optimizer_webp_srcset_replace( $srcset, $home_url, $valid_path );
744
  if ( $srcset_webp ) {
745
  $nscript->setAttribute( 'data-srcset-webp', $srcset_webp );
754
  }
755
  // Lazy Load plugin (and hopefully Cherry variant) and BJ Lazy Load.
756
  if ( false && ! empty( $file ) && ( strpos( $file, 'image/gif;base64,R0lGOD' ) || strpos( $file, 'lazy-load/images/1x1' ) ) && $image->getAttribute( 'data-lazy-src' ) && ! empty( $image->nextSibling ) && 'noscript' == $image->nextSibling->nodeName ) {
757
+ $dummy = $file;
758
  $nimage = $html->createElement( 'img' );
759
  $nimage->setAttribute( 'src', $dummy );
760
  $file = $image->getAttribute( 'data-lazy-src' );
773
  $nimage->setAttribute( 'data-lazy-img-src', $file );
774
  $nimage->setAttribute( 'data-lazy-webp-src', $file . '.webp' );
775
  if ( $image->getAttribute( 'srcset' ) ) {
776
+ $srcset = $image->getAttribute( 'srcset' );
777
  $srcset_webp = ewww_image_optimizer_webp_srcset_replace( $srcset, $home_url, $valid_path );
778
  if ( $srcset_webp ) {
779
  $nimage->setAttribute( 'data-srcset-webp', $srcset_webp );
781
  $nimage->setAttribute( 'data-srcset', $srcset );
782
  }
783
  if ( $image->getAttribute( 'data-lazy-srcset' ) ) {
784
+ $srcset = $image->getAttribute( 'data-lazy-srcset' );
785
  $srcset_webp = ewww_image_optimizer_webp_srcset_replace( $srcset, $home_url, $valid_path );
786
  if ( $srcset_webp ) {
787
  $nimage->setAttribute( 'data-lazy-srcset-webp', $srcset_webp );
819
  foreach ( $links as $link ) {
820
  ewwwio_debug_message( 'parsing a link' );
821
  if ( $link->getAttribute( 'data-src' ) && $link->getAttribute( 'data-thumbnail' ) ) {
822
+ $file = $link->getAttribute( 'data-src' );
823
+ $thumb = $link->getAttribute( 'data-thumbnail' );
824
  $valid_path = false;
825
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
826
  // Check the image for configured CDN paths.
851
  foreach ( $listitems as $listitem ) {
852
  ewwwio_debug_message( 'parsing a listitem' );
853
  if ( $listitem->getAttribute( 'data-title' ) === 'Slide' && ( $listitem->getAttribute( 'data-lazyload' ) || $listitem->getAttribute( 'data-thumb' ) ) ) {
854
+ $thumb = $listitem->getAttribute( 'data-thumb' );
855
  $valid_path = false;
856
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
857
  // Check the image for configured CDN paths.
887
  }
888
  } // End foreach().
889
  } // End if().
890
+ // WooCommerce thumbs listed as 'div' elements.
891
+ $divs = $html->getElementsByTagName( 'div' );
892
+ if ( ewww_image_optimizer_iterable( $divs ) ) {
893
+ foreach ( $divs as $div ) {
894
+ ewwwio_debug_message( 'parsing a div' );
895
+ if ( $div->getAttribute( 'class' ) && $div->getAttribute( 'data-thumb' ) && strpos( $div->getAttribute( 'class' ), 'woocommerce-product-gallery__image' ) !== false ) {
896
+ $thumb = $div->getAttribute( 'data-thumb' );
897
+ $valid_path = false;
898
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
899
+ // Check the image for configured CDN paths.
900
+ foreach ( $webp_paths as $webp_path ) {
901
+ if ( strpos( $file, $webp_path ) !== false ) {
902
+ $valid_path = true;
903
+ }
904
+ }
905
+ }
906
+ ewwwio_debug_message( "checking webp for WC data-thumb: $thumb" );
907
+ $thumbpath = ABSPATH . str_replace( $home_url, '', $thumb );
908
+ if ( $valid_path || is_file( $thumbpath . '.webp' ) ) {
909
+ ewwwio_debug_message( "found webp for WC data-thumb: $thumbpath" );
910
+ $div->setAttribute( 'data-webp-thumb', $thumb . '.webp' );
911
+ }
912
+ }
913
+ }
914
+ }
915
  // Video elements, looking for poster attributes that are images.
916
  $videos = $html->getElementsByTagName( 'video' );
917
  if ( ewww_image_optimizer_iterable( $videos ) ) {
918
  foreach ( $videos as $video ) {
919
  ewwwio_debug_message( 'parsing a video element' );
920
  if ( $link->getAttribute( 'poster' ) ) {
921
+ $file = $link->getAttribute( 'poster' );
922
  $valid_path = false;
923
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
924
  // Check the image for configured CDN paths.
1196
  require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
1197
  }
1198
  if ( is_multisite() && is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) ) {
1199
+ ewwwio_debug_message( 'saving network settings' );
1200
  // Set the common network settings if they have been POSTed.
1201
+ if ( isset( $_POST['option_page'] ) && false !== strpos( $_POST['option_page'], 'ewww_image_optimizer_options' ) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'ewww_image_optimizer_options-options' ) && current_user_can( 'manage_network_options' ) && ! get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) && false === strpos( $_POST['_wp_http_referer'], 'options-general' ) ) {
1202
+ ewwwio_debug_message( 'network-wide settings, no override' );
 
 
1203
  $_POST['ewww_image_optimizer_cloud_key'] = empty( $_POST['ewww_image_optimizer_cloud_key'] ) ? '' : $_POST['ewww_image_optimizer_cloud_key'];
1204
  update_site_option( 'ewww_image_optimizer_cloud_key', ewww_image_optimizer_cloud_key_sanitize( $_POST['ewww_image_optimizer_cloud_key'] ) );
1205
  $_POST['ewww_image_optimizer_debug'] = ( empty( $_POST['ewww_image_optimizer_debug'] ) ? false : true );
1240
  update_site_option( 'ewww_image_optimizer_exclude_paths', ewww_image_optimizer_exclude_paths_sanitize( $_POST['ewww_image_optimizer_exclude_paths'] ) );
1241
  $_POST['ewww_image_optimizer_enable_cloudinary'] = ( empty( $_POST['ewww_image_optimizer_enable_cloudinary'] ) ? false : true );
1242
  update_site_option( 'ewww_image_optimizer_enable_cloudinary', $_POST['ewww_image_optimizer_enable_cloudinary'] );
1243
+ $_POST['ewww_image_optimizer_exactdn'] = ( empty( $_POST['ewww_image_optimizer_exactdn'] ) ? false : true );
1244
+ update_site_option( 'ewww_image_optimizer_exactdn', $_POST['ewww_image_optimizer_exactdn'] );
1245
  $_POST['ewww_image_optimizer_maxmediawidth'] = empty( $_POST['ewww_image_optimizer_maxmediawidth'] ) ? 0 : $_POST['ewww_image_optimizer_maxmediawidth'];
1246
  update_site_option( 'ewww_image_optimizer_maxmediawidth', (int) $_POST['ewww_image_optimizer_maxmediawidth'] );
1247
  $_POST['ewww_image_optimizer_maxmediaheight'] = empty( $_POST['ewww_image_optimizer_maxmediaheight'] ) ? 0 : $_POST['ewww_image_optimizer_maxmediaheight'];
1273
  update_site_option( 'ewww_image_optimizer_allow_tracking', $_POST['ewww_image_optimizer_allow_tracking'] );
1274
  add_action( 'network_admin_notices', 'ewww_image_optimizer_network_settings_saved' );
1275
  } elseif ( isset( $_POST['ewww_image_optimizer_allow_multisite_override_active'] ) && current_user_can( 'manage_network_options' ) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'ewww_image_optimizer_options-options' ) ) {
1276
+ ewwwio_debug_message( 'network-wide settings, single-site overriding' );
1277
  $_POST['ewww_image_optimizer_allow_multisite_override'] = empty( $_POST['ewww_image_optimizer_allow_multisite_override'] ) ? false : true;
1278
  update_site_option( 'ewww_image_optimizer_allow_multisite_override', $_POST['ewww_image_optimizer_allow_multisite_override'] );
1279
  global $ewwwio_tracking;
1313
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_include_media_paths', 'boolval' );
1314
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_aux_paths', 'ewww_image_optimizer_aux_paths_sanitize' );
1315
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_exclude_paths', 'ewww_image_optimizer_exclude_paths_sanitize' );
1316
+ global $ewwwio_tracking;
1317
+ register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_allow_tracking', array( $ewwwio_tracking, 'check_for_settings_optin' ) );
1318
+ register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_enable_help', 'boolval' );
1319
+ register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_exactdn', 'boolval' );
1320
+ register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_resize_detection', 'boolval' );
1321
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxmediawidth', 'intval' );
1322
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxmediaheight', 'intval' );
1323
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxotherwidth', 'intval' );
1324
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_maxotherheight', 'intval' );
1325
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_resize_existing', 'boolval' );
 
1326
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_disable_resizes', 'ewww_image_optimizer_disable_resizes_sanitize' );
1327
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_disable_resizes_opt', 'ewww_image_optimizer_disable_resizes_sanitize' );
 
 
 
1328
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_disable_convert_links', 'boolval' );
1329
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_delete_originals', 'boolval' );
1330
  register_setting( 'ewww_image_optimizer_options', 'ewww_image_optimizer_jpg_to_png', 'boolval' );
1354
  // Alert user if multiple re-optimizations detected.
1355
  add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_reoptimization' );
1356
  add_action( 'admin_notices', 'ewww_image_optimizer_notice_reoptimization' );
1357
+ if ( ! empty( $_GET['page'] ) ) {
1358
+ if ( 'regenerate-thumbnails' == $_GET['page']
1359
+ || 'force-regenerate-thumbnails' == $_GET['page']
1360
+ || 'ajax-thumbnail-rebuild' == $_GET['page']
1361
+ || 'regenerate_thumbnails_advanced' == $_GET['page']
1362
+ ) {
1363
+ // Add a notice for thumb regeneration.
1364
+ add_action( 'admin_notices', 'ewww_image_optimizer_thumbnail_regen_notice' );
1365
+ }
1366
+ }
1367
  ewww_image_optimizer_ajax_compat_check();
1368
  ewwwio_memory( __FUNCTION__ );
1369
  }
1413
  if ( ! wp_doing_ajax() ) {
1414
  return;
1415
  }
1416
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1417
+ // Check for (Force) Regenerate Thumbnails action (includes MLP regenerate).
1418
  if ( ! empty( $_REQUEST['action'] ) ) {
1419
  if ( 'regeneratethumbnail' == $_REQUEST['action'] ||
1420
  'meauh_save_image' == $_REQUEST['action'] ||
1421
  'hotspot_save' == $_REQUEST['action']
1422
  ) {
1423
+ ewwwio_debug_message( 'doing regeneratethumbnail' );
1424
  ewww_image_optimizer_image_sizes( false );
1425
+ return;
1426
  }
1427
  }
1428
  // Check for other MLP actions, including multi-regen.
1429
  if ( ! empty( $_REQUEST['action'] ) && class_exists( 'MaxGalleriaMediaLib' ) && ( 'regen_mlp_thumbnails' == $_REQUEST['action'] || 'move_media' == $_REQUEST['action'] || 'copy_media' == $_REQUEST['action'] || 'maxgalleria_rename_image' == $_REQUEST['action'] ) ) {
1430
+ ewwwio_debug_message( 'doing regen_mlp_thumbnails' );
1431
  ewww_image_optimizer_image_sizes( false );
1432
+ return;
1433
  }
1434
  // Check for MLP upload.
1435
  if ( ! empty( $_REQUEST['action'] ) && class_exists( 'MaxGalleriaMediaLib' ) && ! empty( $_REQUEST['nonce'] ) && 'upload_attachment' == $_REQUEST['action'] ) {
1436
+ ewwwio_debug_message( 'doing maxgalleria upload' );
1437
  ewww_image_optimizer_image_sizes( false );
1438
+ return;
1439
  }
1440
  }
1441
 
1454
  }
1455
  }
1456
 
1457
+ /**
1458
+ * Checks to see if this is a REST API request, and whether the WP_Image_Editor hooks should be undone.
1459
+ *
1460
+ * @since 4.0.6
1461
+ */
1462
+ function ewww_image_optimizer_restapi_compat_check() {
1463
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1464
+ if ( ! empty( $GLOBALS['wp']->query_vars['rest_route'] ) && false !== strpos( $GLOBALS['wp']->query_vars['rest_route'], '/regenerate-thumbnails' ) ) {
1465
+ ewwwio_debug_message( 'doing regenerate-thumbnails via REST' );
1466
+ ewww_image_optimizer_image_sizes( false );
1467
+ return;
1468
+ }
1469
+ }
1470
+
1471
  /**
1472
  * Disables all the local tools by setting their constants to false.
1473
  */
1488
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_PNGQUANT' ) ) {
1489
  define( 'EWWW_IMAGE_OPTIMIZER_PNGQUANT', false );
1490
  }
1491
+ if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_CWEBP' ) ) {
1492
+ define( 'EWWW_IMAGE_OPTIMIZER_CWEBP', false );
1493
  }
1494
  ewwwio_memory( __FUNCTION__ );
1495
  }
1570
  if ( strpos( $column_collate, 'utf8' ) === false ) {
1571
  ewwwio_debug_message( 'converting path column to utf8' );
1572
  $wpdb->query( "ALTER TABLE $wpdb->ewwwio_images CHANGE path path BLOB" );
1573
+ if ( $wpdb->has_cap( 'utf8mb4_520' ) && strpos( $db_collation, 'utf8mb4' ) ) {
1574
  ewwwio_debug_message( 'using mb4 version 5.20' );
1575
  $wpdb->query( "ALTER TABLE $wpdb->ewwwio_images DROP INDEX path_image_size" );
1576
  $wpdb->query( "ALTER TABLE $wpdb->ewwwio_images CONVERT TO CHARACTER SET utf8mb4, CHANGE path path TEXT" );
1755
  echo "<div id='ewww-image-optimizer-settings-saved' class='updated fade'><p><strong>" . esc_html__( 'Settings saved', 'ewww-image-optimizer' ) . '.</strong></p></div>';
1756
  }
1757
 
1758
+ /**
1759
+ * Informs the user about optimization during thumbnail regeneration.
1760
+ */
1761
+ function ewww_image_optimizer_thumbnail_regen_notice() {
1762
+ echo "<div id='ewww-image-optimizer-thumb-regen-notice' class='notice notice-info is-dismissible'><p><strong>" . esc_html__( 'New thumbnails will be optimized by the EWWW Image Optimizer as they are generated. You may wish to disable the plugin and run a bulk optimize later to speed up the process.', 'ewww-image-optimizer' ) . '</strong>';
1763
+ echo '&nbsp;<a href="http://docs.ewww.io/article/49-regenerate-thumbnails" target="_blank" data-beacon-article="5a0f84ed2c7d3a272c0dc801">' . esc_html__( 'Learn more.', 'ewww-image-optimizer' ) . '</a></p></div>';
1764
+ }
1765
+
1766
  /**
1767
  * Alert the user when 5 images have been re-optimized more than 10 times.
1768
  *
1790
  // Do a check for 10+ optimizations on 5+ images.
1791
  if ( ! empty( $reoptimized ) && $reoptimized > 5 ) {
1792
  $debugging_page = admin_url( 'upload.php?page=ewww-image-optimizer-dynamic-debug' );
1793
+ $reset_page = wp_nonce_url( $_SERVER['REQUEST_URI'], 'reset_reoptimization_counters', 'ewww_reset_reopt_nonce' );
1794
  // Display an alert, and let the user reset the warning if they wish.
1795
  echo "<div id='ewww-image-optimizer-warning-reoptimizations' class='error'><p>" .
1796
  sprintf(
1870
  remove_filter( 'wp_generate_attachment_metadata', 'wr2x_wp_generate_attachment_metadata' );
1871
  add_filter( 'wp_generate_attachment_metadata', 'ewww_image_optimizer_retina_wrapper' );
1872
  }
1873
+ if ( class_exists( 'Meow_WR2X_Core' ) ) {
1874
+ global $wr2x_core;
1875
+ if ( is_object( $wr2x_core ) ) {
1876
+ ewwwio_debug_message( 'retina object found' );
1877
+ remove_filter( 'wp_generate_attachment_metadata', array( $wr2x_core, 'wp_generate_attachment_metadata' ) );
1878
+ add_filter( 'wp_generate_attachment_metadata', 'ewww_image_optimizer_retina_wrapper' );
1879
+ }
1880
+ }
1881
  return $metadata;
1882
  }
1883
 
1928
  */
1929
  function ewww_image_optimizer_retina_wrapper( $meta ) {
1930
  remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
1931
+ if ( class_exists( 'Meow_WR2X_Core' ) ) {
1932
+ global $wr2x_core;
1933
+ if ( is_object( $wr2x_core ) ) {
1934
+ $meta = $wr2x_core->wp_generate_attachment_metadata( $meta );
1935
+ }
1936
+ } else {
1937
+ $meta = wr2x_wp_generate_attachment_metadata( $meta );
1938
+ }
1939
  add_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
1940
  return $meta;
1941
  }
1949
  function ewww_image_optimizer_image_sizes_advanced( $sizes ) {
1950
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1951
  $disabled_sizes = get_option( 'ewww_image_optimizer_disable_resizes' );
1952
+ $flipped = false;
1953
  if ( ! empty( $disabled_sizes ) ) {
1954
  if ( ! empty( $sizes[0] ) ) {
1955
+ $sizes = array_flip( $sizes );
1956
  $flipped = true;
1957
  }
1958
  if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
1982
  function ewww_image_optimizer_fallback_sizes( $sizes ) {
1983
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
1984
  $disabled_sizes = get_option( 'ewww_image_optimizer_disable_resizes' );
1985
+ $flipped = false;
1986
  if ( ! empty( $disabled_sizes ) ) {
1987
  if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
1988
  ewwwio_debug_message( print_r( $sizes, true ) );
2067
  function ewww_image_optimizer_w3tc_update_files( $files ) {
2068
  global $ewww_attachment;
2069
  list( $file, $upload_path ) = ewww_image_optimizer_attachment_path( $ewww_attachment['meta'], $ewww_attachment['id'] );
 
2070
  if ( function_exists( 'w3_upload_info' ) ) {
2071
  $upload_info = w3_upload_info();
2072
  } else {
2073
  $upload_info = ewww_image_optimizer_upload_info();
2074
  }
2075
+ $file_info = array();
2076
  if ( $upload_info ) {
2077
+ $remote_file = ltrim( $upload_info['baseurlpath'] . $ewww_attachment['meta']['file'], '/' );
2078
+ $home_url = get_site_url();
2079
  $original_url = $home_url . $file;
2080
+ $file_info[] = array(
2081
+ 'local_path' => $file,
2082
+ 'remote_path' => $remote_file,
2083
  'original_url' => $original_url,
2084
  );
2085
+ $files = array_merge( $files, $file_info );
2086
  }
2087
  return $files;
2088
  }
2152
  $i = 0;
2153
  while ( $i < $count &&
2154
  $attachment = $ewwwdb->get_row( "SELECT id,path FROM $ewwwdb->ewwwio_images WHERE pending=1 LIMIT 1", ARRAY_A )
2155
+ ) {
2156
  // If the nonce has changed since we started, bail out, since that means another aux scan/optimize is running.
2157
  // Do a direct query using $wpdb, because get_option() is cached.
2158
  $current_nonce = $wpdb->get_var( "SELECT option_value FROM $wpdb->options WHERE option_name = 'ewww_image_optimizer_aux_resume'" );
2208
  * Removes rules from .htaccess file added by EWWW for WebP rewriting.
2209
  */
2210
  function ewww_image_optimizer_uninstall() {
2211
+ if ( ewwwio_extract_from_markers( ewww_image_optimizer_htaccess_path(), 'EWWWIO' ) ) {
2212
+ insert_with_markers( ewww_image_optimizer_htaccess_path(), 'EWWWIO', '' );
2213
+ }
2214
  }
2215
 
2216
  /**
2222
  require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
2223
  }
2224
  if ( is_multisite() && is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) ) {
 
2225
  $permissions = apply_filters( 'ewww_image_optimizer_superadmin_permissions', '' );
2226
+ // Add options page to the settings menu.
2227
  $ewww_network_options_page = add_submenu_page(
2228
+ 'settings.php', // Slug of parent.
2229
+ 'EWWW Image Optimizer', // Page Title.
2230
+ 'EWWW Image Optimizer', // Menu title.
2231
+ $permissions, // Capability.
2232
+ EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE, // Slug.
2233
  'ewww_image_optimizer_network_options' // Function to call.
2234
  );
2235
  }
2240
  */
2241
  function ewww_image_optimizer_resize_dup_check() {
2242
  $meta = wp_get_attachment_metadata( 34 );
2243
+
2244
  list( $file, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, 34 );
2245
+
2246
+ $editor = wp_get_image_editor( $file );
2247
  $resized_image = $editor->resize( 150, 150, true );
2248
+ $new_file = $editor->generate_filename();
2249
  echo $new_file;
2250
  if ( is_file( $new_file ) ) {
2251
  echo '<br>file already exists<br>';
2270
  if ( ! is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) ) {
2271
  // Add options page to the settings menu.
2272
  $ewww_options_page = add_options_page(
2273
+ 'EWWW Image Optimizer', // Page title.
2274
+ 'EWWW Image Optimizer', // Menu title.
2275
+ apply_filters( 'ewww_image_optimizer_admin_permissions', 'manage_options' ), // Capability.
2276
+ EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE, // Slug.
2277
  'ewww_image_optimizer_options' // Function to call.
2278
  );
2279
  } else {
2280
  // Add options page to the single-site settings menu.
2281
  $ewww_options_page = add_options_page(
2282
+ 'EWWW Image Optimizer', // Page title.
2283
+ 'EWWW Image Optimizer', // Menu title.
2284
+ apply_filters( 'ewww_image_optimizer_admin_permissions', 'manage_options' ), // Capability.
2285
+ EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE, // Slug.
2286
  'ewww_image_optimizer_network_singlesite_options' // Function to call.
2287
  );
2288
  }
2291
  add_media_page( esc_html__( 'Dynamic Image Debugging', 'ewww-image-optimizer' ), esc_html__( 'Dynamic Image Debugging', 'ewww-image-optimizer' ), $permissions, 'ewww-image-optimizer-dynamic-debug', 'ewww_image_optimizer_dynamic_image_debug' );
2292
  // Add Image Queue Debugging to allow clearing and checking queues.
2293
  add_media_page( esc_html__( 'Image Queue Debugging', 'ewww-image-optimizer' ), esc_html__( 'Image Queue Debugging', 'ewww-image-optimizer' ), $permissions, 'ewww-image-optimizer-queue-debug', 'ewww_image_optimizer_image_queue_debug' );
2294
+ // Add debug log page for viewing the log on hosts where you can't directly access it.
2295
+ add_media_page( esc_html__( 'EWWW IO Debug Log', 'ewww-image-optimizer' ), esc_html__( 'EWWW IO Debug Log', 'ewww-image-optimizer' ), $permissions, 'ewww-image-optimizer-debug-log-display', 'ewww_image_optimizer_debug_log_display' );
2296
  }
2297
  if ( is_plugin_active( 'image-store/ImStore.php' ) || is_plugin_active_for_network( 'image-store/ImStore.php' ) ) {
2298
  // Adds an optimize page for Image Store galleries and images.
2299
+ $ims_menu = 'edit.php?post_type=ims_gallery';
2300
  $ewww_ims_page = add_submenu_page( $ims_menu, esc_html__( 'Image Store Optimize', 'ewww-image-optimizer' ), esc_html__( 'Optimize', 'ewww-image-optimizer' ), 'ims_change_settings', 'ewww-ims-optimize', 'ewww_image_optimizer_ims' );
2301
  }
2302
  }
2312
  $file_info = pathinfo( $retina_path );
2313
  $extension = '.' . $file_info['extension'];
2314
  preg_match( '/-(\d+x\d+)@2x$/', $file_info['filename'], $fileresize );
2315
+ $dimensions = explode( 'x', $fileresize[1] );
2316
  $no_ext_path = $file_info['dirname'] . '/' . preg_replace( '/\d+x\d+@2x$/', '', $file_info['filename'] ) . $dimensions[0] * 2 . 'x' . $dimensions[1] * 2 . '-tmp';
2317
+ $temp_path = $no_ext_path . $extension;
2318
  ewwwio_debug_message( "temp path: $temp_path" );
2319
  // Check for any orphaned webp retina images, and fix their paths.
2320
  ewwwio_debug_message( "retina path: $retina_path" );
2337
  // Replace the 'temp' path in the database with the real path.
2338
  $ewwwdb->update( $ewwwdb->ewwwio_images,
2339
  array(
2340
+ 'path' => ewww_image_optimizer_relative_path_remove( $retina_path ),
2341
  'attachment_id' => $id,
2342
+ 'gallery' => 'media',
2343
  ),
2344
  array(
2345
  'id' => $optimized_query['id'],
2365
  echo '<p>' . esc_html__( 'Choose a gallery or', 'ewww-image-optimizer' ) . " <a href='upload.php?page=ewww-image-optimizer-bulk&ids=$gallery_string'>" . esc_html__( 'optimize all galleries', 'ewww-image-optimizer' ) . '</a></p>';
2366
  echo '<table class="wp-list-table widefat media" cellspacing="0"><thead><tr><th>' . esc_html__( 'Gallery ID', 'ewww-image-optimizer' ) . '</th><th>' . esc_html__( 'Gallery Name', 'ewww-image-optimizer' ) . '</th><th>' . esc_html__( 'Images', 'ewww-image-optimizer' ) . '</th><th>' . esc_html__( 'Image Optimizer', 'ewww-image-optimizer' ) . '</th></tr></thead>';
2367
  foreach ( $galleries as $gid ) {
2368
+ $image_count = $wpdb->get_var( $wpdb->prepare( "SELECT count(ID) FROM $wpdb->posts WHERE post_type = 'ims_image' AND post_mime_type LIKE %s AND post_parent = %d", '%image%', $gid ) );
2369
  $gallery_name = get_the_title( $gid );
2370
  echo "<tr><td>$gid</td>";
2371
  echo "<td><a href='edit.php?post_type=ims_gallery&page=ewww-ims-optimize&ewww_gid=$gid'>$gallery_name</a></td>";
2377
  echo '<p>' . esc_html__( 'No galleries found', 'ewww-image-optimizer' ) . '</p>';
2378
  }
2379
  } else {
2380
+ $gid = (int) $_REQUEST['ewww_gid'];
2381
+ $attachments = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type = 'ims_image' AND post_mime_type LIKE %s AND post_parent = %d ORDER BY ID", '%image%', $gid ) );
2382
  if ( ewww_image_optimizer_iterable( $attachments ) ) {
2383
  echo "<p><a href='upload.php?page=ewww-image-optimizer-bulk&ids=$gid'>" . esc_html__( 'Optimize Gallery', 'ewww-image-optimizer' ) . '</a></p>';
2384
  echo '<table class="wp-list-table widefat media" cellspacing="0"><thead><tr><th>ID</th><th>&nbsp;</th><th>' . esc_html__( 'Title', 'ewww-image-optimizer' ) . '</th><th>' . esc_html__( 'Gallery', 'ewww-image-optimizer' ) . '</th><th>' . esc_html__( 'Image Optimizer', 'ewww-image-optimizer' ) . '</th></tr></thead>';
2388
  if ( empty( $meta['_wp_attachment_metadata'] ) ) {
2389
  continue;
2390
  }
2391
+ $meta = maybe_unserialize( $meta['_wp_attachment_metadata'][0] );
2392
+ $image_name = get_the_title( $id );
2393
  $gallery_name = get_the_title( $gid );
2394
+ $image_url = esc_url( $meta['sizes']['mini']['url'] );
2395
  ?>
2396
  <tr
2397
  <?php
2460
  if ( function_exists( 'wp_add_inline_script' ) && ( ! defined( 'EWWW_IMAGE_OPTIMIZER_WEBP_INLINE_FALLBACK' ) || ! EWWW_IMAGE_OPTIMIZER_WEBP_INLINE_FALLBACK ) ) {
2461
  ewwwio_debug_message( 'loading webp script with wp_add_inline_script' );
2462
  wp_add_inline_script( 'jquery-migrate',
2463
+ 'function check_webp_feature(t,e){var a={alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"},i=!1,r=new Image;r.onload=function(){var t=r.width>0&&r.height>0;i=!0,e(t)},r.onerror=function(){i=!1,e(!1)},r.src="data:image/webp;base64,"+a[t]}function ewww_load_images(t){jQuery(document).arrive(".ewww_webp",function(){ewww_load_images(t)}),function(e){function a(t,a){for(var r=["align","alt","border","crossorigin","height","hspace","ismap","longdesc","usemap","vspace","width","accesskey","class","contenteditable","contextmenu","dir","draggable","dropzone","hidden","id","lang","spellcheck","style","tabindex","title","translate","sizes","data-caption","data-attachment-id","data-permalink","data-orig-size","data-comments-opened","data-image-meta","data-image-title","data-image-description","data-event-trigger","data-highlight-color","data-highlight-opacity","data-highlight-border-color","data-highlight-border-width","data-highlight-border-opacity","data-no-lazy","data-lazy","data-large_image_width","data-large_image_height"],n=0,o=r.length;n<o;n++){var s=e(t).attr(i+r[n]);void 0!==s&&!1!==s&&e(a).attr(r[n],s)}return a}var i="data-";t&&(e(".batch-image img, .image-wrapper a, .ngg-pro-masonry-item a").each(function(){var t=e(this).attr("data-webp");void 0!==t&&!1!==t&&e(this).attr("data-src",t),void 0!==(t=e(this).attr("data-webp-thumbnail"))&&!1!==t&&e(this).attr("data-thumbnail",t)}),e(".image-wrapper a, .ngg-pro-masonry-item a").each(function(){var t=e(this).attr("data-webp");void 0!==t&&!1!==t&&e(this).attr("href",t)}),e(".rev_slider ul li").each(function(){var t=e(this).attr("data-webp-thumb");void 0!==t&&!1!==t&&e(this).attr("data-thumb",t);for(var a=1;a<11;)void 0!==(t=e(this).attr("data-webp-param"+a))&&!1!==t&&e(this).attr("data-param"+a,t),a++}),e(".rev_slider img").each(function(){var t=e(this).attr("data-webp-lazyload");void 0!==t&&!1!==t&&e(this).attr("data-lazyload",t)}),e("div.woocommerce-product-gallery__image").each(function(){var t=e(this).attr("data-webp-thumb");void 0!==t&&!1!==t&&e(this).attr("data-thumb",t)})),e("img.ewww_webp_lazy_retina").each(function(){if(t)void 0!==(a=e(this).attr("data-srcset-webp"))&&!1!==a&&e(this).attr("data-srcset",a);else{var a=e(this).attr("data-srcset-img");void 0!==a&&!1!==a&&e(this).attr("data-srcset",a)}e(this).removeClass("ewww_webp_lazy_retina")}),e("video").each(function(){if(t)void 0!==(a=e(this).attr("data-poster-webp"))&&!1!==a&&e(this).attr("poster",a);else{var a=e(this).attr("data-poster-image");void 0!==a&&!1!==a&&e(this).attr("poster",a)}}),e("img.ewww_webp_lazy_load").each(function(){if(t)e(this).attr("data-lazy-src",e(this).attr("data-lazy-webp-src")),void 0!==(a=e(this).attr("data-srcset-webp"))&&!1!==a&&e(this).attr("srcset",a),void 0!==(a=e(this).attr("data-lazy-srcset-webp"))&&!1!==a&&e(this).attr("data-lazy-srcset",a);else{e(this).attr("data-lazy-src",e(this).attr("data-lazy-img-src"));var a=e(this).attr("data-srcset");void 0!==a&&!1!==a&&e(this).attr("srcset",a),void 0!==(a=e(this).attr("data-lazy-srcset-img"))&&!1!==a&&e(ewww_img).attr("data-lazy-srcset",a)}e(this).removeClass("ewww_webp_lazy_load")}),e(".ewww_webp_lazy_hueman").each(function(){var i=document.createElement("img");if(e(i).attr("src",e(this).attr("data-src")),t)e(i).attr("data-src",e(this).attr("data-webp-src")),void 0!==(r=e(this).attr("data-srcset-webp"))&&!1!==r&&e(i).attr("data-srcset",r);else{e(i).attr("data-src",e(this).attr("data-img"));var r=e(this).attr("data-srcset-img");void 0!==r&&!1!==r&&e(i).attr("data-srcset",r)}i=a(this,i),e(this).after(i),e(this).removeClass("ewww_webp_lazy_hueman")}),e(".ewww_webp").each(function(){var i=document.createElement("img");if(t)e(i).attr("src",e(this).attr("data-webp")),void 0!==(r=e(this).attr("data-srcset-webp"))&&!1!==r&&e(i).attr("srcset",r),void 0!==(r=e(this).attr("data-webp-orig-file"))&&!1!==r?e(i).attr("data-orig-file",r):void 0!==(r=e(this).attr("data-orig-file"))&&!1!==r&&e(i).attr("data-orig-file",r),void 0!==(r=e(this).attr("data-webp-medium-file"))&&!1!==r?e(i).attr("data-medium-file",r):void 0!==(r=e(this).attr("data-medium-file"))&&!1!==r&&e(i).attr("data-medium-file",r),void 0!==(r=e(this).attr("data-webp-large-file"))&&!1!==r?e(i).attr("data-large-file",r):void 0!==(r=e(this).attr("data-large-file"))&&!1!==r&&e(i).attr("data-large-file",r),void 0!==(r=e(this).attr("data-webp-large_image"))&&!1!==r?e(i).attr("data-large_image",r):void 0!==(r=e(this).attr("data-large_image"))&&!1!==r&&e(i).attr("data-large_image",r),void 0!==(r=e(this).attr("data-webp-src"))&&!1!==r?e(i).attr("data-src",r):void 0!==(r=e(this).attr("data-src"))&&!1!==r&&e(i).attr("data-src",r);else{e(i).attr("src",e(this).attr("data-img"));var r=e(this).attr("data-srcset-img");void 0!==r&&!1!==r&&e(i).attr("srcset",r),void 0!==(r=e(this).attr("data-orig-file"))&&!1!==r&&e(i).attr("data-orig-file",r),void 0!==(r=e(this).attr("data-medium-file"))&&!1!==r&&e(i).attr("data-medium-file",r),void 0!==(r=e(this).attr("data-large-file"))&&!1!==r&&e(i).attr("data-large-file",r),void 0!==(r=e(this).attr("data-large_image"))&&!1!==r&&e(i).attr("data-large_image",r),void 0!==(r=e(this).attr("data-src"))&&!1!==r&&e(i).attr("data-src",r)}i=a(this,i),e(this).after(i),e(this).removeClass("ewww_webp")})}(jQuery),jQuery.fn.isotope&&jQuery.fn.imagesLoaded&&(jQuery(".fusion-posts-container-infinite").imagesLoaded(function(){jQuery(".fusion-posts-container-infinite").hasClass("isotope")&&jQuery(".fusion-posts-container-infinite").isotope()}),jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").imagesLoaded(function(){jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").isotope()}))}var Arrive=function(t,e,a){"use strict";function i(t,e,a){o.addMethod(e,a,t.unbindEvent),o.addMethod(e,a,t.unbindEventWithSelectorOrCallback),o.addMethod(e,a,t.unbindEventWithSelectorAndCallback)}function r(t){t.arrive=l.bindEvent,i(l,t,"unbindArrive"),t.leave=c.bindEvent,i(c,t,"unbindLeave")}if(t.MutationObserver&&"undefined"!=typeof HTMLElement){var n=0,o=function(){var e=HTMLElement.prototype.matches||HTMLElement.prototype.webkitMatchesSelector||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelector;return{matchesSelector:function(t,a){return t instanceof HTMLElement&&e.call(t,a)},addMethod:function(t,e,a){var i=t[e];t[e]=function(){return a.length==arguments.length?a.apply(this,arguments):"function"==typeof i?i.apply(this,arguments):void 0}},callCallbacks:function(t){for(var e,a=0;e=t[a];a++)e.callback.call(e.elem)},checkChildNodesRecursively:function(t,e,a,i){for(var r,n=0;r=t[n];n++)a(r,e,i)&&i.push({callback:e.callback,elem:r}),r.childNodes.length>0&&o.checkChildNodesRecursively(r.childNodes,e,a,i)},mergeArrays:function(t,e){var a,i={};for(a in t)i[a]=t[a];for(a in e)i[a]=e[a];return i},toElementsArray:function(e){return void 0===e||"number"==typeof e.length&&e!==t||(e=[e]),e}}}(),s=function(){var t=function(){this._eventsBucket=[],this._beforeAdding=null,this._beforeRemoving=null};return t.prototype.addEvent=function(t,e,a,i){var r={target:t,selector:e,options:a,callback:i,firedElems:[]};return this._beforeAdding&&this._beforeAdding(r),this._eventsBucket.push(r),r},t.prototype.removeEvent=function(t){for(var e,a=this._eventsBucket.length-1;e=this._eventsBucket[a];a--)t(e)&&(this._beforeRemoving&&this._beforeRemoving(e),this._eventsBucket.splice(a,1))},t.prototype.beforeAdding=function(t){this._beforeAdding=t},t.prototype.beforeRemoving=function(t){this._beforeRemoving=t},t}(),d=function(e,i){var r=new s,n=this,d={fireOnAttributesModification:!1};return r.beforeAdding(function(a){var r,o=a.target;a.selector,a.callback;o!==t.document&&o!==t||(o=document.getElementsByTagName("html")[0]),r=new MutationObserver(function(t){i.call(this,t,a)});var s=e(a.options);r.observe(o,s),a.observer=r,a.me=n}),r.beforeRemoving(function(t){t.observer.disconnect()}),this.bindEvent=function(t,e,a){e=o.mergeArrays(d,e);for(var i=o.toElementsArray(this),n=0;n<i.length;n++)r.addEvent(i[n],t,e,a)},this.unbindEvent=function(){var t=o.toElementsArray(this);r.removeEvent(function(e){for(var i=0;i<t.length;i++)if(this===a||e.target===t[i])return!0;return!1})},this.unbindEventWithSelectorOrCallback=function(t){var e,i=o.toElementsArray(this),n=t;e="function"==typeof t?function(t){for(var e=0;e<i.length;e++)if((this===a||t.target===i[e])&&t.callback===n)return!0;return!1}:function(e){for(var r=0;r<i.length;r++)if((this===a||e.target===i[r])&&e.selector===t)return!0;return!1},r.removeEvent(e)},this.unbindEventWithSelectorAndCallback=function(t,e){var i=o.toElementsArray(this);r.removeEvent(function(r){for(var n=0;n<i.length;n++)if((this===a||r.target===i[n])&&r.selector===t&&r.callback===e)return!0;return!1})},this},l=new function(){function t(t,e,i){if(o.matchesSelector(t,e.selector)&&(t._id===a&&(t._id=n++),-1==e.firedElems.indexOf(t._id))){if(e.options.onceOnly){if(0!==e.firedElems.length)return;e.me.unbindEventWithSelectorAndCallback.call(e.target,e.selector,e.callback)}e.firedElems.push(t._id),i.push({callback:e.callback,elem:t})}}var e={fireOnAttributesModification:!1,onceOnly:!1,existing:!1},i=(l=new d(function(t){var e={attributes:!1,childList:!0,subtree:!0};return t.fireOnAttributesModification&&(e.attributes=!0),e},function(e,a){e.forEach(function(e){var i=e.addedNodes,r=e.target,n=[];null!==i&&i.length>0?o.checkChildNodesRecursively(i,a,t,n):"attributes"===e.type&&t(r,a,n)&&n.push({callback:a.callback,elem:node}),o.callCallbacks(n)})})).bindEvent;return l.bindEvent=function(t,a,r){void 0===r?(r=a,a=e):a=o.mergeArrays(e,a);var n=o.toElementsArray(this);if(a.existing){for(var s=[],d=0;d<n.length;d++)for(var l=n[d].querySelectorAll(t),c=0;c<l.length;c++)s.push({callback:r,elem:l[c]});if(a.onceOnly&&s.length)return r.call(s[0].elem);setTimeout(o.callCallbacks,1,s)}i.call(this,t,a,r)},l},c=new function(){function t(t,e){return o.matchesSelector(t,e.selector)}var e={},a=(c=new d(function(t){return{childList:!0,subtree:!0}},function(e,a){e.forEach(function(e){var i=e.removedNodes,r=(e.target,[]);null!==i&&i.length>0&&o.checkChildNodesRecursively(i,a,t,r),o.callCallbacks(r)})})).bindEvent;return c.bindEvent=function(t,i,r){void 0===r?(r=i,i=e):i=o.mergeArrays(e,i),a.call(this,t,i,r)},c};e&&r(e.fn),r(HTMLElement.prototype),r(NodeList.prototype),r(HTMLCollection.prototype),r(HTMLDocument.prototype),r(Window.prototype);var h={};return i(l,h,"unbindAllArrive"),i(c,h,"unbindAllLeave"),h}}(window,"undefined"==typeof jQuery?null:jQuery,void 0);"undefined"!=typeof jQuery&&check_webp_feature("alpha",ewww_load_images);'
2464
  );
2465
  }
2466
  }
2474
  ewwwio_debug_message( 'loading webp script without wp_add_inline_script' );
2475
  ?>
2476
  <script>
2477
+ function check_webp_feature(t,e){var a={alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"},i=!1,r=new Image;r.onload=function(){var t=r.width>0&&r.height>0;i=!0,e(t)},r.onerror=function(){i=!1,e(!1)},r.src="data:image/webp;base64,"+a[t]}function ewww_load_images(t){jQuery(document).arrive(".ewww_webp",function(){ewww_load_images(t)}),function(e){function a(t,a){for(var r=["align","alt","border","crossorigin","height","hspace","ismap","longdesc","usemap","vspace","width","accesskey","class","contenteditable","contextmenu","dir","draggable","dropzone","hidden","id","lang","spellcheck","style","tabindex","title","translate","sizes","data-caption","data-attachment-id","data-permalink","data-orig-size","data-comments-opened","data-image-meta","data-image-title","data-image-description","data-event-trigger","data-highlight-color","data-highlight-opacity","data-highlight-border-color","data-highlight-border-width","data-highlight-border-opacity","data-no-lazy","data-lazy","data-large_image_width","data-large_image_height"],n=0,o=r.length;n<o;n++){var s=e(t).attr(i+r[n]);void 0!==s&&!1!==s&&e(a).attr(r[n],s)}return a}var i="data-";t&&(e(".batch-image img, .image-wrapper a, .ngg-pro-masonry-item a").each(function(){var t=e(this).attr("data-webp");void 0!==t&&!1!==t&&e(this).attr("data-src",t),void 0!==(t=e(this).attr("data-webp-thumbnail"))&&!1!==t&&e(this).attr("data-thumbnail",t)}),e(".image-wrapper a, .ngg-pro-masonry-item a").each(function(){var t=e(this).attr("data-webp");void 0!==t&&!1!==t&&e(this).attr("href",t)}),e(".rev_slider ul li").each(function(){var t=e(this).attr("data-webp-thumb");void 0!==t&&!1!==t&&e(this).attr("data-thumb",t);for(var a=1;a<11;)void 0!==(t=e(this).attr("data-webp-param"+a))&&!1!==t&&e(this).attr("data-param"+a,t),a++}),e(".rev_slider img").each(function(){var t=e(this).attr("data-webp-lazyload");void 0!==t&&!1!==t&&e(this).attr("data-lazyload",t)}),e("div.woocommerce-product-gallery__image").each(function(){var t=e(this).attr("data-webp-thumb");void 0!==t&&!1!==t&&e(this).attr("data-thumb",t)})),e("img.ewww_webp_lazy_retina").each(function(){if(t)void 0!==(a=e(this).attr("data-srcset-webp"))&&!1!==a&&e(this).attr("data-srcset",a);else{var a=e(this).attr("data-srcset-img");void 0!==a&&!1!==a&&e(this).attr("data-srcset",a)}e(this).removeClass("ewww_webp_lazy_retina")}),e("video").each(function(){if(t)void 0!==(a=e(this).attr("data-poster-webp"))&&!1!==a&&e(this).attr("poster",a);else{var a=e(this).attr("data-poster-image");void 0!==a&&!1!==a&&e(this).attr("poster",a)}}),e("img.ewww_webp_lazy_load").each(function(){if(t)e(this).attr("data-lazy-src",e(this).attr("data-lazy-webp-src")),void 0!==(a=e(this).attr("data-srcset-webp"))&&!1!==a&&e(this).attr("srcset",a),void 0!==(a=e(this).attr("data-lazy-srcset-webp"))&&!1!==a&&e(this).attr("data-lazy-srcset",a);else{e(this).attr("data-lazy-src",e(this).attr("data-lazy-img-src"));var a=e(this).attr("data-srcset");void 0!==a&&!1!==a&&e(this).attr("srcset",a),void 0!==(a=e(this).attr("data-lazy-srcset-img"))&&!1!==a&&e(ewww_img).attr("data-lazy-srcset",a)}e(this).removeClass("ewww_webp_lazy_load")}),e(".ewww_webp_lazy_hueman").each(function(){var i=document.createElement("img");if(e(i).attr("src",e(this).attr("data-src")),t)e(i).attr("data-src",e(this).attr("data-webp-src")),void 0!==(r=e(this).attr("data-srcset-webp"))&&!1!==r&&e(i).attr("data-srcset",r);else{e(i).attr("data-src",e(this).attr("data-img"));var r=e(this).attr("data-srcset-img");void 0!==r&&!1!==r&&e(i).attr("data-srcset",r)}i=a(this,i),e(this).after(i),e(this).removeClass("ewww_webp_lazy_hueman")}),e(".ewww_webp").each(function(){var i=document.createElement("img");if(t)e(i).attr("src",e(this).attr("data-webp")),void 0!==(r=e(this).attr("data-srcset-webp"))&&!1!==r&&e(i).attr("srcset",r),void 0!==(r=e(this).attr("data-webp-orig-file"))&&!1!==r?e(i).attr("data-orig-file",r):void 0!==(r=e(this).attr("data-orig-file"))&&!1!==r&&e(i).attr("data-orig-file",r),void 0!==(r=e(this).attr("data-webp-medium-file"))&&!1!==r?e(i).attr("data-medium-file",r):void 0!==(r=e(this).attr("data-medium-file"))&&!1!==r&&e(i).attr("data-medium-file",r),void 0!==(r=e(this).attr("data-webp-large-file"))&&!1!==r?e(i).attr("data-large-file",r):void 0!==(r=e(this).attr("data-large-file"))&&!1!==r&&e(i).attr("data-large-file",r),void 0!==(r=e(this).attr("data-webp-large_image"))&&!1!==r?e(i).attr("data-large_image",r):void 0!==(r=e(this).attr("data-large_image"))&&!1!==r&&e(i).attr("data-large_image",r),void 0!==(r=e(this).attr("data-webp-src"))&&!1!==r?e(i).attr("data-src",r):void 0!==(r=e(this).attr("data-src"))&&!1!==r&&e(i).attr("data-src",r);else{e(i).attr("src",e(this).attr("data-img"));var r=e(this).attr("data-srcset-img");void 0!==r&&!1!==r&&e(i).attr("srcset",r),void 0!==(r=e(this).attr("data-orig-file"))&&!1!==r&&e(i).attr("data-orig-file",r),void 0!==(r=e(this).attr("data-medium-file"))&&!1!==r&&e(i).attr("data-medium-file",r),void 0!==(r=e(this).attr("data-large-file"))&&!1!==r&&e(i).attr("data-large-file",r),void 0!==(r=e(this).attr("data-large_image"))&&!1!==r&&e(i).attr("data-large_image",r),void 0!==(r=e(this).attr("data-src"))&&!1!==r&&e(i).attr("data-src",r)}i=a(this,i),e(this).after(i),e(this).removeClass("ewww_webp")})}(jQuery),jQuery.fn.isotope&&jQuery.fn.imagesLoaded&&(jQuery(".fusion-posts-container-infinite").imagesLoaded(function(){jQuery(".fusion-posts-container-infinite").hasClass("isotope")&&jQuery(".fusion-posts-container-infinite").isotope()}),jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").imagesLoaded(function(){jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").isotope()}))}var Arrive=function(t,e,a){"use strict";function i(t,e,a){o.addMethod(e,a,t.unbindEvent),o.addMethod(e,a,t.unbindEventWithSelectorOrCallback),o.addMethod(e,a,t.unbindEventWithSelectorAndCallback)}function r(t){t.arrive=l.bindEvent,i(l,t,"unbindArrive"),t.leave=c.bindEvent,i(c,t,"unbindLeave")}if(t.MutationObserver&&"undefined"!=typeof HTMLElement){var n=0,o=function(){var e=HTMLElement.prototype.matches||HTMLElement.prototype.webkitMatchesSelector||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelector;return{matchesSelector:function(t,a){return t instanceof HTMLElement&&e.call(t,a)},addMethod:function(t,e,a){var i=t[e];t[e]=function(){return a.length==arguments.length?a.apply(this,arguments):"function"==typeof i?i.apply(this,arguments):void 0}},callCallbacks:function(t){for(var e,a=0;e=t[a];a++)e.callback.call(e.elem)},checkChildNodesRecursively:function(t,e,a,i){for(var r,n=0;r=t[n];n++)a(r,e,i)&&i.push({callback:e.callback,elem:r}),r.childNodes.length>0&&o.checkChildNodesRecursively(r.childNodes,e,a,i)},mergeArrays:function(t,e){var a,i={};for(a in t)i[a]=t[a];for(a in e)i[a]=e[a];return i},toElementsArray:function(e){return void 0===e||"number"==typeof e.length&&e!==t||(e=[e]),e}}}(),s=function(){var t=function(){this._eventsBucket=[],this._beforeAdding=null,this._beforeRemoving=null};return t.prototype.addEvent=function(t,e,a,i){var r={target:t,selector:e,options:a,callback:i,firedElems:[]};return this._beforeAdding&&this._beforeAdding(r),this._eventsBucket.push(r),r},t.prototype.removeEvent=function(t){for(var e,a=this._eventsBucket.length-1;e=this._eventsBucket[a];a--)t(e)&&(this._beforeRemoving&&this._beforeRemoving(e),this._eventsBucket.splice(a,1))},t.prototype.beforeAdding=function(t){this._beforeAdding=t},t.prototype.beforeRemoving=function(t){this._beforeRemoving=t},t}(),d=function(e,i){var r=new s,n=this,d={fireOnAttributesModification:!1};return r.beforeAdding(function(a){var r,o=a.target;a.selector,a.callback;o!==t.document&&o!==t||(o=document.getElementsByTagName("html")[0]),r=new MutationObserver(function(t){i.call(this,t,a)});var s=e(a.options);r.observe(o,s),a.observer=r,a.me=n}),r.beforeRemoving(function(t){t.observer.disconnect()}),this.bindEvent=function(t,e,a){e=o.mergeArrays(d,e);for(var i=o.toElementsArray(this),n=0;n<i.length;n++)r.addEvent(i[n],t,e,a)},this.unbindEvent=function(){var t=o.toElementsArray(this);r.removeEvent(function(e){for(var i=0;i<t.length;i++)if(this===a||e.target===t[i])return!0;return!1})},this.unbindEventWithSelectorOrCallback=function(t){var e,i=o.toElementsArray(this),n=t;e="function"==typeof t?function(t){for(var e=0;e<i.length;e++)if((this===a||t.target===i[e])&&t.callback===n)return!0;return!1}:function(e){for(var r=0;r<i.length;r++)if((this===a||e.target===i[r])&&e.selector===t)return!0;return!1},r.removeEvent(e)},this.unbindEventWithSelectorAndCallback=function(t,e){var i=o.toElementsArray(this);r.removeEvent(function(r){for(var n=0;n<i.length;n++)if((this===a||r.target===i[n])&&r.selector===t&&r.callback===e)return!0;return!1})},this},l=new function(){function t(t,e,i){if(o.matchesSelector(t,e.selector)&&(t._id===a&&(t._id=n++),-1==e.firedElems.indexOf(t._id))){if(e.options.onceOnly){if(0!==e.firedElems.length)return;e.me.unbindEventWithSelectorAndCallback.call(e.target,e.selector,e.callback)}e.firedElems.push(t._id),i.push({callback:e.callback,elem:t})}}var e={fireOnAttributesModification:!1,onceOnly:!1,existing:!1},i=(l=new d(function(t){var e={attributes:!1,childList:!0,subtree:!0};return t.fireOnAttributesModification&&(e.attributes=!0),e},function(e,a){e.forEach(function(e){var i=e.addedNodes,r=e.target,n=[];null!==i&&i.length>0?o.checkChildNodesRecursively(i,a,t,n):"attributes"===e.type&&t(r,a,n)&&n.push({callback:a.callback,elem:node}),o.callCallbacks(n)})})).bindEvent;return l.bindEvent=function(t,a,r){void 0===r?(r=a,a=e):a=o.mergeArrays(e,a);var n=o.toElementsArray(this);if(a.existing){for(var s=[],d=0;d<n.length;d++)for(var l=n[d].querySelectorAll(t),c=0;c<l.length;c++)s.push({callback:r,elem:l[c]});if(a.onceOnly&&s.length)return r.call(s[0].elem);setTimeout(o.callCallbacks,1,s)}i.call(this,t,a,r)},l},c=new function(){function t(t,e){return o.matchesSelector(t,e.selector)}var e={},a=(c=new d(function(t){return{childList:!0,subtree:!0}},function(e,a){e.forEach(function(e){var i=e.removedNodes,r=(e.target,[]);null!==i&&i.length>0&&o.checkChildNodesRecursively(i,a,t,r),o.callCallbacks(r)})})).bindEvent;return c.bindEvent=function(t,i,r){void 0===r?(r=i,i=e):i=o.mergeArrays(e,i),a.call(this,t,i,r)},c};e&&r(e.fn),r(HTMLElement.prototype),r(NodeList.prototype),r(HTMLCollection.prototype),r(HTMLDocument.prototype),r(Window.prototype);var h={};return i(l,h,"unbindAllArrive"),i(c,h,"unbindAllLeave"),h}}(window,"undefined"==typeof jQuery?null:jQuery,void 0);"undefined"!=typeof jQuery&&check_webp_feature("alpha",ewww_load_images);
2478
  </script>
2479
  <?php
2480
  } // End if().
2481
+ // Current length 10783.
2482
  }
2483
 
2484
  /**
2500
  'ewww_vars',
2501
  array(
2502
  'optimizing' => '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' /></p>",
2503
+ 'restoring' => '<p>' . esc_html__( 'Restoring', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' /></p>",
2504
  )
2505
  );
2506
  }
2541
  ewwwio_debug_message( 'GD found, supports:' );
2542
  if ( ewww_image_optimizer_iterable( $gd_support ) ) {
2543
  foreach ( $gd_support as $supports => $supported ) {
2544
+ ewwwio_debug_message( "$supports: $supported" );
2545
  }
2546
  ewwwio_memory( __FUNCTION__ );
2547
  if ( ( ! empty( $gd_support['JPEG Support'] ) || ! empty( $gd_support['JPG Support'] ) ) && ! empty( $gd_support['PNG Support'] ) ) {
2612
  return '';
2613
  }
2614
  $path_array = array();
2615
+ $paths = explode( "\n", $input );
2616
  if ( ewww_image_optimizer_iterable( $paths ) ) {
2617
  $i = 0;
2618
  foreach ( $paths as $path ) {
2673
  return '';
2674
  }
2675
  $path_array = array();
2676
+ $paths = explode( "\n", $input );
2677
  if ( ewww_image_optimizer_iterable( $paths ) ) {
2678
  $i = 0;
2679
  foreach ( $paths as $path ) {
2700
  return '';
2701
  }
2702
  $paths_entered = explode( "\n", $paths );
2703
+ $paths_saved = array();
2704
  if ( ewww_image_optimizer_iterable( $paths_entered ) ) {
2705
  $i = 0;
2706
  foreach ( $paths_entered as $path ) {
2707
  $i++;
2708
  $original_path = esc_html( $path );
2709
+ $path = esc_url( $path, null, 'db' );
2710
  if ( ! empty( $path ) ) {
2711
  if ( ! substr_count( $path, '.' ) ) {
2712
  add_settings_error( 'ewww_image_optimizer_webp_paths', "ewwwio-webp-paths-$i", sprintf(
2873
  if ( ! wp_doing_ajax() ) {
2874
  wp_die( esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ) );
2875
  }
2876
+ ewwwio_ob_clean();
2877
  wp_die( json_encode( array(
2878
  'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
2879
  ) ) );
2884
  if ( ! wp_doing_ajax() ) {
2885
  wp_die( esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ) );
2886
  }
2887
+ ewwwio_ob_clean();
2888
  wp_die( json_encode( array(
2889
  'error' => esc_html__( 'No attachment ID was provided.', 'ewww-image-optimizer' ),
2890
  ) ) );
2896
  if ( ! wp_doing_ajax() ) {
2897
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
2898
  }
2899
+ ewwwio_ob_clean();
2900
  wp_die( json_encode( array(
2901
  'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
2902
  ) ) );
2916
  if ( ! wp_doing_ajax() ) {
2917
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
2918
  }
2919
+ ewwwio_ob_clean();
2920
  wp_die( json_encode( array(
2921
  'error' => esc_html__( 'Access denied.', 'ewww-image-optimizer' ),
2922
  ) ) );
2934
  if ( ! wp_doing_ajax() ) {
2935
  wp_die( esc_html__( 'License exceeded', 'ewww-image-optimizer' ) );
2936
  }
2937
+ ewwwio_ob_clean();
2938
  wp_die( json_encode( array(
2939
  'error' => esc_html__( 'License exceeded', 'ewww-image-optimizer' ),
2940
  ) ) );
2952
  return;
2953
  }
2954
  ewwwio_memory( __FUNCTION__ );
2955
+ ewwwio_ob_clean();
2956
+ wp_die( json_encode( array(
2957
+ 'success' => $success,
2958
  'basename' => $basename,
2959
  ) ) );
2960
  }
2982
  if ( empty( $db_image ) || ! is_array( $db_image ) || empty( $db_image['path'] ) ) {
2983
  // Get the filepath based on the meta and id.
2984
  list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
2985
+
2986
  $db_image = ewww_image_optimizer_find_already_optimized( $file_path );
2987
  if ( empty( $db_image ) || ! is_array( $db_image ) || empty( $db_image['path'] ) ) {
2988
  return $meta;
3028
  $permissions = apply_filters( 'ewww_image_optimizer_manual_permissions', '' );
3029
  if ( false === current_user_can( $permissions ) ) {
3030
  // Display error message if insufficient permissions.
3031
+ ewwwio_ob_clean();
3032
  wp_die( json_encode( array(
3033
  'error' => esc_html__( 'You do not have permission to optimize images.', 'ewww-image-optimizer' ),
3034
  ) ) );
3036
  // Make sure we didn't accidentally get to this page without an attachment to work on.
3037
  if ( empty( $_REQUEST['ewww_image_id'] ) ) {
3038
  // Display an error message since we don't have anything to work on.
3039
+ ewwwio_ob_clean();
3040
  wp_die( json_encode( array(
3041
  'error' => esc_html__( 'No image ID was provided.', 'ewww-image-optimizer' ),
3042
  ) ) );
3043
  }
3044
  if ( empty( $_REQUEST['ewww_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) ) {
3045
+ ewwwio_ob_clean();
3046
  wp_die( json_encode( array(
3047
  'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ),
3048
  ) ) );
3050
  session_write_close();
3051
  $image = (int) $_REQUEST['ewww_image_id'];
3052
  if ( ewww_image_optimizer_cloud_restore_single_image( $image ) ) {
3053
+ ewwwio_ob_clean();
3054
  wp_die( json_encode( array(
3055
  'success' => 1,
3056
  ) ) );
3057
  }
3058
+ ewwwio_ob_clean();
3059
  wp_die( json_encode( array(
3060
  'error' => esc_html__( 'Unable to restore image.', 'ewww-image-optimizer' ),
3061
  ) ) );
3086
  $image['path'] = ewww_image_optimizer_relative_path_replace( $image['path'] );
3087
  }
3088
  $api_key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
3089
+ $domain = parse_url( get_site_url(), PHP_URL_HOST );
3090
+ $url = 'http://optimize.exactlywww.com/backup/restore.php';
3091
+ $ssl = wp_http_supports( array( 'ssl' ) );
3092
  if ( $ssl ) {
3093
  $url = set_url_scheme( $url, 'https' );
3094
  }
3095
  $result = wp_remote_post( $url, array(
3096
+ 'timeout' => 30,
3097
  'sslverify' => false,
3098
+ 'body' => array(
3099
  'api_key' => $api_key,
3100
+ 'domain' => $domain,
3101
+ 'hash' => $image['backup'],
3102
  ),
3103
  ) );
3104
  if ( is_wp_error( $result ) ) {
3112
  $new_type = ewww_image_optimizer_mimetype( $image['path'] . '.tmp', 'i' );
3113
  $old_type = '';
3114
  if ( is_file( $image['path'] ) ) {
3115
+ $old_type = ewww_image_optimizer_mimetype( $image['path'], 'i' );
3116
  }
3117
  if ( ! in_array( $new_type, $enabled_types ) ) {
3118
  return false;
3147
  } else {
3148
  $ewwwdb = $wpdb;
3149
  }
3150
+ $id = (int) $id;
3151
  // Finds non-meta images to remove from disk, and from db, as well as converted originals.
3152
  if (
3153
  $optimized_images = $ewwwdb->get_results( "SELECT path,converted FROM $ewwwdb->ewwwio_images WHERE attachment_id = $id AND gallery = 'media'", ARRAY_A )
3157
  if ( ! empty( $image['path'] ) ) {
3158
  $image['path'] = ewww_image_optimizer_relative_path_replace( $image['path'] );
3159
  }
3160
+ if ( strpos( $image['path'], WP_CONTENT_DIR ) === false ) {
3161
+ continue;
3162
+ }
3163
  if ( ! empty( $image['path'] ) && is_file( $image['path'] ) ) {
3164
  unlink( $image['path'] );
3165
  if ( is_file( $image['path'] . '.webp' ) ) {
3191
  // Get the base filename.
3192
  $filename = basename( $file_path );
3193
  // Delete any residual webp versions.
3194
+ $webpfile = $filename . '.webp';
3195
  $webpfileold = preg_replace( '/\.\w+$/', '.webp', $filename );
3196
  if ( is_file( $webpfile ) ) {
3197
  unlink( $webpfile );
3221
  $base_dir = dirname( $file_path ) . '/';
3222
  foreach ( $meta['sizes'] as $size => $data ) {
3223
  // Delete any residual webp versions.
3224
+ $webpfile = $base_dir . $data['file'] . '.webp';
3225
  $webpfileold = preg_replace( '/\.\w+$/', '.webp', $base_dir . $data['file'] );
3226
  if ( is_file( $webpfile ) ) {
3227
  unlink( $webpfile );
3238
  // Retrieve the filename from the metadata.
3239
  $filename = $data['orig_file'];
3240
  // Retrieve any posts that link the image.
3241
+ $esql = "SELECT ID, post_content FROM $ewwwdb->posts WHERE post_content LIKE '%$filename%' LIMIT 1";
3242
  $srows = $ewwwdb->get_row( $esql );
3243
  // If there are no posts containing links to the original, delete it.
3244
  if ( empty( $srows ) ) {
3378
  }
3379
  $result = ewww_image_optimizer_cloud_post_key( $url, $api_key );
3380
  if ( is_wp_error( $result ) ) {
3381
+ $url = set_url_scheme( $url, 'http' );
3382
  $error_message = $result->get_error_message();
3383
  ewwwio_debug_message( "verification failed: $error_message" );
3384
  $result = ewww_image_optimizer_cloud_post_key( $url, $api_key );
3421
  */
3422
  function ewww_image_optimizer_cloud_post_key( $url, $key ) {
3423
  $result = wp_remote_post( $url, array(
3424
+ 'timeout' => 5,
3425
  'sslverify' => false,
3426
+ 'body' => array(
3427
  'api_key' => $key,
3428
  ),
3429
  ) );
3438
  function ewww_image_optimizer_cloud_quota() {
3439
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
3440
  $api_key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
3441
+ $url = 'http://optimize.exactlywww.com/quota/';
3442
+ $ssl = wp_http_supports( array( 'ssl' ) );
3443
  if ( $ssl ) {
3444
  $url = set_url_scheme( $url, 'https' );
3445
  }
3446
  $result = wp_remote_post( $url, array(
3447
+ 'timeout' => 5,
3448
  'sslverify' => false,
3449
+ 'body' => array(
3450
  'api_key' => $api_key,
3451
  ),
3452
  ) );
3475
  /* translators: 1: Number of images */
3476
  _n( '%1$d image credit remaining.', '%1$d image credits remaining.', $real_quota, 'ewww-image-optimizer' ), $real_quota
3477
  ) );
3478
+ } elseif ( 0 == $quota[0] && 0 == $quota[1] && 0 == $quota[2] ) {
3479
+ return esc_html__( 'no credits remaining, please purchase more.', 'ewww-image-optimizer' );
3480
  } else {
3481
  return esc_html( sprintf(
3482
  /* translators: 1: Number of image credits used 2: Number of image credits available 3: days until subscription renewal */
3522
  ewww_image_optimizer_debug_log();
3523
  }
3524
  $ewww_status = get_transient( 'ewww_image_optimizer_cloud_status' );
3525
+ $started = microtime( true );
3526
  if ( preg_match( '/exceeded/', $ewww_status ) ) {
3527
  if ( ! ewww_image_optimizer_cloud_verify() ) {
3528
  return array( $file, false, 'key verification failed', 0, '' );
3568
  } else {
3569
  $lossy = 0;
3570
  }
3571
+ if ( strpos( $file, '/wp-admin/' ) || strpos( $file, '/wp-includes/' ) || strpos( $file, '/wp-content/themes/' ) || strpos( $file, '/wp-content/plugins/' ) ) {
3572
+ $lossy = 0;
3573
+ $lossy_fast = 0;
3574
+ }
3575
  if ( 'image/webp' == $newtype ) {
3576
+ $webp = 1;
3577
  $jpg_quality = apply_filters( 'jpeg_quality', $jpg_quality, 'image/webp' );
3578
  } else {
3579
  $webp = 0;
3606
  }
3607
  $domain = parse_url( get_site_url(), PHP_URL_HOST );
3608
  } else {
3609
+ $hash = '';
3610
  $domain = parse_url( get_site_url(), PHP_URL_HOST );
3611
  }
3612
  ewwwio_debug_message( "file: $file " );
3618
  ewwwio_debug_message( "jpg fill: $jpg_fill" );
3619
  ewwwio_debug_message( "jpg quality: $jpg_quality" );
3620
  $api_key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
3621
+ $url = 'http://optimize.exactlywww.com/v2/';
3622
+ $ssl = wp_http_supports( array( 'ssl' ) );
3623
  if ( $ssl ) {
3624
  $url = set_url_scheme( $url, 'https' );
3625
  }
3627
 
3628
  $headers = array(
3629
  'content-type' => 'multipart/form-data; boundary=' . $boundary,
3630
+ 'timeout' => 300,
3631
+ 'httpversion' => '1.0',
3632
+ 'blocking' => true,
3633
  );
3634
+
3635
  $post_fields = array(
3636
+ 'filename' => $file,
3637
+ 'convert' => $convert,
3638
+ 'metadata' => $metadata,
3639
+ 'api_key' => $api_key,
3640
+ 'jpg_fill' => $jpg_fill,
3641
+ 'quality' => $jpg_quality,
3642
+ 'compress' => $png_compress,
3643
+ 'lossy' => $lossy,
3644
  'lossy_fast' => $lossy_fast,
3645
+ 'webp' => $webp,
3646
+ 'backup' => $hash,
3647
+ 'domain' => $domain,
3648
  );
3649
 
3650
  $payload = '';
3671
 
3672
  // Retrieve the time when the optimizer starts.
3673
  $response = wp_remote_post( $url, array(
3674
+ 'timeout' => 300,
3675
+ 'headers' => $headers,
3676
  'sslverify' => false,
3677
+ 'body' => $payload,
3678
  ) );
3679
  if ( is_wp_error( $response ) ) {
3680
  $error_message = $response->get_error_message();
3684
  $tempfile = $file . '.tmp';
3685
  file_put_contents( $tempfile, $response['body'] );
3686
  $orig_size = filesize( $file );
3687
+ $newsize = $orig_size;
3688
  $converted = false;
3689
+ $msg = '';
3690
+ if ( 100 > strlen( $response['body'] ) && preg_match( '/exceeded/', $response['body'] ) ) {
3691
  ewwwio_debug_message( 'License Exceeded' );
3692
  set_transient( 'ewww_image_optimizer_cloud_status', 'exceeded', 3600 );
3693
  $msg = 'exceeded';
3702
  rename( $tempfile, $newfile );
3703
  } elseif ( ewww_image_optimizer_mimetype( $tempfile, 'i' ) == $newtype ) {
3704
  $converted = true;
3705
+ $newsize = filesize( $tempfile );
3706
  ewwwio_debug_message( "cloud results: $newsize (new) vs. $orig_size (original)" );
3707
  rename( $tempfile, $newfile );
3708
  $file = $newfile;
3734
  ewww_image_optimizer_debug_log();
3735
  }
3736
  $ewww_status = get_transient( 'ewww_image_optimizer_cloud_status' );
3737
+ $started = microtime( true );
3738
  if ( preg_match( '/exceeded/', $ewww_status ) ) {
3739
  if ( ! ewww_image_optimizer_cloud_verify() ) {
3740
  ewwwio_debug_message( 'cloud verify failed, image not rotated' );
3752
  ewwwio_debug_message( "file: $file " );
3753
  ewwwio_debug_message( "type: $type" );
3754
  $api_key = ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' );
3755
+ $url = 'http://optimize.exactlywww.com/rotate/';
3756
+ $ssl = wp_http_supports( array( 'ssl' ) );
3757
  if ( $ssl ) {
3758
  $url = set_url_scheme( $url, 'https' );
3759
  }
3761
 
3762
  $headers = array(
3763
  'content-type' => 'multipart/form-data; boundary=' . $boundary,
3764
+ 'timeout' => 60,
3765
+ 'httpversion' => '1.0',
3766
+ 'blocking' => true,
3767
  );
3768
+
3769
  $post_fields = array(
3770
  'filename' => $file,
3771
+ 'api_key' => $api_key,
3772
  );
3773
 
3774
  $payload = '';
3794
  $payload .= '--' . $boundary . '--';
3795
 
3796
  $response = wp_remote_post( $url, array(
3797
+ 'timeout' => 60,
3798
+ 'headers' => $headers,
3799
  'sslverify' => false,
3800
+ 'body' => $payload,
3801
  ) );
3802
  if ( is_wp_error( $response ) ) {
3803
  $error_message = $response->get_error_message();
3807
  $tempfile = $file . '.tmp';
3808
  file_put_contents( $tempfile, $response['body'] );
3809
  $orig_size = filesize( $file );
3810
+ $newsize = $orig_size;
3811
  if ( preg_match( '/exceeded/', $response['body'] ) ) {
3812
  ewwwio_debug_message( 'License Exceeded' );
3813
  set_transient( 'ewww_image_optimizer_cloud_status', 'exceeded', 3600 );
3844
  }
3845
 
3846
  $ewwwdb->field_types = array(
3847
+ 'post_author' => '%d',
3848
+ 'post_parent' => '%d',
3849
+ 'menu_order' => '%d',
3850
+ 'term_id' => '%d',
3851
+ 'term_group' => '%d',
3852
  'term_taxonomy_id' => '%d',
3853
+ 'parent' => '%d',
3854
+ 'count' => '%d',
3855
+ 'object_id' => '%d',
3856
+ 'term_order' => '%d',
3857
+ 'ID' => '%d',
3858
+ 'comment_ID' => '%d',
3859
+ 'comment_post_ID' => '%d',
3860
+ 'comment_parent' => '%d',
3861
+ 'user_id' => '%d',
3862
+ 'link_id' => '%d',
3863
+ 'link_owner' => '%d',
3864
+ 'link_rating' => '%d',
3865
+ 'option_id' => '%d',
3866
+ 'blog_id' => '%d',
3867
+ 'meta_id' => '%d',
3868
+ 'post_id' => '%d',
3869
+ 'user_status' => '%d',
3870
+ 'umeta_id' => '%d',
3871
+ 'comment_karma' => '%d',
3872
+ 'comment_count' => '%d',
3873
  // multisite.
3874
+ 'active' => '%d',
3875
+ 'cat_id' => '%d',
3876
+ 'deleted' => '%d',
3877
+ 'lang_id' => '%d',
3878
+ 'mature' => '%d',
3879
+ 'public' => '%d',
3880
+ 'site_id' => '%d',
3881
+ 'spam' => '%d',
3882
  );
3883
 
3884
  $prefix = $ewwwdb->set_prefix( $table_prefix );
3987
  // First check if the image was converted, so we don't orphan records.
3988
  if ( $original && $original != $attachment ) {
3989
  $already_optimized = ewww_image_optimizer_find_already_optimized( $original );
3990
+ $converted = $original;
3991
  } else {
3992
  global $s3_uploads_image;
3993
  if ( class_exists( 'S3_Uploads' ) && ! empty( $s3_uploads_image ) && $s3_uploads_image != $attachment ) {
4014
  $results_msg = ewww_image_optimizer_image_results( $orig_size, $opt_size, $prev_string );
4015
 
4016
  $updates = array(
4017
+ 'path' => ewww_image_optimizer_relative_path_remove( $attachment ),
4018
+ 'converted' => $converted,
4019
  'image_size' => $opt_size,
4020
+ 'results' => $results_msg,
4021
+ 'updates' => 1,
4022
+ 'backup' => preg_replace( '/[^\w]/', '', $backup_hash ),
4023
  );
4024
  if ( ! seems_utf8( $updates['path'] ) ) {
4025
  $updates['path'] = utf8_encode( $updates['path'] );
4037
  $updates['resize'] = $ewww_image->resize;
4038
  }
4039
  $updates['orig_size'] = $orig_size;
4040
+ $updates['updated'] = date( 'Y-m-d H:i:s' );
4041
  $ewwwdb->insert( $ewwwdb->ewwwio_images, $updates );
4042
  } else {
4043
  if ( is_array( $already_optimized ) && empty( $already_optimized['orig_size'] ) ) {
4098
  $results_msg = __( 'No savings', 'ewww-image-optimizer' );
4099
  } else {
4100
  // Calculate how much space was saved.
4101
+ $savings = intval( $orig_size ) - intval( $opt_size );
4102
  $savings_str = ewww_image_optimizer_size_format( $savings );
4103
  // Determine the percentage savings.
4104
  $percent = number_format_i18n( 100 - ( 100 * ( $opt_size / $orig_size ) ), 1 ) . '%';
4157
  }
4158
  global $ewww_defer;
4159
  $ewww_defer = false;
4160
+ $output = array();
4161
  // Verify that an authorized user has started the optimizer.
4162
  $permissions = apply_filters( 'ewww_image_optimizer_bulk_permissions', '' );
4163
  if ( ! $auto && ( empty( $_REQUEST['ewww_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-bulk' ) || ! current_user_can( $permissions ) ) ) {
4164
  $output['error'] = esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' );
4165
  echo json_encode( $output );
4166
+ wp_die();
4167
  }
4168
  session_write_close();
4169
  if ( ! empty( $_REQUEST['ewww_wpnonce'] ) ) {
4186
  if ( empty( $attachment ) ) {
4187
  list( $id, $attachment ) = $ewwwdb->get_row( "SELECT id,path FROM $ewwwdb->ewwwio_images WHERE pending=1 LIMIT 1", ARRAY_N );
4188
  } else {
4189
+ $id = $attachment['id'];
4190
  $attachment = $attachment['path'];
4191
  }
4192
  if ( $attachment ) {
4214
  if ( $cli ) {
4215
  WP_CLI::error( __( 'License Exceeded', 'ewww-image-optimizer' ) );
4216
  }
4217
+ wp_die();
4218
  }
4219
  if ( ! $auto ) {
4220
  // Output the path.
4234
  }
4235
  $next_file = ewww_image_optimizer_relative_path_replace( $wpdb->get_var( "SELECT path FROM $wpdb->ewwwio_images WHERE pending=1 LIMIT 1" ) );
4236
  if ( ! empty( $next_file ) ) {
4237
+ $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
4238
  $output['next_file'] = '<p>' . esc_html__( 'Optimizing', 'ewww-image-optimizer' ) . ' <b>' . esc_html( $next_file ) . "</b>&nbsp;<img src='$loading_image' alt='loading'/></p>";
4239
  }
4240
  echo json_encode( $output );
4241
  ewwwio_memory( __FUNCTION__ );
4242
+ wp_die();
4243
  }
4244
  if ( $cli ) {
4245
  return $results[1];
4260
  function ewww_image_optimizer_hidpi_optimize( $orig_path, $return_path = false, $validate_file = true ) {
4261
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
4262
  $hidpi_suffix = apply_filters( 'ewww_image_optimizer_hidpi_suffix', '@2x' );
4263
+ $pathinfo = pathinfo( $orig_path );
4264
  if ( empty( $pathinfo['dirname'] ) || empty( $pathinfo['filename'] ) || empty( $pathinfo['extension'] ) ) {
4265
  return;
4266
  }
4274
  }
4275
  global $ewww_image;
4276
  if ( is_object( $ewww_image ) && $ewww_image instanceof EWWW_Image ) {
4277
+ $id = $ewww_image->attachment_id;
4278
  $gallery = 'media';
4279
+ $size = $ewww_image->resize;
4280
  } else {
4281
+ $id = 0;
4282
  $gallery = '';
4283
+ $size = null;
4284
  }
4285
+ $ewww_image = new EWWW_Image( $id, $gallery, $hidpi_path );
4286
  $ewww_image->resize = $size . '-retina';
4287
  ewww_image_optimizer( $hidpi_path );
4288
  }
4319
  $disabled_sizes = get_option( 'ewww_image_optimizer_disable_resizes_opt' );
4320
  ewwwio_debug_message( 'retrieving resizes' );
4321
  // Meta sizes don't contain a path, so we calculate one.
4322
+ $base_dir = trailingslashit( dirname( $filename ) );
4323
  $processed = array();
4324
  foreach ( $meta['sizes'] as $size => $data ) {
4325
  ewwwio_debug_message( "processing size: $size" );
4344
  // If this is a unique size.
4345
  if ( ! $dup_size ) {
4346
  $resize_path = $base_dir . $data['file'];
4347
+ $resize_url = $as3cf->get_attachment_url( $id, null, $size, $meta );
4348
  ewwwio_debug_message( "fetching $resize_url to $resize_path" );
4349
  $temp_file = download_url( $resize_url );
4350
  if ( ! is_wp_error( $temp_file ) ) {
4352
  }
4353
  }
4354
  // Store info on the sizes we've processed, so we can check the list for duplicate sizes.
4355
+ $processed[ $size ]['width'] = $data['width'];
4356
  $processed[ $size ]['height'] = $data['height'];
4357
  }
4358
  } // End if().
4398
  // If this is a unique size.
4399
  if ( ! $dup_size ) {
4400
  $resize_path = $base_dir . $data['file'];
4401
+ $resize_url = $base_url . $data['file'];
4402
  ewwwio_debug_message( "fetching $resize_url to $resize_path" );
4403
  $temp_file = download_url( $resize_url );
4404
  if ( ! is_wp_error( $temp_file ) ) {
4406
  }
4407
  }
4408
  // Store info on the sizes we've processed, so we can check the list for duplicate sizes.
4409
+ $processed[ $size ]['width'] = $data['width'];
4410
  $processed[ $size ]['height'] = $data['height'];
4411
  }
4412
  } // End if().
4413
  } // End if().
4414
+ clearstatcache();
4415
  if ( ! empty( $filename ) && is_file( $filename ) ) {
4416
  return $filename;
4417
  } else {
4439
  ewwwio_debug_message( 'updating s3 resizes' );
4440
  // Meta sizes don't contain a path, so we calculate one.
4441
  $local_dir = trailingslashit( dirname( $local_path ) );
4442
+ $s3_dir = trailingslashit( dirname( $s3_path ) );
4443
  $processed = array();
4444
  foreach ( $meta['sizes'] as $size => $data ) {
4445
  if ( strpos( $size, 'webp' ) === 0 ) {
4455
  }
4456
  // If this is a unique size.
4457
  $local_resize_path = $local_dir . $data['file'];
4458
+ $s3_resize_path = $s3_dir . $data['file'];
4459
  if ( $local_resize_path !== $s3_resize_path ) {
4460
  ewww_image_optimizer_update_table_as3cf( $local_resize_path, $s3_resize_path );
4461
  }
4462
  // Store info on the sizes we've processed, so we can check the list for duplicate sizes.
4463
+ $processed[ $size ]['width'] = $data['width'];
4464
  $processed[ $size ]['height'] = $data['height'];
4465
  }
4466
  }
4509
  $ewwwdb->update( $ewwwdb->ewwwio_images,
4510
  array(
4511
  'orig_size' => $s3_image['orig_size'],
4512
+ 'results' => $s3_image['results'],
4513
  ),
4514
  array(
4515
  'id' => $found_local_image['id'],
4579
  $jpeg = new PelJpeg( $file );
4580
  $exif = $jpeg->getExif();
4581
  if ( null != $exif ) {
4582
+ $tiff = $exif->getTiff();
4583
+ $ifd0 = $tiff->getIfd();
4584
  $orientation = $ifd0->getEntry( PelTag::ORIENTATION );
4585
  if ( null != $orientation ) {
4586
  ewwwio_debug_message( 'orientation being adjusted' );
4613
  wp_raise_memory_limit( 'image' );
4614
  }
4615
  if ( ! empty( $_REQUEST['post_id'] ) || ( ! empty( $_REQUEST['action'] ) && 'upload-attachment' === $_REQUEST['action'] ) || ( ! empty( $_SERVER['HTTP_REFERER'] ) && strpos( $_SERVER['HTTP_REFERER'], 'media-new.php' ) ) ) {
4616
+ $maxwidth = ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' );
4617
  $maxheight = ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' );
4618
  ewwwio_debug_message( 'resizing image from media library or attached to post' );
4619
  } else {
4620
+ $maxwidth = ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherwidth' );
4621
  $maxheight = ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherheight' );
4622
  ewwwio_debug_message( 'resizing images from somewhere else' );
4623
  }
4639
  if ( 0 == $maxwidth && 0 == $maxheight ) {
4640
  return false;
4641
  }
4642
+ $maxwidth = $maxwidth ? $maxwidth : 999999;
4643
  $maxheight = $maxheight ? $maxheight : 999999;
4644
  // Check the file type.
4645
  $type = ewww_image_optimizer_mimetype( $file, 'i' );
4658
  }
4659
  $crop = false;
4660
  if ( $oldwidth > $maxwidth && $maxwidth && $oldheight > $maxheight && $maxheight && apply_filters( 'ewww_image_optimizer_crop_image', false ) ) {
4661
+ $crop = true;
4662
+ $newwidth = $maxwidth;
4663
  $newheight = $maxheight;
4664
  } else {
4665
  list( $newwidth, $newheight ) = wp_constrain_dimensions( $oldwidth, $oldheight, $maxwidth, $maxheight );
4677
  ewwwio_debug_message( 'no image editor function' );
4678
  return false;
4679
  }
4680
+
4681
+ // From here...
4682
  remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
4683
  $editor = wp_get_image_editor( $file );
4684
  if ( is_wp_error( $editor ) ) {
4685
  ewwwio_debug_message( 'could not get image editor' );
4686
  return false;
4687
  }
4688
+ // Rotation only happens on existing media here, so we need to swap dimension when we rotate by 90.
4689
  $orientation = ewww_image_optimizer_get_orientation( $file, $type );
4690
+ $rotated = false;
4691
  switch ( $orientation ) {
4692
  case 3:
4693
  $editor->rotate( 180 );
4696
  case 6:
4697
  $editor->rotate( -90 );
4698
  $new_newwidth = $newwidth;
4699
+ $newwidth = $newheight;
4700
+ $newheight = $new_newwidth;
4701
+ $rotated = true;
4702
  break;
4703
  case 8:
4704
  $editor->rotate( 90 );
4705
  $new_newwidth = $newwidth;
4706
+ $newwidth = $newheight;
4707
+ $newheight = $new_newwidth;
4708
+ $rotated = true;
4709
  break;
4710
  }
4711
  $resized_image = $editor->resize( $newwidth, $newheight, $crop );
4713
  ewwwio_debug_message( 'error during resizing' );
4714
  return false;
4715
  }
4716
+ $new_file = $editor->generate_filename( 'tmp' );
4717
  $orig_size = filesize( $file );
4718
  ewwwio_debug_message( "before resizing: $orig_size" );
4719
  $saved = $editor->save( $new_file );
4721
  ewwwio_debug_message( 'error saving resized image' );
4722
  }
4723
  add_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
4724
+ // to here is replaced by cloud/API function.
4725
  $new_size = ewww_image_optimizer_filesize( $new_file );
4726
  if ( $new_size && $new_size < $orig_size ) {
4727
  // Use this action to perform any operations on the original file before it is overwritten with the new, smaller file.
4730
  // TODO: see if there is a way to just check that meta exists on the new image.
4731
  // 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.
4732
  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() ) {
4733
+ ewwwio_debug_message( 'manually copying metadata for GD' );
4734
  $old_jpeg = new PelJpeg( $file );
4735
  $old_exif = $old_jpeg->getExif();
4736
  $new_jpeg = new PelJpeg( $new_file );
4737
  if ( null != $old_exif ) {
4738
  if ( $rotated ) {
4739
+ $tiff = $old_exif->getTiff();
4740
+ $ifd0 = $tiff->getIfd();
4741
  $orientation = $ifd0->getEntry( PelTag::ORIENTATION );
4742
  if ( null != $orientation ) {
4743
  $orientation->setValue( 1 );
4761
  if ( empty( $already_optimized ) ) {
4762
  $tmp_exists = $ewwwdb->update( $ewwwdb->ewwwio_images,
4763
  array(
4764
+ 'path' => ewww_image_optimizer_relative_path_remove( $file ),
4765
  'orig_size' => $orig_size,
4766
  ),
4767
  array(
4771
  // If the tmp file didn't get optimized (and it shouldn't), then just insert a dummy record to be updated shortly.
4772
  if ( ! $tmp_exists ) {
4773
  $ewwwdb->insert( $ewwwdb->ewwwio_images, array(
4774
+ 'path' => ewww_image_optimizer_relative_path_remove( $file ),
4775
  'orig_size' => $orig_size,
4776
  ) );
4777
  }
4840
  $ewwwdb = $wpdb;
4841
  }
4842
  $maybe_return_image = false;
4843
+ $query = $ewwwdb->prepare( "SELECT * FROM $ewwwdb->ewwwio_images WHERE path = %s", ewww_image_optimizer_relative_path_remove( $attachment ) );
4844
+ $optimized_query = $ewwwdb->get_results( $query, ARRAY_A );
4845
  if ( ewww_image_optimizer_iterable( $optimized_query ) ) {
4846
  foreach ( $optimized_query as $image ) {
4847
  $image['path'] = ewww_image_optimizer_relative_path_replace( $image['path'] );
4892
  if ( ! is_array( $duplicates[0] ) ) {
4893
  // Retrieve records for the ID #s passed.
4894
  $duplicate_ids = implode( ',', array_map( 'intval', $duplicates ) );
4895
+ $duplicates = $ewwwdb->get_results( "SELECT * FROM $ewwwdb->ewwwio_images WHERE id IN ($duplicate_ids)" ); // WPCS: unprepared SQL ok.
4896
  }
4897
  if ( ! is_array( $duplicates ) || ! is_array( $duplicates[0] ) ) {
4898
  return false;
4899
  }
4900
  $image_size = ewww_image_optimizer_filesize( $duplicates[0]['path'] );
4901
+ $discard = array();
4902
  // First look for an image size match.
4903
  foreach ( $duplicates as $duplicate ) {
4904
  if ( empty( $keeper ) && ! empty( $duplicate['image_size'] ) && $image_size == $duplicate['image_size'] ) {
4920
  }
4921
  // If we still have nothing, mark the 0 record as the primary and pull it off the stack.
4922
  if ( empty( $keeper ) ) {
4923
+ $keeper = array_shift( $duplicates );
4924
  $discard = $duplicates;
4925
  }
4926
  if ( is_array( $keeper ) && is_array( $discard ) ) {
5146
  }
5147
  }
5148
  ewwwio_debug_message( "retrieved file path: $file_path" );
5149
+ $type = ewww_image_optimizer_mimetype( $file_path, 'i' );
5150
  $supported_types = array(
5151
  'image/jpeg',
5152
  'image/png',
5163
  list( $maxw, $maxh ) = imsanity_get_max_width_height( IMSANITY_SOURCE_LIBRARY );
5164
  list( $oldw, $oldh ) = getimagesize( $file_path );
5165
  list( $neww, $newh ) = wp_constrain_dimensions( $oldw, $oldh, $maxw, $maxh );
5166
+ $path_parts = pathinfo( $file_path );
5167
+ $imsanity_path = trailingslashit( $path_parts['dirname'] ) . $path_parts['filename'] . '-' . $neww . 'x' . $newh . '.' . $path_parts['extension'];
5168
  ewwwio_debug_message( "imsanity path: $imsanity_path" );
5169
+ $image_size = ewww_image_optimizer_filesize( $file_path );
5170
  $already_optimized = ewww_image_optimizer_find_already_optimized( $imsanity_path );
5171
  if ( is_array( $already_optimized ) ) {
5172
  ewwwio_debug_message( "updating existing record, path: $file_path, size: " . $image_size );
5173
  // Store info on the current image for future reference.
5174
  $ewwwdb->update( $ewwwdb->ewwwio_images,
5175
  array(
5176
+ 'path' => ewww_image_optimizer_relative_path_remove( $file_path ),
5177
  'attachment_id' => $id,
5178
+ 'resize' => 'full',
5179
+ 'gallery' => 'media',
5180
  ),
5181
  array(
5182
  'id' => $already_optimized['id'],
5188
  if ( ( empty( $new_image ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' ) ) && ! function_exists( 'imsanity_get_max_width_height' ) ) {
5189
  $new_dimensions = ewww_image_optimizer_resize_upload( $file_path );
5190
  if ( is_array( $new_dimensions ) ) {
5191
+ $meta['width'] = $new_dimensions[0];
5192
  $meta['height'] = $new_dimensions[1];
5193
  }
5194
  }
5207
  }
5208
  ewwwio_debug_message( "backgrounding optimization for $id" );
5209
  $ewwwio_media_background->push_to_queue( array(
5210
+ 'id' => $id,
5211
+ 'new' => $new_image,
5212
  'type' => $type,
5213
  ) );
5214
  $ewwwio_media_background->save()->dispatch();
5225
  if ( apply_filters( 'ewww_image_optimizer_defer_resizing', false ) && ( ! empty( $new_image ) || ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' ) ) && ! function_exists( 'imsanity_get_max_width_height' ) ) {
5226
  $new_dimensions = ewww_image_optimizer_resize_upload( $file_path );
5227
  if ( is_array( $new_dimensions ) ) {
5228
+ $meta['width'] = $new_dimensions[0];
5229
  $meta['height'] = $new_dimensions[1];
5230
  }
5231
  }
5250
  $ewwwio_async_optimize_media = new EWWWIO_Async_Request();
5251
  }
5252
  } else {
5253
+ $ewww_image = new EWWW_Image( $id, 'media', $file_path );
5254
  $ewww_image->resize = 'full';
5255
+
5256
+ // Run the optimization and store the results.
5257
  list( $file, $msg, $conv, $original ) = ewww_image_optimizer( $file_path, $gallery_type, false, $new_image, true );
5258
 
5259
  if ( false === $file ) {
5264
  if ( $conv ) {
5265
  $ewww_image->increment = $conv;
5266
  }
5267
+ $ewww_image->file = $file;
5268
  $ewww_image->converted = $original;
5269
+ $meta['file'] = trailingslashit( dirname( $meta['file'] ) ) . basename( $file );
5270
  $ewww_image->update_converted_attachment( $meta );
5271
  $meta = $ewww_image->convert_sizes( $meta );
5272
  ewwwio_debug_message( 'image was converted' );
5302
  }
5303
  if ( 6 === $gallery_type ) {
5304
  // We reset base_dir, because base_dir potentially gets overwritten with base_ims_dir.
5305
+ $base_dir = trailingslashit( dirname( $file_path ) );
5306
  $image_path = $base_dir . $data['file'];
5307
+ $ims_path = $base_ims_dir . $data['file'];
5308
  if ( is_file( $ims_path ) ) {
5309
  ewwwio_debug_message( 'ims resize already exists, wahoo' );
5310
  ewwwio_debug_message( "ims path: $ims_path" );
5311
+ $image_size = ewww_image_optimizer_filesize( $ims_path );
5312
  $already_optimized = ewww_image_optimizer_find_already_optimized( $image_path );
5313
  if ( is_array( $already_optimized ) ) {
5314
  ewwwio_debug_message( "updating existing record, path: $ims_path, size: " . $image_size );
5341
  $size = 'pdf-full';
5342
  ewwwio_debug_message( 'processing full size pdf preview' );
5343
  }
 
5344
  if ( $parallel_opt && is_file( $resize_path ) ) {
5345
  $parallel_sizes[ $size ] = $resize_path;
5346
  } else {
5347
+ $ewww_image = new EWWW_Image( $id, 'media', $resize_path );
5348
  $ewww_image->resize = $size;
5349
+ // Run the optimization and store the results.
5350
  list( $optimized_file, $results, $resize_conv, $original ) = ewww_image_optimizer( $resize_path );
5351
  }
5352
  // Optimize retina images, if they exist.
5360
  $async_path = str_replace( $upload_path, '', $retina_path );
5361
  $ewwwio_async_optimize_media->data(
5362
  array(
5363
+ 'ewwwio_id' => $id,
5364
  'ewwwio_path' => $async_path,
5365
  'ewwwio_size' => '',
5366
+ 'ewww_force' => $force,
5367
  )
5368
  )->dispatch();
5369
  } else {
5370
+ $ewww_image = new EWWW_Image( $id, 'media', $retina_path );
5371
  $ewww_image->resize = $size . '-retina';
5372
  ewww_image_optimizer( $retina_path );
5373
  }
5375
  ewww_image_optimizer_hidpi_optimize( $resize_path );
5376
  }
5377
  // Store info on the sizes we've processed, so we can check the list for duplicate sizes.
5378
+ $processed[ $size ]['width'] = $data['width'];
5379
  $processed[ $size ]['height'] = $data['height'];
5380
  } // End foreach().
5381
  } // End if().
5383
  // Process size from a custom theme.
5384
  if ( isset( $meta['image_meta']['resized_images'] ) && ewww_image_optimizer_iterable( $meta['image_meta']['resized_images'] ) ) {
5385
  $imagemeta_resize_pathinfo = pathinfo( $file_path );
5386
+ $imagemeta_resize_path = '';
5387
  foreach ( $meta['image_meta']['resized_images'] as $imagemeta_resize ) {
5388
  $imagemeta_resize_path = $imagemeta_resize_pathinfo['dirname'] . '/' . $imagemeta_resize_pathinfo['filename'] . '-' . $imagemeta_resize . '.' . $imagemeta_resize_pathinfo['extension'];
5389
  if ( $parallel_opt && is_file( $imagemeta_resize_path ) ) {
5390
  $async_path = str_replace( $upload_path, '', $imagemeta_resize_path );
5391
  $ewwwio_async_optimize_media->data(
5392
  array(
5393
+ 'ewwwio_id' => $id,
5394
  'ewwwio_path' => $async_path,
5395
  'ewwwio_size' => '',
5396
+ 'ewww_force' => $force,
5397
  )
5398
  )->dispatch();
5399
  } else {
5406
  // And another custom theme.
5407
  if ( isset( $meta['custom_sizes'] ) && ewww_image_optimizer_iterable( $meta['custom_sizes'] ) ) {
5408
  $custom_sizes_pathinfo = pathinfo( $file_path );
5409
+ $custom_size_path = '';
5410
  foreach ( $meta['custom_sizes'] as $custom_size ) {
5411
  $custom_size_path = $custom_sizes_pathinfo['dirname'] . '/' . $custom_size['file'];
5412
  if ( $parallel_opt && file_exists( $custom_size_path ) ) {
5413
  $async_path = str_replace( $upload_path, '', $custom_size_path );
5414
  $ewwwio_async_optimize_media->data(
5415
  array(
5416
+ 'ewwwio_id' => $id,
5417
  'ewwwio_path' => $async_path,
5418
  'ewwwio_size' => '',
5419
+ 'ewww_force' => $force,
5420
  )
5421
  )->dispatch();
5422
  } else {
5427
  }
5428
 
5429
  if ( $parallel_opt && count( $parallel_sizes ) > 0 ) {
5430
+ $max_threads = (int) apply_filters( 'ewww_image_optimizer_max_parallel_threads', 5 );
5431
+ $processing = true;
5432
+ $timer = (int) apply_filters( 'ewww_image_optimizer_background_timer_init', 1 );
5433
+ $increment = (int) apply_filters( 'ewww_image_optimizer_background_timer_increment', 1 );
5434
+ $timer_max = (int) apply_filters( 'ewww_image_optimizer_background_timer_max', 20 );
5435
  $processing_sizes = array();
5436
  if ( ! empty( $_REQUEST['ewww_force'] ) ) {
5437
  $force = true;
5465
  ewwwio_debug_message( "sending off $async_path in folder $upload_path" );
5466
  $ewwwio_async_optimize_media->data(
5467
  array(
5468
+ 'ewwwio_id' => $id,
5469
  'ewwwio_path' => $async_path,
5470
  'ewwwio_size' => $size,
5471
+ 'ewww_force' => $force,
5472
  )
5473
  )->dispatch();
5474
  $threads--;
5521
  unset( $meta['processing'] );
5522
 
5523
  global $ewww_attachment;
5524
+ $ewww_attachment['id'] = $id;
5525
  $ewww_attachment['meta'] = $meta;
5526
  add_filter( 'w3tc_cdn_update_attachment_metadata', 'ewww_image_optimizer_w3tc_update_files' );
5527
 
5559
  // Register the attachment in the database as a cloudinary attachment.
5560
  $old_url = wp_get_attachment_url( $id );
5561
  wp_update_post( array(
5562
+ 'ID' => $id,
5563
  'guid' => $result['url'],
5564
  ) );
5565
  update_attached_file( $id, $result['url'] );
5566
  $meta['cloudinary'] = true;
5567
+ $errors = array();
5568
  // Update the image location for the attachment.
5569
  CloudinaryPlugin::update_image_src_all( $id, $result, $old_url, $result['url'], true, $errors );
5570
  if ( count( $errors ) > 0 ) {
5594
  if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
5595
  ewwwio_debug_message( print_r( $shield_user_man, true ) );
5596
  }
5597
+ if ( ! empty( $shield_user_man['session_lock_location'] ) && 'Y' == $shield_user_man['session_lock_location'] ) {
5598
  return true;
5599
  }
5600
  }
5629
  return $meta;
5630
  }
5631
  // Retrieve any posts that link the image.
5632
+ $esql = $wpdb->prepare( "SELECT ID, post_content FROM $wpdb->posts WHERE post_content LIKE %s", '%' . $wpdb->esc_like( $old_guid ) . '%' );
5633
  ewwwio_debug_message( "using query: $esql" );
5634
  // While there are posts to process.
5635
  $rows = $wpdb->get_results( $esql, ARRAY_A ); // WPCS: unprepared SQL ok.
5672
  continue;
5673
  }
5674
  // Retrieve any posts that link the resize.
5675
+ $rows = $wpdb->get_results( $wpdb->prepare( "SELECT ID, post_content FROM $wpdb->posts WHERE post_content LIKE %s", '%' . $wpdb->esc_like( $old_sguid ) . '%' ), ARRAY_A );
5676
  // While there are posts to process.
5677
  if ( ewww_image_optimizer_iterable( $rows ) ) {
5678
  foreach ( $rows as $row ) {
5705
  }
5706
  // Update the attachment post with the new mimetype and id.
5707
  wp_update_post( array(
5708
+ 'ID' => $id,
5709
  'post_mime_type' => $mime,
5710
  ) );
5711
  ewww_image_optimizer_debug_log();
5731
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
5732
 
5733
  // Retrieve the location of the WordPress upload folder.
5734
+ $upload_dir = wp_upload_dir( null, false, $refresh_cache );
5735
  $upload_path = trailingslashit( $upload_dir['basedir'] );
5736
  if ( ! $file ) {
5737
  $file = get_post_meta( $id, '_wp_attached_file', true );
5738
  } else {
5739
  ewwwio_debug_message( 'using prefetched _wp_attached_file' );
5740
  }
5741
+ $file_path = ( 0 !== strpos( $file, '/' ) && ! preg_match( '|^.:\\\|', $file ) ? $upload_path . $file : $file );
5742
  $filtered_file_path = apply_filters( 'get_attached_file', $file_path, $id );
5743
  ewwwio_debug_message( "WP (filtered) thinks the file is at: $filtered_file_path" );
5744
  if ( ( strpos( $filtered_file_path, 's3' ) === false || in_array( 's3', stream_get_wrappers() ) ) && is_file( $filtered_file_path ) ) {
5752
  ewwwio_debug_message( "finding path for IMS image: $id " );
5753
  if ( is_dir( $file_path ) && is_file( $file_path . $meta['file'] ) ) {
5754
  // Generate the absolute path.
5755
+ $file_path = $file_path . $meta['file'];
5756
  $upload_path = ewww_image_optimizer_upload_path( $file_path, $upload_path );
5757
  ewwwio_debug_message( "found path for IMS image: $file_path" );
5758
  } elseif ( is_file( $meta['file'] ) ) {
5759
+ $file_path = $meta['file'];
5760
  $upload_path = ewww_image_optimizer_upload_path( $file_path, $upload_path );
5761
  ewwwio_debug_message( "found path for IMS image: $file_path" );
5762
  } else {
5763
  $upload_path = trailingslashit( WP_CONTENT_DIR );
5764
+ $file_path = $upload_path . ltrim( $meta['file'], '/' );
5765
  ewwwio_debug_message( "checking path for IMS image: $file_path" );
5766
  if ( ! file_exists( $file_path ) ) {
5767
  $file_path = '';
5784
  return array( $file_path, $upload_path );
5785
  }
5786
  $upload_path = trailingslashit( WP_CONTENT_DIR ) . 'uploads/';
5787
+ $file_path = $upload_path . $meta['file'];
5788
  ewwwio_debug_message( "one last shot, using the wp-content/ constant: $file_path" );
5789
  if ( is_file( $file_path ) ) {
5790
  return array( $file_path, $upload_path );
5918
  $filenum = apply_filters( 'ewww_image_optimizer_converted_filename_suffix', 1 );
5919
  // But it must be only letters, numbers, or underscores.
5920
  $filenum = ( preg_match( '/^[\w\d]*$/', $filenum ) ? $filenum : 1 );
5921
+ $suffix = ( ! empty( $filenum ) ? '-' . $filenum : '' );
5922
  // While a file exists with the current increment.
5923
  while ( file_exists( $filename . $suffix . $fileext ) ) {
5924
  // Increment the increment...
5984
  for ( $y = 0; $y < $height; $y++ ) {
5985
  for ( $x = 0; $x < $width; $x++ ) {
5986
  $color = imagecolorat( $image, $x, $y );
5987
+ $rgb = imagecolorsforindex( $image, $color );
5988
  if ( $rgb['alpha'] > 0 ) {
5989
  ewwwio_debug_message( 'transparency found' );
5990
  return true;
6016
  $count = 0;
6017
  // We read through the file til we reach the end of the file, or we've found at least 2 frame headers.
6018
  while ( ! feof( $fh ) && $count < 2 ) {
6019
+ $chunk = fread( $fh, 1024 * 100 ); // Read 100kb at a time.
6020
  $count += preg_match_all( '#\x00\x21\xF9\x04.{4}\x00(\x2C|\x21)#s', $chunk, $matches );
6021
  }
6022
  fclose( $fh );
6036
  return 0;
6037
  }
6038
  $size_count = 0;
6039
+ $processed = array();
6040
  foreach ( $sizes as $size => $data ) {
6041
  if ( strpos( $size, 'webp' ) === 0 ) {
6042
  continue;
6054
  // If this is a unique size.
6055
  $size_count++;
6056
  // Sore info on the sizes we've processed, so we can check the list for duplicate sizes.
6057
+ $processed[ $size ]['width'] = $data['width'];
6058
  $processed[ $size ]['height'] = $data['height'];
6059
  }
6060
  return $size_count;
6096
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) && ! $return_output && ewww_image_optimizer_function_exists( 'print_r' ) ) {
6097
  $print_meta = print_r( $meta, true );
6098
  $print_meta = preg_replace( array( '/ /', '/\n+/' ), array( '&nbsp;', '<br />' ), $print_meta );
6099
+ $output .= '<div style="background-color:#ffff99;font-size: 10px;padding: 10px;margin:-10px -10px 10px;line-height: 1.1em">' . $print_meta . '</div>';
6100
  }
6101
+ $output .= "<div id='ewww-media-status-$id'>";
6102
  $ewww_cdn = false;
6103
  if ( is_array( $meta ) && ! empty( $meta['cloudinary'] ) ) {
6104
  $output .= esc_html__( 'Cloudinary image', 'ewww-image-optimizer' ) . '</div>';
6109
  return;
6110
  }
6111
  if ( is_array( $meta ) & class_exists( 'WindowsAzureStorageUtil' ) && ! empty( $meta['url'] ) ) {
6112
+ $output .= '<div>' . esc_html__( 'Azure Storage image', 'ewww-image-optimizer' ) . '</div>';
6113
  $ewww_cdn = true;
6114
  }
6115
  if ( is_array( $meta ) && class_exists( 'Amazon_S3_And_CloudFront' ) && preg_match( '/^(http|s3)\w*:/', get_attached_file( $id ) ) ) {
6116
+ $output .= '<div>' . esc_html__( 'Amazon S3 image', 'ewww-image-optimizer' ) . '</div>';
6117
  $ewww_cdn = true;
6118
  }
6119
  if ( is_array( $meta ) && class_exists( 'S3_Uploads' ) && preg_match( '/^(http|s3)\w*:/', get_attached_file( $id ) ) ) {
6120
+ $output .= '<div>' . esc_html__( 'Amazon S3 image', 'ewww-image-optimizer' ) . '</div>';
6121
  $ewww_cdn = true;
6122
  }
6123
  list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
6134
  if ( is_array( $meta ) && ( ! empty( $meta['ewww_image_optimizer'] ) || ! empty( $meta['converted'] ) ) ) {
6135
  $meta = ewww_image_optimizer_migrate_meta_to_db( $id, $meta );
6136
  }
6137
+ $msg = '';
6138
  $convert_desc = '';
6139
  $convert_link = '';
6140
  if ( $ewww_cdn ) {
6222
  }
6223
  $ewww_manual_nonce = wp_create_nonce( 'ewww-manual' );
6224
  global $wpdb;
6225
+ $in_progress = false;
6226
+ $migrated = false;
6227
  $optimized_images = false;
6228
  $backup_available = false;
6229
+ $file_parts = pathinfo( $file_path );
6230
+ $basename = $file_parts['filename'];
6231
  // If necessary, use get_post_meta( $post_id, '_wp_attachment_backup_sizes', true ); to only use basename for edited attachments, but that requires extra queries, so kiss for now.
6232
  if ( $ewww_cdn ) {
6233
  if ( get_transient( 'ewwwio-background-in-progress-' . $id ) ) {
6234
+ $output .= '<div>' . esc_html__( 'In Progress', 'ewww-image-optimizer' ) . '</div>';
6235
  $in_progress = true;
6236
  }
6237
  if ( ! $in_progress ) {
6238
+ $optimized_images = $wpdb->get_results( $wpdb->prepare( "SELECT image_size,orig_size,resize,converted,level,backup,updated FROM $wpdb->ewwwio_images WHERE attachment_id = %d AND gallery = 'media' AND image_size <> 0 ORDER BY orig_size DESC", $id ), ARRAY_A );
6239
  if ( ! $optimized_images ) {
6240
  // Attempt migration, but only if the original image is in the db, $migrated will be metadata on success, false on failure.
6241
  $migrated = ewww_image_optimizer_migrate_meta_to_db( $id, $meta, true );
6242
  }
6243
  if ( $migrated ) {
6244
+ $optimized_images = $wpdb->get_results( $wpdb->prepare( "SELECT image_size,orig_size,resize,converted,level,backup,updated FROM $wpdb->ewwwio_images WHERE attachment_id = %d AND gallery = 'media' AND image_size <> 0 ORDER BY orig_size DESC", $id ), ARRAY_A );
6245
  }
6246
  }
6247
  // If optimizer data exists in the db.
6267
  // Give the user the option to optimize the image right now.
6268
  if ( isset( $meta['sizes'] ) && ewww_image_optimizer_iterable( $meta['sizes'] ) ) {
6269
  $sizes_to_opt = ewww_image_optimizer_count_unoptimized_sizes( $meta['sizes'] ) + 1;
6270
+ $output .= '<div>' . sprintf( esc_html(
6271
  /* translators: %d: The number of resize/thumbnail images */
6272
  _n( '%d size to compress', '%d sizes to compress', $sizes_to_opt, 'ewww-image-optimizer' )
6273
  ), $sizes_to_opt ) . '</div>';
6283
  } // End if().
6284
  // End of output for CDN images.
6285
  if ( get_transient( 'ewwwio-background-in-progress-' . $id ) ) {
6286
+ $output .= esc_html__( 'In Progress', 'ewww-image-optimizer' );
6287
  $in_progress = true;
6288
  }
6289
  if ( ! $in_progress ) {
6290
+ $optimized_images = $wpdb->get_results( $wpdb->prepare( "SELECT image_size,orig_size,resize,converted,level,backup,updated FROM $wpdb->ewwwio_images WHERE attachment_id = %d AND gallery = 'media' AND image_size <> 0 ORDER BY orig_size DESC", $id ), ARRAY_A );
6291
  if ( ! $optimized_images ) {
6292
  // Attempt migration, but only if the original image is in the db, $migrated will be metadata on success, false on failure.
6293
  $migrated = ewww_image_optimizer_migrate_meta_to_db( $id, $meta, true );
6294
  }
6295
  if ( $migrated ) {
6296
+ $optimized_images = $wpdb->get_results( $wpdb->prepare( "SELECT image_size,orig_size,resize,converted,level,backup,updated FROM $wpdb->ewwwio_images WHERE attachment_id = %d AND gallery = 'media' AND image_size <> 0 ORDER BY orig_size DESC", $id ), ARRAY_A );
6297
  }
6298
  }
6299
  // If optimizer data exists.
6308
  }
6309
 
6310
  // Determine filepath for webp.
6311
+ $webpfile = $file_path . '.webp';
6312
  $webp_size = ewww_image_optimizer_filesize( $webpfile );
6313
  if ( $webp_size ) {
6314
  // Get a human readable filesize.
6315
  $webp_size = ewww_image_optimizer_size_format( $webp_size );
6316
+ $webpurl = esc_url( wp_get_attachment_url( $id ) . '.webp' );
6317
+ $output .= "<div>WebP: <a href='$webpurl'>$webp_size</a></div>";
6318
  }
6319
 
6320
  if ( empty( $msg ) && current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
6349
  // Otherwise, this must be an image we haven't processed.
6350
  if ( isset( $meta['sizes'] ) && ewww_image_optimizer_iterable( $meta['sizes'] ) ) {
6351
  $sizes_to_opt = ewww_image_optimizer_count_unoptimized_sizes( $meta['sizes'] ) + 1;
6352
+ $output .= '<div>' . sprintf( esc_html(
6353
  /* translators: %d: The number of resize/thumbnail images */
6354
  _n( '%d size to compress', '%d sizes to compress', $sizes_to_opt, 'ewww-image-optimizer' )
6355
  ), $sizes_to_opt ) . '</div>';
6395
  ewwwio_debug_message( 'unoptimized sizes cannot be counted' );
6396
  return 0;
6397
  }
6398
+ $sizes_to_opt = 0;
6399
  $disabled_sizes = get_option( 'ewww_image_optimizer_disable_resizes_opt' );
6400
 
6401
  // To keep track of the ones we have already processed.
6426
  }
6427
  $sizes_to_opt++;
6428
  // Store info on the sizes we've processed, so we can check the list for duplicate sizes.
6429
+ $processed[ $size ]['width'] = $data['width'];
6430
  $processed[ $size ]['height'] = $data['height'];
6431
  } // End foreach().
6432
  return $sizes_to_opt;
6449
  if ( empty( $id ) || empty( $optimized_images ) || ! is_array( $optimized_images ) ) {
6450
  return array( '', false, false );
6451
  }
6452
+ $orig_size = 0;
6453
+ $opt_size = 0;
6454
+ $level = 0;
6455
+ $converted = false;
6456
  $backup_available = false;
6457
+ $sizes_to_opt = 0;
6458
+ $output = '';
6459
+ $detail_output = '<table class="striped"><tr><th>&nbsp;</th><th>' . esc_html__( 'Image Size', 'ewww-image-optimizer' ) . '</th><th>' . esc_html__( 'Savings', 'ewww-image-optimizer' ) . '</th></tr>';
6460
  foreach ( $optimized_images as $optimized_image ) {
6461
  if ( ! empty( $optimized_image['attachment_id'] ) ) {
6462
  $id = $optimized_image['attachment_id'];
6463
  }
6464
  $orig_size += $optimized_image['orig_size'];
6465
+ $opt_size += $optimized_image['image_size'];
6466
  if ( 'full' == $optimized_image['resize'] ) {
6467
+ $level = $optimized_image['level'];
6468
  $updated_time = strtotime( $optimized_image['updated'] );
6469
  if ( DAY_IN_SECONDS * 30 + $updated_time > time() ) {
6470
  $backup_available = $optimized_image['backup'];
6477
  }
6478
  $sizes_to_opt++;
6479
  if ( ! empty( $optimized_image['resize'] ) ) {
6480
+ $display_size = ewww_image_optimizer_size_format( $optimized_image['image_size'] );
6481
  $detail_output .= '<tr><td><strong>' . ucfirst( $optimized_image['resize'] ) . "</strong></td><td>$display_size</td><td>" . esc_html( ewww_image_optimizer_image_results( $optimized_image['orig_size'], $optimized_image['image_size'] ) ) . '</td></tr>';
6482
  }
6483
  }
6487
  /* translators: %d: number of resizes/thumbnails compressed */
6488
  _n( '%d size compressed', '%d sizes compressed', $sizes_to_opt, 'ewww-image-optimizer' )
6489
  ), $sizes_to_opt );
6490
+ $output .= " <a href='#TB_inline?width=550&height=450&inlineId=ewww-attachment-detail-$id' class='thickbox'>(+)</a></div>";
6491
  $results_msg = ewww_image_optimizer_image_results( $orig_size, $opt_size );
6492
  // Output the optimizer results.
6493
+ $output .= '<div>' . esc_html( $results_msg ) . '</div>';
6494
  $display_size = ewww_image_optimizer_size_format( $opt_size );
6495
  // Output the total filesize.
6496
  $detail_output .= '<div><strong>' . sprintf(
6617
  // TODO: ditto.
6618
  return $meta;
6619
  }
6620
+ $converted = ( is_array( $meta ) && ! empty( $meta['converted'] ) && ! empty( $meta['orig_file'] ) ? trailingslashit( dirname( $file_path ) ) . basename( $meta['orig_file'] ) : false );
6621
  $full_size_update = ewww_image_optimizer_update_file_from_meta( $file_path, 'media', $id, 'full', $converted );
6622
  if ( ! $full_size_update && $bail_early ) {
6623
  ewwwio_debug_message( "bailing early for migration of $id" );
6651
  }
6652
 
6653
  $resize_path = $base_dir . $data['file'];
6654
+ $converted = ( is_array( $data ) && ! empty( $data['converted'] ) && ! empty( $data['orig_file'] ) ? trailingslashit( dirname( $resize_path ) ) . basename( $data['orig_file'] ) : false );
6655
  ewww_image_optimizer_update_file_from_meta( $resize_path, 'media', $id, $size, $converted );
6656
  // Search for retina images.
6657
  if ( function_exists( 'wr2x_get_retina' ) ) {
6668
  // Search sizes from a custom theme...
6669
  if ( isset( $meta['image_meta']['resized_images'] ) && ewww_image_optimizer_iterable( $meta['image_meta']['resized_images'] ) ) {
6670
  $imagemeta_resize_pathinfo = pathinfo( $file_path );
6671
+ $imagemeta_resize_path = '';
6672
  foreach ( $meta['image_meta']['resized_images'] as $index => $imagemeta_resize ) {
6673
  $imagemeta_resize_path = $imagemeta_resize_pathinfo['dirname'] . '/' . $imagemeta_resize_pathinfo['filename'] . '-' . $imagemeta_resize . '.' . $imagemeta_resize_pathinfo['extension'];
6674
  ewww_image_optimizer_update_file_from_meta( $imagemeta_resize_path, 'media', $id, 'resized-images-' . $index );
6678
  // and another custom theme.
6679
  if ( isset( $meta['custom_sizes'] ) && ewww_image_optimizer_iterable( $meta['custom_sizes'] ) ) {
6680
  $custom_sizes_pathinfo = pathinfo( $file_path );
6681
+ $custom_size_path = '';
6682
  foreach ( $meta['custom_sizes'] as $dimensions => $custom_size ) {
6683
  $custom_size_path = $custom_sizes_pathinfo['dirname'] . '/' . $custom_size['file'];
6684
  ewww_image_optimizer_update_file_from_meta( $custom_size_path, 'media', $id, 'custom-size-' . $dimensions );
6738
  $ids = implode( ',', array_map( 'intval', $_REQUEST['media'] ) );
6739
  wp_redirect( add_query_arg(
6740
  array(
6741
+ 'page' => 'ewww-image-optimizer-bulk',
6742
  '_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-bulk' ),
6743
+ 'goback' => 1,
6744
+ 'ids' => $ids,
6745
  ),
6746
  admin_url( 'upload.php' )
6747
  ) );
6808
  function ewww_image_optimizer_get_bad_attachments() {
6809
  $bad_attachment = get_transient( 'ewww_image_optimizer_rebuilding_attachment' );
6810
  if ( $bad_attachment ) {
6811
+ $bad_attachments = (array) ewww_image_optimizer_get_option( 'ewww_image_optimizer_bad_attachments' );
6812
  $bad_attachments[] = $bad_attachment;
6813
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_bad_attachments', $bad_attachments, false );
6814
  } else {
6826
  function ewww_image_optimizer_settings_script( $hook ) {
6827
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
6828
  // Make sure we are being called from the settings page.
6829
+ if ( strpos( $hook, 'settings_page_ewww-image-optimizer' ) !== 0 ) {
6830
  return;
6831
  }
6832
  wp_enqueue_script( 'ewwwbulkscript', plugins_url( '/includes/eio.js', __FILE__ ), array( 'jquery' ), EWWW_IMAGE_OPTIMIZER_VERSION );
6871
  ewwwio_debug_message( 'retrieving list of sites the easy way (pre 4.6)' );
6872
  $blogs = wp_get_sites( array(
6873
  'network_id' => $wpdb->siteid,
6874
+ 'limit' => 1000,
6875
  ) );
6876
  }
6877
  $total_savings = 0;
6885
  switch_to_blog( $blog_id );
6886
  ewwwio_debug_message( "getting savings for site: $blog_id" );
6887
  $table_name = $wpdb->prefix . 'ewwwio_images';
6888
+ ewwwio_debug_message( "table name is $table_name" );
6889
  if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name ) ) != $table_name ) {
6890
  ewww_image_optimizer_install_table();
6891
  }
6901
  } else {
6902
  ewwwio_debug_message( 'querying savings for single site' );
6903
  $total_savings = 0;
6904
+ $table_name = $wpdb->ewwwio_images;
6905
+ ewwwio_debug_message( "table name is $table_name" );
6906
  if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name ) ) != $table_name ) {
6907
  ewww_image_optimizer_install_table();
6908
  }
6927
  $newhtpath = trailingslashit( $htpath . $path_diff ) . '.htaccess';
6928
  if ( is_file( $newhtpath ) ) {
6929
  ewwwio_debug_message( 'subdir install confirmed' );
6930
+ ewwwio_debug_message( "using $newhtpath" );
6931
  return $newhtpath;
6932
  }
6933
  }
6934
+ ewwwio_debug_message( "using $htpath.htaccess" );
6935
  return $htpath . '.htaccess';
6936
  }
6937
 
6939
  * Called via AJAX, adds WebP rewrite rules to the .htaccess file.
6940
  */
6941
  function ewww_image_optimizer_webp_rewrite() {
6942
+ ewwwio_ob_clean();
6943
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
6944
  // Verify that the user is properly authorized.
6945
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-settings' ) ) {
6946
  wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
6953
  esc_html_e( 'Insertion failed', 'ewww-image-optimizer' );
6954
  }
6955
  }
6956
+ wp_die();
6957
+ }
6958
+
6959
+ /**
6960
+ * Called via AJAX, removes WebP rewrite rules from the .htaccess file.
6961
+ */
6962
+ function ewww_image_optimizer_webp_unwrite() {
6963
+ ewwwio_ob_clean();
6964
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
6965
+ // Verify that the user is properly authorized.
6966
+ if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-settings' ) ) {
6967
+ wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
6968
+ }
6969
+ if ( insert_with_markers( ewww_image_optimizer_htaccess_path(), 'EWWWIO', '' ) ) {
6970
+ esc_html_e( 'Removal successful', 'ewww-image-optimizer' );
6971
+ } else {
6972
+ esc_html_e( 'Removal failed', 'ewww-image-optimizer' );
6973
+ }
6974
+ wp_die();
6975
  }
6976
 
6977
  /**
6978
  * If rules are present, stay silent, otherwise, gives us some rules to insert!
6979
+ *
6980
+ * @return array Rules to be inserted.
6981
  */
6982
  function ewww_image_optimizer_webp_rewrite_verify() {
6983
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
6984
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
6985
+ if ( ewwwio_extract_from_markers( ewww_image_optimizer_htaccess_path(), 'EWWWIO' ) ) {
6986
+ ewwwio_debug_message( 'removing htaccess webp to prevent ExactDN problems' );
6987
+ insert_with_markers( ewww_image_optimizer_htaccess_path(), 'EWWWIO', '' );
6988
+ }
6989
+ }
6990
+ $current_rules = ewwwio_extract_from_markers( ewww_image_optimizer_htaccess_path(), 'EWWWIO' );
6991
+ $ewww_rules = array(
6992
  '<IfModule mod_rewrite.c>',
6993
  'RewriteEngine On',
6994
  'RewriteCond %{HTTP_ACCEPT} image/webp',
6995
  'RewriteCond %{REQUEST_FILENAME} (.*)\.(jpe?g|png)$',
6996
  'RewriteCond %{REQUEST_FILENAME}.webp -f',
6997
  'RewriteCond %{QUERY_STRING} !type=original',
6998
+ 'RewriteRule (.+)\.(jpe?g|png)$ %{REQUEST_URI}.webp [T=image/webp,E=accept:1,L]',
6999
  '</IfModule>',
7000
  '<IfModule mod_headers.c>',
7001
  'Header append Vary Accept env=REDIRECT_accept',
7009
  ! ewww_image_optimizer_array_search( 'Header append Vary Accept', $current_rules ) ||
7010
  ! ewww_image_optimizer_array_search( 'AddType image/webp', $current_rules )
7011
  ) {
7012
+ ewwwio_debug_message( 'missing or invalid rules' );
7013
  return $ewww_rules;
7014
  } else {
7015
+ ewwwio_debug_message( 'all good' );
7016
  return;
7017
  }
7018
  }
7019
 
7020
+ /**
7021
+ * Extracts strings from between the BEGIN and END markers in the .htaccess file.
7022
+ *
7023
+ * @param string $filename The file within which to search.
7024
+ * @param string $marker The bounary marker of the desired content.
7025
+ * @return array An array of strings from a file (.htaccess ) from between BEGIN and END markers.
7026
+ */
7027
+ function ewwwio_extract_from_markers( $filename, $marker ) {
7028
+ // All because someone didn't test changes in core...
7029
+ global $wp_version;
7030
+ if ( '4.9' != $wp_version ) {
7031
+ return extract_from_markers( $filename, $marker );
7032
+ }
7033
+ $result = array();
7034
+
7035
+ if ( ! file_exists( $filename ) ) {
7036
+ return $result;
7037
+ }
7038
+
7039
+ $markerdata = explode( "\n", implode( '', file( $filename ) ) );
7040
+
7041
+ $state = false;
7042
+ foreach ( $markerdata as $markerline ) {
7043
+ if ( false !== strpos( $markerline, '# END ' . $marker ) ) {
7044
+ $state = false;
7045
+ }
7046
+ if ( $state ) {
7047
+ $result[] = $markerline;
7048
+ }
7049
+ if ( false !== strpos( $markerline, '# BEGIN ' . $marker ) ) {
7050
+ $state = true;
7051
+ }
7052
+ }
7053
+ return $result;
7054
+ }
7055
+
7056
  /**
7057
  * Looks for a certain string within all array elements.
7058
  *
7075
  return false;
7076
  }
7077
 
7078
+ /**
7079
+ * Clear output buffers without throwing a fit.
7080
+ */
7081
+ function ewwwio_ob_clean() {
7082
+ if ( ob_get_length() ) {
7083
+ ob_end_clean();
7084
+ }
7085
+ }
7086
+
7087
  /**
7088
  * Retrieves a list of registered image sizes.
7089
  *
7094
  function ewww_image_optimizer_get_image_sizes() {
7095
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
7096
  global $_wp_additional_image_sizes;
7097
+ $sizes = array();
7098
  $image_sizes = get_intermediate_image_sizes();
7099
  if ( ewww_image_optimizer_function_exists( 'print_r' ) ) {
7100
  ewwwio_debug_message( print_r( $image_sizes, true ) );
7105
  if ( ewww_image_optimizer_iterable( $image_sizes ) ) {
7106
  foreach ( $image_sizes as $_size ) {
7107
  if ( in_array( $_size, array( 'thumbnail', 'medium', 'medium_large', 'large' ) ) ) {
7108
+ $sizes[ $_size ]['width'] = get_option( $_size . '_size_w' );
7109
  $sizes[ $_size ]['height'] = get_option( $_size . '_size_h' );
7110
  if ( 'medium_large' === $_size && 0 == $sizes[ $_size ]['width'] ) {
7111
  $sizes[ $_size ]['width'] = '768';
7115
  }
7116
  } elseif ( isset( $_wp_additional_image_sizes[ $_size ] ) ) {
7117
  $sizes[ $_size ] = array(
7118
+ 'width' => $_wp_additional_image_sizes[ $_size ]['width'],
7119
  'height' => $_wp_additional_image_sizes[ $_size ]['height'],
7120
  );
7121
  }
7122
  }
7123
  }
7124
  $sizes['pdf-full'] = array(
7125
+ 'width' => 99999,
7126
  'height' => 99999,
7127
  );
7128
 
7168
  ewwwio_debug_message( 'WP_CONTENT_DIR: ' . WP_CONTENT_DIR );
7169
  ewwwio_debug_message( 'home url: ' . get_home_url() );
7170
  ewwwio_debug_message( 'site url: ' . get_site_url() );
7171
+ ewwwio_debug_message( 'content_url: ' . content_url() );
7172
  $network_class = $network;
7173
  if ( empty( $network ) ) {
7174
  $network_class = 'singlesite';
7184
  if ( is_multisite() && is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) && ! get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) ) {
7185
  $network_class = 'network-multisite';
7186
  }
7187
+ $output = array();
7188
  $output[] = "<script type='text/javascript'>\n" .
7189
  'jQuery(document).ready(function($) {$(".fade").fadeTo(5000,1).fadeOut(3000);});' . "\n" .
7190
  "</script>\n";
7211
  } else {
7212
  $bulk_link = '<a href="upload.php?page=ewww-image-optimizer-bulk">' . esc_html__( 'Bulk Optimize', 'ewww-image-optimizer' ) . '</a>';
7213
  }
7214
+ $s3_link = '<a href="https://ewww.io/downloads/s3-image-optimizer/">' . esc_html__( 'S3 Image Optimizer', 'ewww-image-optimizer' ) . '</a>';
7215
  $output[] = '<p>' .
7216
  sprintf(
7217
  /* translators: %s: Bulk Optimize (link) */
7240
  if ( preg_match( '/great/', $verify_cloud ) ) {
7241
  $status_output .= '<span style="color: green">' . esc_html__( 'Verified,', 'ewww-image-optimizer' ) . ' </span>' . ewww_image_optimizer_cloud_quota();
7242
  } elseif ( preg_match( '/exceeded/', $verify_cloud ) ) {
7243
+ $status_output .= '<span style="color: orange">' . esc_html__( 'Verified,', 'ewww-image-optimizer' ) . '</span> <a href="https://ewww.io/plans/" target="_blank">' . ewww_image_optimizer_cloud_quota() . '</a>';
7244
+ $collapsible = false;
7245
  } else {
7246
  $status_output .= '<span style="color: red">' . esc_html__( 'Not Verified', 'ewww-image-optimizer' ) . '</span>';
7247
+ $collapsible = false;
7248
  }
7249
  $status_output .= "</p>\n";
7250
+ $disable_level = '';
7251
  } else {
7252
  $disable_level = "disabled='disabled'";
7253
  }
7254
+ if ( class_exists( 'Jetpack_Photon' ) && Jetpack::is_module_active( 'photon' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
7255
+ $status_output .= '<p><b>ExactDN:</b> <span style="color: red">' . esc_html__( 'Inactive, please disable the Image Performance option on the Jetpack Dashboard.', 'ewww-image-optimizer' ) . '</span></p>';
7256
+ $collapsible = false;
7257
+ } elseif ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
7258
+ $status_output .= '<p><b>ExactDN:</b> ';
7259
+ global $exactdn;
7260
+ if ( $exactdn->get_exactdn_domain() ) {
7261
+ $status_output .= '<span style="color: green">' . esc_html__( 'Verified', 'ewww-image-optimizer' ) . ' </span>';
7262
+ } else {
7263
+ $status_output .= '<span style="color: red"><a href="https://ewww.io/manage-sites/" target="_blank">' . esc_html__( 'Not Verified', 'ewww-image-optimizer' ) . '</a></span>';
7264
+ $collapsible = false;
7265
+ }
7266
+ $status_output .= '</p>';
7267
+ } else {
7268
+ $status_output .= '<p><b>ExactDN:</b> ' . esc_html__( 'Inactive, enable automatic resizing in the Resize Settings', 'ewww-image-optimizer' ) . '</p>';
7269
+ delete_option( 'ewww_image_optimizer_exactdn_domain' );
7270
+ delete_option( 'ewww_image_optimizer_exactdn_failures' );
7271
+ delete_option( 'ewww_image_optimizer_exactdn_validation' );
7272
+ delete_site_option( 'ewww_image_optimizer_exactdn_domain' );
7273
+ delete_site_option( 'ewww_image_optimizer_exactdn_failures' );
7274
+ delete_site_option( 'ewww_image_optimizer_exactdn_validation' );
7275
+ }
7276
  if ( ! ewww_image_optimizer_full_cloud() && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
7277
  list ( $jpegtran_src, $optipng_src, $gifsicle_src, $jpegtran_dst, $optipng_dst, $gifsicle_dst ) = ewww_image_optimizer_install_paths();
7278
  }
7279
+ $skip = ewww_image_optimizer_skip_tools();
7280
  $status_output .= "<p>\n";
7281
  if ( ! $skip['jpegtran'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
7282
  $status_output .= '<b>jpegtran:</b> ';
7290
  $status_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span>&emsp;' . esc_html__( 'version', 'ewww-image-optimizer' ) . ': ' . $jpegtran_installed . "<br />\n";
7291
  } else {
7292
  $status_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span><br />' . "\n";
7293
+ $collapsible = false;
7294
  }
7295
  }
7296
  if ( ! $skip['optipng'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
7305
  $status_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span>&emsp;' . esc_html__( 'version', 'ewww-image-optimizer' ) . ': ' . $optipng_version . "<br />\n";
7306
  } else {
7307
  $status_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span><br />' . "\n";
7308
+ $collapsible = false;
7309
  }
7310
  }
7311
  if ( ! $skip['pngout'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
7320
  $status_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span>&emsp;' . esc_html__( 'version', 'ewww-image-optimizer' ) . ': ' . preg_replace( '/PNGOUT \[.*\)\s*?/', '', $pngout_version ) . "<br />\n";
7321
  } else {
7322
  $status_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span>&emsp;' . esc_html__( 'Install', 'ewww-image-optimizer' ) . ' <a href="admin.php?action=ewww_image_optimizer_install_pngout">' . esc_html__( 'automatically', 'ewww-image-optimizer' ) . '</a> | <a href="http://advsys.net/ken/utils.htm">' . esc_html__( 'manually', 'ewww-image-optimizer' ) . '</a> - ' . esc_html__( 'Pngout is free closed-source software that can produce drastically reduced filesizes for PNGs, but can be very time consuming to process images', 'ewww-image-optimizer' ) . "<br />\n";
7323
+ $collapsible = false;
7324
  }
7325
  }
7326
  if ( ! $skip['gifsicle'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
7335
  $status_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span>&emsp;' . esc_html__( 'version', 'ewww-image-optimizer' ) . ': ' . $gifsicle_version . "<br />\n";
7336
  } else {
7337
  $status_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span><br />' . "\n";
7338
+ $collapsible = false;
7339
  }
7340
  }
7341
  if ( ! $skip['pngquant'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
7350
  $status_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span>&emsp;' . esc_html__( 'version', 'ewww-image-optimizer' ) . ': ' . $pngquant_version . "<br />\n";
7351
  } else {
7352
  $status_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span><br />' . "\n";
7353
+ $collapsible = false;
7354
  }
7355
  }
7356
+ if ( EWWW_IMAGE_OPTIMIZER_CWEBP && ! $skip['webp'] && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
7357
  $status_output .= '<b>webp:</b> ';
7358
+ if ( EWWW_IMAGE_OPTIMIZER_CWEBP ) {
7359
+ $webp_version = ewww_image_optimizer_tool_found( EWWW_IMAGE_OPTIMIZER_CWEBP, 'w' );
7360
  if ( ! $webp_version ) {
7361
+ $webp_version = ewww_image_optimizer_tool_found( EWWW_IMAGE_OPTIMIZER_CWEBP, 'wb' );
7362
  }
7363
  }
7364
  if ( ! empty( $webp_version ) ) {
7365
  $status_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span>&emsp;' . esc_html__( 'version', 'ewww-image-optimizer' ) . ': ' . $webp_version . "<br />\n";
7366
  } else {
7367
  $status_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span><br />' . "\n";
7368
+ $collapsible = false;
7369
  }
7370
  }
7371
  if ( ! ewww_image_optimizer_full_cloud() ) {
7372
  if ( ewww_image_optimizer_safemode_check() ) {
7373
  $status_output .= 'safe mode: <span style="color: red; font-weight: bolder">' . esc_html__( 'On', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7374
+ $collapsible = false;
7375
  } else {
7376
  $status_output .= 'safe mode: <span style="color: green; font-weight: bolder">' . esc_html__( 'Off', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7377
  }
7378
  if ( ewww_image_optimizer_exec_check() ) {
7379
  $status_output .= 'exec(): <span style="color: red; font-weight: bolder">' . esc_html__( 'Disabled', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7380
+ $collapsible = false;
7381
  } else {
7382
  $status_output .= 'exec(): <span style="color: green; font-weight: bolder">' . esc_html__( 'Enabled', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7383
  }
7390
  '<b>' . __( 'Graphics libraries', 'ewww-image-optimizer' ) . '</b> - '
7391
  );
7392
  $toolkit_output .= '<br>';
7393
+ $toolkit_found = false;
7394
  if ( ewww_image_optimizer_gd_support() ) {
7395
  $toolkit_output .= 'GD: <span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' );
7396
+ $toolkit_found = true;
7397
  } else {
7398
  $toolkit_output .= 'GD: <span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' );
7399
  }
7401
  'Gmagick: ';
7402
  if ( ewww_image_optimizer_gmagick_support() ) {
7403
  $toolkit_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' );
7404
+ $toolkit_found = true;
7405
  } else {
7406
  $toolkit_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' );
7407
  }
7409
  'Imagick: ';
7410
  if ( ewww_image_optimizer_imagick_support() ) {
7411
  $toolkit_output .= '<span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' );
7412
+ $toolkit_found = true;
7413
  } else {
7414
  $toolkit_output .= '<span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' );
7415
  }
7420
  $toolkit_output = str_replace( 'color: red', 'color: gray', $toolkit_output );
7421
  }
7422
  $status_output .= $toolkit_output;
7423
+ } else {
7424
+ ewww_image_optimizer_gd_support();
7425
+ ewww_image_optimizer_gmagick_support();
7426
+ ewww_image_optimizer_imagick_support();
7427
  } // End if().
7428
  $mimetype_output = '<b>' . esc_html__( 'Only need one of these:', 'ewww-image-optimizer' ) . ' </b><br>';
7429
  // Initialize this variable to check for the 'file' command if we don't have any php libraries we can use.
7430
  $file_command_check = true;
7431
+ $mimetype_tool = '';
7432
  if ( function_exists( 'finfo_file' ) ) {
7433
+ $mimetype_output .= 'fileinfo: <span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7434
  $file_command_check = false;
7435
+ $mimetype_tool = 'fileinfo';
7436
  } else {
7437
  $mimetype_output .= 'fileinfo: <span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7438
  }
7446
  $mimetype_output .= 'getimagesize(): <span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span>&emsp;&emsp;';
7447
  }
7448
  if ( function_exists( 'mime_content_type' ) ) {
7449
+ $mimetype_output .= 'mime_content_type(): <span style="color: green; font-weight: bolder">' . esc_html__( 'Installed', 'ewww-image-optimizer' ) . '</span><br />' . "\n";
7450
  $file_command_check = false;
7451
+ $mimetype_tool = empty( $mimetype_tool ) ? 'mime_content_type' : $mimetype_tool;
7452
  } else {
7453
  $mimetype_output .= 'mime_content_type(): <span style="color: red; font-weight: bolder">' . esc_html__( 'Missing', 'ewww-image-optimizer' ) . '</span><br />' . "\n";
7454
  }
7456
  if ( PHP_OS != 'WINNT' && ! ewww_image_optimizer_full_cloud() && ! EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
7457
  if ( $file_command_check && ! ewww_image_optimizer_find_nix_binary( 'file', 'f' ) ) {
7458
  $extra_tool_output .= '<span style="color: red; font-weight: bolder">file: ' . esc_html__( 'command not found on your system', 'ewww-image-optimizer' ) . '</span><br />';
7459
+ $collapsible = false;
7460
  } elseif ( empty( $mimetype_tool ) ) {
7461
  $mimetype_tool = 'file'; // So that we know a mimetype library was found.
7462
  }
7465
  }
7466
  if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_pngout' ) && ! $skip['pngout'] && PHP_OS != 'SunOS' && ! ewww_image_optimizer_find_nix_binary( 'tar', 't' ) ) {
7467
  $extra_tool_output .= '<span style="color: red; font-weight: bolder">tar: ' . esc_html__( 'command not found on your system', 'ewww-image-optimizer' ) . ' (' . esc_html__( 'required for automatic pngout installer', 'ewww-image-optimizer' ) . ')</span><br />';
7468
+ $collapsible = false;
7469
  }
7470
  } elseif ( $file_command_check ) {
7471
  $collapsible = false;
7518
  $output[] = "<input type='hidden' name='option_page' value='ewww_image_optimizer_options' />\n";
7519
  $output[] = "<input type='hidden' name='action' value='update' />\n";
7520
  $output[] = wp_nonce_field( 'ewww_image_optimizer_options-options', '_wpnonce', true, false ) . "\n";
7521
+ if ( is_multisite() && is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) && ! get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) ) {
7522
+ $output[] = '<i class="network-singlesite"><strong>' . esc_html__( 'Configure network-wide settings in the Network Admin.', 'ewww-image-optimizer' ) . "</strong></i>\n";
7523
+ }
7524
  $output[] = "<div id='ewww-general-settings'>\n";
7525
  $output[] = "<table class='form-table'>\n";
7526
  if ( is_multisite() ) {
7529
  $output[] = "<tr><th><label for='ewww_image_optimizer_allow_tracking'>" . esc_html__( 'Allow Usage Tracking?', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_allow_tracking' name='ewww_image_optimizer_allow_tracking' value='true' " . ( get_site_option( 'ewww_image_optimizer_allow_tracking' ) == true ? "checked='true'" : '' ) . ' /> ' .
7530
  esc_html__( 'Allow EWWW Image Optimizer to anonymously track how this plugin is used and help us make the plugin better. Opt-in to tracking and receive 500 API image credits free. No sensitive data is tracked.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7531
  $output[] = "<input type='hidden' id='ewww_image_optimizer_allow_multisite_override_active' name='ewww_image_optimizer_allow_multisite_override_active' value='0'>";
7532
+ if ( get_site_option( 'ewww_image_optimizer_cloud_key' ) ) {
7533
+ $output[] = "<input type='hidden' id='ewww_image_optimizer_cloud_key' name='ewww_image_optimizer_cloud_key' value='" . get_site_option( 'ewww_image_optimizer_cloud_key' ) . "' />\n";
7534
+ }
7535
  foreach ( $output as $line ) {
7536
  echo $line;
7537
  }
7542
  }
7543
  }
7544
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
7545
+ $blog_id = get_current_blog_id();
7546
+ $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_cloud_notkey'>" . esc_html__( 'Cloud optimization API Key', 'ewww-image-optimizer' ) . "</label></th><td><input type='text' id='ewww_image_optimizer_cloud_notkey' name='ewww_image_optimizer_cloud_notkey' readonly='readonly' value='****************************" . substr( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ), 28 ) . "' size='32' /> <a href='admin.php?action=ewww_image_optimizer_remove_cloud_key&site=$blog_id'>" . esc_html__( 'Remove API key', 'ewww-image-optimizer' ) . "</a></td></tr>\n";
7547
  $output[] = "<input type='hidden' id='ewww_image_optimizer_cloud_key' name='ewww_image_optimizer_cloud_key' value='" . ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) . "' />\n";
7548
  } else {
7549
+ $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_cloud_key'>" . esc_html__( 'Cloud optimization API Key', 'ewww-image-optimizer' ) . "</label></th><td><input type='text' id='ewww_image_optimizer_cloud_key' name='ewww_image_optimizer_cloud_key' value='' size='32' /> " . esc_html__( 'API Key will be validated when you save your settings.', 'ewww-image-optimizer' ) . " <a href='https://ewww.io/plans/' target='_blank'>" . esc_html__( 'Purchase an API key.', 'ewww-image-optimizer' ) . "</a></td></tr>\n";
7550
  }
7551
  $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_debug'>" . esc_html__( 'Debugging', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_debug' name='ewww_image_optimizer_debug' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Use this to provide information for support purposes, or if you feel comfortable digging around in the code to fix a problem you are experiencing.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7552
  $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_jpegtran_copy'>" . esc_html__( 'Remove metadata', 'ewww-image-optimizer' ) . "</label></th>\n" .
7589
  $disable_pdf_level = $disable_level;
7590
  if ( 'getimagesize' == $mimetype_tool ) {
7591
  $disable_pdf_level = "disabled='disabled'";
7592
+ $output[] = "<tr class='$network_class'><th>&nbsp;</th><td>";
7593
+ $output[] = "<p class='$network_class description'>" . esc_html__( '*PDF optimization cannot be enabled because the fileinfo extension is missing.', 'ewww-image-optimizer' ) . "</p></td></tr>\n";
7594
  }
7595
  $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_pdf_level'>" . esc_html__( 'PDF Optimization Level', 'ewww-image-optimizer' ) . "</label></th>\n" .
7596
  "<td><span><select id='ewww_image_optimizer_pdf_level' name='ewww_image_optimizer_pdf_level'>\n" .
7624
  $media_include_disable = '';
7625
  if ( get_option( 'ewww_image_optimizer_disable_resizes_opt' ) ) {
7626
  $media_include_disable = 'disabled="disabled"';
7627
+ $output[] = "<tr class='$network_class'><th>&nbsp;</th><td>" .
7628
  '<p><span style="color: green">' . esc_html__( '*Include Media Library Folders has been disabled because it will cause the scanner to ignore the disabled resizes.', 'ewww-image-optimizer' ) . "</span></p></td></tr>\n";
7629
  }
7630
  $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_include_media_paths'>" . esc_html__( 'Include Media Library Folders', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_include_media_paths' name='ewww_image_optimizer_include_media_paths' $media_include_disable value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_include_media_paths' ) == true && ! get_option( 'ewww_image_optimizer_disable_resizes_opt' ) ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Scan all images from the latest two folders of the Media Library during the Bulk Optimizer and Scheduled Optimization.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7631
  ewwwio_debug_message( 'include media library: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_include_media_paths' ) == true ? 'on' : 'off' ) );
7632
  $aux_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_aux_paths' ) ? esc_html( implode( "\n", ewww_image_optimizer_get_option( 'ewww_image_optimizer_aux_paths' ) ) ) : '';
7633
+ $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_aux_paths'>" . esc_html__( 'Folders to optimize', 'ewww-image-optimizer' ) . '</label></th><td>' .
7634
  /* translators: %s: the folder where WordPress is installed */
7635
  sprintf( esc_html__( 'One path per line, must be within %s. Use full paths, not relative paths.', 'ewww-image-optimizer' ), ABSPATH ) . "<br>\n" .
7636
  "<textarea id='ewww_image_optimizer_aux_paths' name='ewww_image_optimizer_aux_paths' rows='3' cols='60'>$aux_paths</textarea>\n" .
7639
  ewwwio_debug_message( $aux_paths );
7640
 
7641
  $exclude_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_exclude_paths' ) ? esc_html( implode( "\n", ewww_image_optimizer_get_option( 'ewww_image_optimizer_exclude_paths' ) ) ) : '';
7642
+ $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_exclude_paths'>" . esc_html__( 'Folders to ignore', 'ewww-image-optimizer' ) . '</label></th><td>' . esc_html__( 'One path per line, partial paths allowed, but no urls.', 'ewww-image-optimizer' ) . "<br>\n" .
7643
  "<textarea id='ewww_image_optimizer_exclude_paths' name='ewww_image_optimizer_exclude_paths' rows='3' cols='60'>$exclude_paths</textarea>\n" .
7644
  "<p class='description'>" . esc_html__( 'A file that matches any pattern or path provided will not be optimized.', 'ewww-image-optimizer' ) . "</p></td></tr>\n";
7645
  ewwwio_debug_message( 'folders to ignore:' );
7658
 
7659
  $output[] = "<div id='ewww-resize-settings'>\n";
7660
  $output[] = "<table class='form-table'>\n";
7661
+ $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_exactdn'>" . esc_html__( 'ExactDN', 'ewww-image-optimizer' ) .
7662
+ "</label></th><td><input type='checkbox' id='ewww_image_optimizer_exactdn' name='ewww_image_optimizer_exactdn' value='true' " .
7663
+ ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) == true ? "checked='true'" : '' ) . ' /> ' .
7664
+ esc_html__( 'Enables CDN and automatic image resizing to fit your pages.', 'ewww-image-optimizer' ) .
7665
+ ' <a href="https://ewww.io/resize/" target="_blank">' . esc_html__( 'Purchase a subscription for your site.', 'ewww-image-optimizer' ) . '</a>' .
7666
+ '<p class="description">' . // esc_html__( 'WebP Conversion', 'ewww-image-optimizer' ) . '<br>' .
7667
+ esc_html__( 'Retina Support, use WP Retina 2x for best results', 'ewww-image-optimizer' ) . '<br>' .
7668
+ esc_html__( 'Maximum Lossless Compression', 'ewww-image-optimizer' ) . '<br>' .
7669
+ esc_html__( 'Adjustable Quality', 'ewww-image-optimizer' ) . '<br>' .
7670
+ '<a href="http://docs.ewww.io/article/44-introduction-to-exactdn" target="_blank" data-beacon-article="59bc5ad6042863033a1ce370">' . esc_html__( 'Learn more about ExactDN', 'ewww-image-optimizer' ) . '</a>' .
7671
+ "</p></td></tr>\n";
7672
+ ewwwio_debug_message( 'ExactDN enabled: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) == true ? 'on' : 'off' ) );
7673
+ $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_resize_detection'>" . esc_html__( 'Resize Detection', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_resize_detection' name='ewww_image_optimizer_resize_detection' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_detection' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Highlight images that need to be resized because the browser is scaling them down. Only visible for Admin users and adds a button to the admin bar to detect scaled images that have been lazy loaded.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7674
+ ewwwio_debug_message( 'resize detection: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_detection' ) == true ? 'on' : 'off' ) );
7675
  if ( function_exists( 'imsanity_get_max_width_height' ) ) {
7676
  $output[] = "<tr class='$network_class'><th>&nbsp;</th><td>" .
7677
  '<p><span style="color: green">' . esc_html__( '*Imsanity settings override the EWWW resize dimensions.', 'ewww-image-optimizer' ) . "</span></p></td></tr>\n";
7681
  "</td></tr>\n";
7682
  ewwwio_debug_message( 'max media dimensions: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediawidth' ) . ' x ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxmediaheight' ) );
7683
  $output[] = "<tr class='$network_class'><th>" . esc_html__( 'Resize Other Images', 'ewww-image-optimizer' ) . "</th><td><label for='ewww_image_optimizer_maxotherwidth'>" . esc_html__( 'Max Width', 'ewww-image-optimizer' ) . "</label> <input type='number' step='1' min='0' class='small-text' id='ewww_image_optimizer_maxotherwidth' name='ewww_image_optimizer_maxotherwidth' value='" . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherwidth' ) . ( function_exists( 'imsanity_get_max_width_height' ) ? "' disabled='disabled" : '' ) . "' /> <label for='ewww_image_optimizer_maxotherheight'>" . esc_html__( 'Max Height', 'ewww-image-optimizer' ) . "</label> <input type='number' step='1' min='0' class='small-text' id='ewww_image_optimizer_maxotherheight' name='ewww_image_optimizer_maxotherheight' value='" . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherheight' ) . ( function_exists( 'imsanity_get_max_width_height' ) ? "' disabled='disabled" : '' ) . "' /> " . esc_html__( 'in pixels', 'ewww-image-optimizer' ) . "\n" .
7684
+ "<p class='description'>" . esc_html__( 'Resizes images uploaded indirectly to the Media Library, like theme images or front-end uploads. Also applied to existing images during Bulk Optimization if necessary.', 'ewww-image-optimizer' ) .
7685
  "</td></tr>\n";
7686
  ewwwio_debug_message( 'max other dimensions: ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherwidth' ) . ' x ' . ewww_image_optimizer_get_option( 'ewww_image_optimizer_maxotherheight' ) );
7687
  $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_resize_existing'>" . esc_html__( 'Resize Existing Images', 'ewww-image-optimizer' ) . "</label></th><td><input type='checkbox' id='ewww_image_optimizer_resize_existing' name='ewww_image_optimizer_resize_existing' value='true' " . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' ) == true ? "checked='true'" : '' ) . ' /> ' . esc_html__( 'Allow resizing of existing Media Library images.', 'ewww-image-optimizer' ) . "</td></tr>\n";
7688
  ewwwio_debug_message( 'resize existing images: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_existing' ) == true ? 'on' : 'off' ) );
7689
 
7690
+ $output[] = '<tr class="network-singlesite"><th>' . esc_html__( 'Disable Resizes', 'ewww-image-optimizer' ) . '</th><td><p>' . esc_html__( 'WordPress, your theme, and other plugins generate various image sizes. You may disable optimization for certain sizes, or completely prevent those sizes from being created.', 'ewww-image-optimizer' ) . "</p>\n";
7691
+ $image_sizes = ewww_image_optimizer_get_image_sizes();
7692
+ $disabled_sizes = get_option( 'ewww_image_optimizer_disable_resizes' );
7693
  $disabled_sizes_opt = get_option( 'ewww_image_optimizer_disable_resizes_opt' );
7694
+ $output[] = '<table><tr class="network-singlesite"><th>' . esc_html__( 'Disable Optimization', 'ewww-image-optimizer' ) . '</th><th>' . esc_html__( 'Disable Creation', 'ewww-image-optimizer' ) . "</th></tr>\n";
7695
  ewwwio_debug_message( 'disabled resizes:' );
7696
  foreach ( $image_sizes as $size => $dimensions ) {
7697
  if ( 'thumbnail' == $size ) {
7698
+ $output[] = "<tr class='network-singlesite'><td><input type='checkbox' id='ewww_image_optimizer_disable_resizes_opt_$size' name='ewww_image_optimizer_disable_resizes_opt[$size]' value='true' " . ( ! empty( $disabled_sizes_opt[ $size ] ) ? "checked='true'" : '' ) . " /></td><td><input type='checkbox' id='ewww_image_optimizer_disable_resizes_$size' name='ewww_image_optimizer_disable_resizes[$size]' value='true' disabled /></td><td><label for='ewww_image_optimizer_disable_resizes_$size'>$size - {$dimensions['width']}x{$dimensions['height']}</label></td></tr>\n";
7699
  } elseif ( 'pdf-full' == $size ) {
7700
+ $output[] = "<tr class='network-singlesite'><td><input type='checkbox' id='ewww_image_optimizer_disable_resizes_opt_$size' name='ewww_image_optimizer_disable_resizes_opt[$size]' value='true' " . ( ! empty( $disabled_sizes_opt[ $size ] ) ? "checked='true'" : '' ) . " /></td><td><input type='checkbox' id='ewww_image_optimizer_disable_resizes_$size' name='ewww_image_optimizer_disable_resizes[$size]' value='true' " . ( ! empty( $disabled_sizes[ $size ] ) ? "checked='true'" : '' ) . " /></td><td><label for='ewww_image_optimizer_disable_resizes_$size'>$size - <span class='description'>" . esc_html__( 'Disabling creation of the full-size preview for PDF files will disable all PDF preview sizes', 'ewww-image-optimizer' ) . "</span></label></td></tr>\n";
7701
  } else {
7702
+ $output[] = "<tr class='network-singlesite'><td><input type='checkbox' id='ewww_image_optimizer_disable_resizes_opt_$size' name='ewww_image_optimizer_disable_resizes_opt[$size]' value='true' " . ( ! empty( $disabled_sizes_opt[ $size ] ) ? "checked='true'" : '' ) . " /></td><td><input type='checkbox' id='ewww_image_optimizer_disable_resizes_$size' name='ewww_image_optimizer_disable_resizes[$size]' value='true' " . ( ! empty( $disabled_sizes[ $size ] ) ? "checked='true'" : '' ) . " /></td><td><label for='ewww_image_optimizer_disable_resizes_$size'>$size - {$dimensions['width']}x{$dimensions['height']}</label></td></tr>\n";
7703
  }
7704
  ewwwio_debug_message( $size . ': ' . ( ! empty( $disabled_sizes_opt[ $size ] ) ? 'optimization=disabled ' : 'optimization=enabled ' ) . ( ! empty( $disabled_sizes[ $size ] ) ? 'creation=disabled' : 'creation=enabled' ) );
7705
  }
7749
  ewwwio_debug_message( 'forced webp: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) == true ? 'on' : 'off' ) );
7750
  if ( ! ewww_image_optimizer_ce_webp_enabled() ) {
7751
  $webp_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' ) ? esc_html( implode( "\n", ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' ) ) ) : '';
7752
+ $output[] = "<tr class='$network_class'><th><label for='ewww_image_optimizer_webp_paths'>" . esc_html__( 'WebP URLs', 'ewww-image-optimizer' ) . '</label></th><td>' . esc_html__( 'If Force WebP is enabled, enter URL patterns that should be permitted for Alternative WebP Rewriting. One pattern per line, may be partial URLs, but must include the domain name.', 'ewww-image-optimizer' ) . '<br>' .
7753
  "<textarea id='ewww_image_optimizer_webp_paths' name='ewww_image_optimizer_webp_paths' rows='3' cols='60'>$webp_paths</textarea></td></tr>\n";
7754
  ewwwio_debug_message( 'webp paths:' );
7755
  ewwwio_debug_message( $webp_paths );
7765
  $output[] = "</table>\n</div>\n";
7766
  $output[] = "<p class='submit'><input type='submit' class='button-primary' value='" . esc_attr__( 'Save Changes', 'ewww-image-optimizer' ) . "' /></p>\n";
7767
  $output[] = "</form>\n";
7768
+ // Make sure .htaccess rules are terminated when ExactDN is enabled.
7769
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
7770
+ ewww_image_optimizer_webp_rewrite_verify();
7771
+ }
7772
+ if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) && ! ewww_image_optimizer_ce_webp_enabled() && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
7773
  $output[] = "<form id='ewww-webp-rewrite'>\n";
7774
  $output[] = '<p>' . esc_html__( 'There are many ways to serve WebP images to visitors with supported browsers. You may choose any you wish, but it is recommended to serve them with an .htaccess file using mod_rewrite and mod_headers. The plugin can insert the rules for you if the file is writable, or you can edit .htaccess yourself.', 'ewww-image-optimizer' ) . "</p>\n";
7775
  if ( ! ewww_image_optimizer_webp_rewrite_verify() ) {
7776
  $output[] = "<img id='webp-image' src='" . plugins_url( '/images/test.png', __FILE__ ) . "' style='float: right; padding: 0 0 10px 10px;'>\n" .
7777
+ "<p id='ewww-webp-rewrite-status'><b>" . esc_html__( 'Rules verified successfully', 'ewww-image-optimizer' ) . "</b></p>\n" .
7778
+ "<button type='submit' id='ewww-webp-remove' class='button-secondary action'>" . esc_html__( 'Remove Rewrite Rules', 'ewww-image-optimizer' ) . "</button>\n";
7779
  ewwwio_debug_message( 'webp .htaccess rewriting enabled' );
7780
  } else {
7781
  $output[] = "<pre id='webp-rewrite-rules' style='background: white; font-color: black; border: 1px solid black; clear: both; padding: 10px;'>\n" .
7793
  "AddType image/webp .webp</pre>\n" .
7794
  "<img id='webp-image' src='" . plugins_url( '/images/test.png', __FILE__ ) . "' style='float: right; padding-left: 10px;'>\n" .
7795
  "<p id='ewww-webp-rewrite-status'>" . esc_html__( 'The image to the right will display a WebP image with WEBP in white text, if your site is serving WebP images and your browser supports WebP.', 'ewww-image-optimizer' ) . "</p>\n" .
7796
+ "<button type='submit' id='ewww-webp-insert' class='button-secondary action'>" . esc_html__( 'Insert Rewrite Rules', 'ewww-image-optimizer' ) . "</button>\n";
7797
  ewwwio_debug_message( 'webp .htaccess rules not detected' );
7798
  }
7799
  $output[] = "</form>\n";
7800
  } elseif ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) && ! ewww_image_optimizer_ce_webp_enabled() ) {
7801
  $test_webp_image = plugins_url( '/images/test.png.webp', __FILE__ );
7802
+ $test_png_image = plugins_url( '/images/test.png', __FILE__ );
7803
+ $output[] = "<noscript data-img='$test_png_image' data-webp='$test_webp_image' data-style='float: right; padding: 0 0 10px 10px;' class='ewww_webp'><img src='$test_png_image' style='float: right; padding: 0 0 10px 10px;'></noscript>\n";
7804
  }
7805
  $output[] = "</div><!-- end container left -->\n";
7806
  $output[] = "<div id='ewww-container-right' style='border: 1px solid #e5e5e5; float: right; margin-left: -215px; padding: 0em 1.5em 1em; background-color: #fff; box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04); display: inline-block; width: 174px;'>\n" .
7809
  "<p><a href='https://translate.wordpress.org/projects/wp-plugins/ewww-image-optimizer/'>" . esc_html__( 'Help translate EWWW I.O.', 'ewww-image-optimizer' ) . "</a></p>\n" .
7810
  "<p><a href='https://wordpress.org/support/view/plugin-reviews/ewww-image-optimizer#postform'>" . esc_html__( 'Write a review.', 'ewww-image-optimizer' ) . "</a></p>\n" .
7811
  /* translators: %s: Paypal (link) */
7812
+ '<p>' . sprintf( esc_html__( 'Contribute directly via %s.', 'ewww-image-optimizer' ), "<a href='https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=MKMQKCBFFG3WW'>Paypal</a>" ) . "</p>\n" .
7813
+ '<p>' . esc_html__( 'Signup for premium image optimization:', 'ewww-image-optimizer' ) . "<br>\n" .
7814
+ "<a target='_blank' href='https://ewww.io/plans/'>" . esc_html__( 'Compress', 'ewww-image-optimizer' ) . "</a><br>\n" .
7815
+ "<a target='_blank' href='https://ewww.io/resize/'>" . esc_html__( 'Resize', 'ewww-image-optimizer' ) . "</a></p>\n" .
7816
+ '<p><b>' . esc_html_x( 'CDN:', 'abbreviation for Content Delivery Network', 'ewww-image-optimizer' ) . "</b><br><a target='_blank' href='https://ewww.io/resize/'>" . esc_html__( 'Add ExactDN to increase website speeds dramatically!', 'ewww-image-optimizer' ) . "</a></p>\n" .
 
 
 
 
 
7817
  "</div>\n" .
7818
  "</div>\n";
7819
  ewwwio_debug_message( 'max_execution_time: ' . ini_get( 'max_execution_time' ) );
7864
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_help' ) ) {
7865
  /* $help_instructions = esc_html__( 'Please turn on the Debugging option. Then copy and paste the Debug Information from the bottom of the settings page. This will allow us to assist you more quickly.', 'ewww-image-optimizer' ); */
7866
  $current_user = wp_get_current_user();
7867
+ $help_email = $current_user->user_email;
7868
+ $hs_config = array(
7869
+ 'color' => '#3eadc9',
7870
+ 'icon' => 'buoy',
7871
+ 'instructions' => $help_instructions,
7872
+ 'poweredBy' => false,
7873
  'showContactFields' => true,
7874
+ 'showSubject' => true,
7875
+ 'topArticles' => true,
7876
+ 'zIndex' => 100000,
7877
  );
7878
+ $hs_identify = array(
7879
  'email' => $help_email,
7880
  );
7881
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
7882
  $ewww_debug_array = explode( '<br>', $ewww_debug );
7883
+ $ewww_debug_i = 0;
7884
  foreach ( $ewww_debug_array as $ewww_debug_line ) {
7885
  $hs_identify[ 'debug_info_' . $ewww_debug_i ] = $ewww_debug_line;
7886
  $ewww_debug_i++;
7979
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' ) > 0 ) {
7980
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_pdf_level', 0 );
7981
  }
7982
+ ewww_image_optimizer_set_option( 'ewww_image_optimizer_cloud_exceeded', 0 );
7983
+ delete_transient( 'ewww_image_optimizer_cloud_status' );
7984
  ewww_image_optimizer_set_option( 'ewww_image_optimizer_backup_files', '' );
7985
  $sendback = wp_get_referer();
7986
  wp_redirect( esc_url_raw( $sendback ) );
7997
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_resize_detection' ) ) {
7998
  wp_enqueue_script( 'ewww-resize-detection', plugins_url( '/includes/resize_detection.js', __FILE__ ), array(), EWWW_IMAGE_OPTIMIZER_VERSION );
7999
  }
8000
+ add_filter( 'autoptimize_filter_js_exclude', 'ewww_image_optimizer_autoptimize_js_exclude', -1, 2 );
8001
+ }
8002
+
8003
+ /**
8004
+ * Makes sure the resize detection script is excluded from Autoptimize functions.
8005
+ *
8006
+ * @param string $jsexcludes A list of exclusions from Autoptimize.
8007
+ * @param string $content The page content being parsed by Autoptimize.
8008
+ * @return string The JS excludes plus one more.
8009
+ */
8010
+ function ewww_image_optimizer_autoptimize_js_exclude( $jsexcludes = '', $content = '' ) {
8011
+ ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
8012
+ if ( is_array( $jsexcludes ) ) {
8013
+ $jsexcludes['includes/resize_detection.js'] = '';
8014
+ return $jsexludes;
8015
+ }
8016
+ return $jsexcludes . ', includes/resize_detection.js';
8017
  }
8018
 
8019
  /**
8061
  ewwwio_debug_version_info();
8062
  $ewww_version_dumped = true;
8063
  }
8064
+ $message = str_replace( "\n\n\n", '<br>', $message );
8065
+ $message = str_replace( "\n\n", '<br>', $message );
8066
+ $message = str_replace( "\n", '<br>', $message );
8067
  $ewww_debug .= "$message<br>";
8068
  } else {
8069
  global $ewww_debug;
8072
  }
8073
  }
8074
 
8075
+ /**
8076
+ * Loads the logfile and displays it in the WP admin.
8077
+ */
8078
+ function ewww_image_optimizer_debug_log_display() {
8079
+ if ( file_exists( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'debug.log' ) ) {
8080
+ $ewww_debug_log = file_get_contents( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'debug.log' );
8081
+ $ewww_debug_log = str_replace( "\n", '<br>', $ewww_debug_log );
8082
+ echo $ewww_debug_log;
8083
+ } else {
8084
+ esc_html_e( 'The Debug Log is empty.', 'ewww-image-optimizer' );
8085
+ }
8086
+ }
8087
+
8088
  /**
8089
  * Saves the in-memory debug log to a logfile in the plugin folder.
8090
  *
8145
 
8146
  // Check the WP version.
8147
  global $wp_version;
8148
+ $my_version = substr( $wp_version, 0, 3 );
8149
+ $ewww_debug .= "WP version: $wp_version<br>";
8150
 
8151
  if ( defined( 'PHP_VERSION_ID' ) ) {
8152
  $ewww_debug .= 'PHP version: ' . PHP_VERSION_ID . '<br>';
8210
  $i++;
8211
  }
8212
  } else {
8213
+ esc_html_e( 'Cannot display trace', 'ewww-image-optimizer' );
8214
  }
8215
  echo '</p>';
8216
  }
8262
  echo "<div class='wrap'><h1>" . esc_html__( 'Image Queue Debugging', 'ewww-image-optimizer' ) . '</h1>';
8263
  global $wpdb;
8264
 
8265
+ $table = $wpdb->options;
8266
 
8267
+ $key = 'wp_ewwwio_media_optimize_batch_%';
8268
  $queues = $wpdb->get_results(
8269
  $wpdb->prepare( "
8270
  SELECT *
8287
  foreach ( $items as $item ) {
8288
  echo "{$item['id']} - {$item['type']}<br>";
8289
  $all_ids[] = $item['id'];
8290
+ $ids[] = $item['id'];
8291
  }
8292
  $ids = implode( ',', $ids );
8293
  ?>
8324
  if ( ! defined( 'EWWW_MEMORY_LIMIT' ) ) {
8325
  // Conservative default, current usage + 16M.
8326
  $current_memory = memory_get_usage( true );
8327
+ $memory_limit = round( $current_memory / ( 1024 * 1024 ) ) + 16;
8328
  define( 'EWWW_MEMORY_LIMIT', $memory_limit );
8329
  }
8330
  }
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: 3.6.1
18
  Author URI: https://ewww.io/
19
  License: GPLv3
20
  */
@@ -59,6 +59,11 @@ if ( ! defined( 'PHP_VERSION_ID' ) || PHP_VERSION_ID < 50300 ) {
59
  add_action( 'admin_notices', 'ewww_image_optimizer_notice_wpengine' );
60
  // Loads the plugin translations.
61
  add_action( 'plugins_loaded', 'ewww_image_optimizer_false_init' );
 
 
 
 
 
62
  } else {
63
  /**
64
  * The full path of the plugin file (this file).
@@ -122,7 +127,7 @@ if ( ! function_exists( 'ewww_image_optimizer_unsupported_php' ) ) {
122
  * Display a notice that the PHP version is too old.
123
  */
124
  function ewww_image_optimizer_unsupported_php() {
125
- echo "<div id='ewww-image-optimizer-warning-php' class='error'><p><strong>" . esc_html__( 'EWWW Image Optimizer requires PHP 5.3 or greater. Newer versions of PHP, like 5.6, 7.0 and 7.1, are significantly faster and much more secure, as PHP 5.2 has been unsupported for several years. If you are unsure how to upgrade to a supported version, ask your webhost for instructions.', 'ewww-image-optimizer' ) . '</strong></p></div>';
126
  }
127
 
128
  /**
@@ -153,3 +158,10 @@ function ewww_image_optimizer_notice_wpengine() {
153
  function ewww_image_optimizer_notice_kinsta() {
154
  echo "<div id='ewww-image-optimizer-warning-kinsta' class='error'><p>" . esc_html__( 'The regular version of the EWWW Image Optimizer plugin is not permitted on Kinsta sites. Please deactivate EWWW Image Optimizer and install EWWW Image Optimizer Cloud to optimize your images.', 'ewww-image-optimizer' ) . '</p></div>';
155
  }
 
 
 
 
 
 
 
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.0.6
18
  Author URI: https://ewww.io/
19
  License: GPLv3
20
  */
59
  add_action( 'admin_notices', 'ewww_image_optimizer_notice_wpengine' );
60
  // Loads the plugin translations.
61
  add_action( 'plugins_loaded', 'ewww_image_optimizer_false_init' );
62
+ } elseif ( defined( 'FLYWHEEL_CONFIG_DIR' ) ) {
63
+ add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_flywheel' );
64
+ add_action( 'admin_notices', 'ewww_image_optimizer_notice_flywheel' );
65
+ // Loads the plugin translations.
66
+ add_action( 'plugins_loaded', 'ewww_image_optimizer_false_init' );
67
  } else {
68
  /**
69
  * The full path of the plugin file (this file).
127
  * Display a notice that the PHP version is too old.
128
  */
129
  function ewww_image_optimizer_unsupported_php() {
130
+ echo "<div id='ewww-image-optimizer-warning-php' class='error'><p><strong>" . esc_html__( 'EWWW Image Optimizer requires PHP 5.3 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>';
131
  }
132
 
133
  /**
158
  function ewww_image_optimizer_notice_kinsta() {
159
  echo "<div id='ewww-image-optimizer-warning-kinsta' class='error'><p>" . esc_html__( 'The regular version of the EWWW Image Optimizer plugin is not permitted on Kinsta sites. Please deactivate EWWW Image Optimizer and install EWWW Image Optimizer Cloud to optimize your images.', 'ewww-image-optimizer' ) . '</p></div>';
160
  }
161
+
162
+ /**
163
+ * Inform the user that only ewww-image-optimizer-cloud is permitted on Flywheel.
164
+ */
165
+ function ewww_image_optimizer_notice_flywheel() {
166
+ echo "<div id='ewww-image-optimizer-warning-flywheel' class='error'><p>" . esc_html__( 'The regular version of the EWWW Image Optimizer plugin is not permitted on Flywheel sites. Please deactivate EWWW Image Optimizer and install EWWW Image Optimizer Cloud to optimize your images.', 'ewww-image-optimizer' ) . '</p></div>';
167
+ }
includes/eio.js CHANGED
@@ -1,7 +1,7 @@
1
  jQuery(document).ready(function($) {
2
  var ewww_error_counter = 30;
3
  if (!ewww_vars.scan_fail) {
4
- $('#ewww-webp-rewrite').submit(function() {
5
  var ewww_webp_rewrite_action = 'ewww_webp_rewrite';
6
  var ewww_webp_rewrite_data = {
7
  action: ewww_webp_rewrite_action,
@@ -14,6 +14,19 @@ jQuery(document).ready(function($) {
14
  });
15
  return false;
16
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  $('#ewww-status-expand').click(function() {
18
  $('#ewww-collapsible-status').show();
19
  $('#ewww-status-expand').hide();
@@ -27,9 +40,9 @@ jQuery(document).ready(function($) {
27
  $('#ewww-webp-settings').hide();
28
  $('#ewww-general-settings').show();
29
  $('li.ewww-general-nav').addClass('ewww-selected');
30
- if($('#ewww_image_optimizer_cloud_key').length){
31
  $('#ewww-resize-settings').hide();
32
- console.log($('#ewww-general-settings').length);
33
  }
34
  $('#ewww-optimization-settings').hide();
35
  $('#ewww-conversion-settings').hide();
@@ -362,10 +375,12 @@ jQuery(document).ready(function($) {
362
  });
363
  }
364
  function ewwwUpdateQuota() {
365
- ewww_quota_update_data.ewww_wpnonce = ewww_vars._wpnonce;
366
- $.post(ajaxurl, ewww_quota_update_data, function(response) {
367
- $('#ewww-bulk-credits-available').html(response);
368
- });
 
 
369
  }
370
  function ewwwStartOpt () {
371
  ewww_k = 0;
@@ -447,6 +462,7 @@ jQuery(document).ready(function($) {
447
  $('#ewww-bulk-loading').html('<p style="color: red"><b>' + ewww_response.error + '</b></p>');
448
  clearInterval(ewww_quota_update);
449
  clearInterval(ewww_countdown);
 
450
  }
451
  else if (ewww_k == 9) {
452
  if ( ewww_response.results ) {
1
  jQuery(document).ready(function($) {
2
  var ewww_error_counter = 30;
3
  if (!ewww_vars.scan_fail) {
4
+ $('#ewww-webp-rewrite #ewww-webp-insert').click(function() {
5
  var ewww_webp_rewrite_action = 'ewww_webp_rewrite';
6
  var ewww_webp_rewrite_data = {
7
  action: ewww_webp_rewrite_action,
14
  });
15
  return false;
16
  });
17
+ $('#ewww-webp-rewrite #ewww-webp-remove').click(function() {
18
+ var ewww_webp_rewrite_action = 'ewww_webp_unwrite';
19
+ var ewww_webp_rewrite_data = {
20
+ action: ewww_webp_rewrite_action,
21
+ ewww_wpnonce: ewww_vars._wpnonce,
22
+ };
23
+ $.post(ajaxurl, ewww_webp_rewrite_data, function(response) {
24
+ $('#ewww-webp-rewrite-status').html('<b>' + response + '</b>');
25
+ ewww_webp_image = document.getElementById("webp-image").src;
26
+ document.getElementById("webp-image").src = ewww_webp_image + '#' + new Date().getTime();
27
+ });
28
+ return false;
29
+ });
30
  $('#ewww-status-expand').click(function() {
31
  $('#ewww-collapsible-status').show();
32
  $('#ewww-status-expand').hide();
40
  $('#ewww-webp-settings').hide();
41
  $('#ewww-general-settings').show();
42
  $('li.ewww-general-nav').addClass('ewww-selected');
43
+ if($('#ewww_image_optimizer_debug').length){
44
  $('#ewww-resize-settings').hide();
45
+ console.log($('#ewww_image_optimizer_debug').length);
46
  }
47
  $('#ewww-optimization-settings').hide();
48
  $('#ewww-conversion-settings').hide();
375
  });
376
  }
377
  function ewwwUpdateQuota() {
378
+ if ($('#ewww-bulk-credits-available').length > 0) {
379
+ ewww_quota_update_data.ewww_wpnonce = ewww_vars._wpnonce;
380
+ $.post(ajaxurl, ewww_quota_update_data, function(response) {
381
+ $('#ewww-bulk-credits-available').html(response);
382
+ });
383
+ }
384
  }
385
  function ewwwStartOpt () {
386
  ewww_k = 0;
462
  $('#ewww-bulk-loading').html('<p style="color: red"><b>' + ewww_response.error + '</b></p>');
463
  clearInterval(ewww_quota_update);
464
  clearInterval(ewww_countdown);
465
+ ewwwUpdateQuota();
466
  }
467
  else if (ewww_k == 9) {
468
  if ( ewww_response.results ) {
includes/exactdn.js ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* jshint onevar: false */
2
+
3
+ (function($){
4
+ /**
5
+ * For images lacking explicit dimensions and needing them, try to add them.
6
+ */
7
+ var restore_dims = function() {
8
+ $( 'img[data-recalc-dims]' ).each( function recalc() {
9
+ var $this = $( this );
10
+ if ( this.complete ) {
11
+
12
+ // Support for lazy loading: if there is a lazy-src
13
+ // attribute and it's value is not the same as the current src we
14
+ // should wait until the image load event
15
+ if ( $this.data( 'lazy-src' ) && $this.attr( 'src' ) !== $this.data( 'lazy-src' ) ) {
16
+ $this.load( recalc );
17
+ return;
18
+ }
19
+
20
+ var width = this.width,
21
+ height = this.height;
22
+
23
+ if ( width && width > 0 && height && height > 0 ) {
24
+ $this.attr( {
25
+ width: width,
26
+ height: height
27
+ } );
28
+
29
+ reset_for_retina( this );
30
+ }
31
+ }
32
+ else {
33
+ $this.load( recalc );
34
+ }
35
+ } );
36
+ },
37
+
38
+ /**
39
+ * Modify image's markup so that it won't be reprocessed by this script.
40
+ */
41
+ reset_for_retina = function( img ) {
42
+ $( img ).removeAttr( 'data-recalc-dims' ).removeAttr( 'scale' );
43
+ };
44
+
45
+ /**
46
+ * Check both when page loads, and when post-load is triggered.
47
+ */
48
+ $( document ).ready( restore_dims );
49
+
50
+ if ( 'on' in $.fn ) {
51
+ $( document.body ).on( 'post-load', restore_dims );
52
+ } else {
53
+ $( document ).delegate( 'body', 'post-load', restore_dims );
54
+ }
55
+ })(jQuery);
includes/load_webp.js CHANGED
@@ -475,7 +475,7 @@ function ewww_load_images(ewww_webp_supported) {
475
  (function($) {
476
  var attr_prefix = 'data-';
477
  function ewww_copy_attrs(ewww_nscript, ewww_img) {
478
- var attrs = ['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-attachment-id','data-permalink','data-orig-size','data-comments-opened','data-image-meta','data-image-title','data-image-description'];
479
  for (var i = 0, len = attrs.length; i < len; i++) {
480
  var ewww_attr = $(ewww_nscript).attr(attr_prefix + attrs[i]);
481
  if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
@@ -521,6 +521,12 @@ function ewww_load_images(ewww_webp_supported) {
521
  $(this).attr('data-lazyload', ewww_attr);
522
  }
523
  });
 
 
 
 
 
 
524
  }
525
  $('img.ewww_webp_lazy_retina').each(function() {
526
  if (ewww_webp_supported) {
@@ -564,11 +570,11 @@ function ewww_load_images(ewww_webp_supported) {
564
  $(this).attr('data-lazy-src', $(this).attr('data-lazy-img-src'));
565
  var ewww_attr = $(this).attr('data-srcset');
566
  if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
567
- $(this).attr('srcset', ewww_attr);
568
  }
569
  var ewww_attr = $(this).attr('data-lazy-srcset-img');
570
  if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
571
- $(ewww_img).attr('data-lazy-srcset', ewww_attr);
572
  }
573
  }
574
  $(this).removeClass('ewww_webp_lazy_load');
@@ -604,14 +610,47 @@ function ewww_load_images(ewww_webp_supported) {
604
  var ewww_attr = $(this).attr('data-webp-orig-file');
605
  if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
606
  $(ewww_img).attr('data-orig-file', ewww_attr);
607
- }
 
 
 
 
 
608
  var ewww_attr = $(this).attr('data-webp-medium-file');
609
  if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
610
  $(ewww_img).attr('data-medium-file', ewww_attr);
 
 
 
 
 
611
  }
612
  var ewww_attr = $(this).attr('data-webp-large-file');
613
  if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
614
  $(ewww_img).attr('data-large-file', ewww_attr);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
615
  }
616
  } else {
617
  $(ewww_img).attr('src', $(this).attr('data-img'));
@@ -619,6 +658,26 @@ function ewww_load_images(ewww_webp_supported) {
619
  if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
620
  $(ewww_img).attr('srcset', ewww_attr);
621
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
622
  }
623
  ewww_img = ewww_copy_attrs(this, ewww_img);
624
  $(this).after(ewww_img);
475
  (function($) {
476
  var attr_prefix = 'data-';
477
  function ewww_copy_attrs(ewww_nscript, ewww_img) {
478
+ var attrs = ['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'];
479
  for (var i = 0, len = attrs.length; i < len; i++) {
480
  var ewww_attr = $(ewww_nscript).attr(attr_prefix + attrs[i]);
481
  if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
521
  $(this).attr('data-lazyload', ewww_attr);
522
  }
523
  });
524
+ $('div.woocommerce-product-gallery__image').each(function() {
525
+ var ewww_attr = $(this).attr('data-webp-thumb');
526
+ if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
527
+ $(this).attr('data-thumb', ewww_attr);
528
+ }
529
+ });
530
  }
531
  $('img.ewww_webp_lazy_retina').each(function() {
532
  if (ewww_webp_supported) {
570
  $(this).attr('data-lazy-src', $(this).attr('data-lazy-img-src'));
571
  var ewww_attr = $(this).attr('data-srcset');
572
  if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
573
+ $(this).attr('srcset', ewww_attr);
574
  }
575
  var ewww_attr = $(this).attr('data-lazy-srcset-img');
576
  if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
577
+ $(ewww_img).attr('data-lazy-srcset', ewww_attr);
578
  }
579
  }
580
  $(this).removeClass('ewww_webp_lazy_load');
610
  var ewww_attr = $(this).attr('data-webp-orig-file');
611
  if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
612
  $(ewww_img).attr('data-orig-file', ewww_attr);
613
+ } else {
614
+ var ewww_attr = $(this).attr('data-orig-file');
615
+ if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
616
+ $(ewww_img).attr('data-orig-file', ewww_attr);
617
+ }
618
+ }
619
  var ewww_attr = $(this).attr('data-webp-medium-file');
620
  if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
621
  $(ewww_img).attr('data-medium-file', ewww_attr);
622
+ } else {
623
+ var ewww_attr = $(this).attr('data-medium-file');
624
+ if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
625
+ $(ewww_img).attr('data-medium-file', ewww_attr);
626
+ }
627
  }
628
  var ewww_attr = $(this).attr('data-webp-large-file');
629
  if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
630
  $(ewww_img).attr('data-large-file', ewww_attr);
631
+ } else {
632
+ var ewww_attr = $(this).attr('data-large-file');
633
+ if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
634
+ $(ewww_img).attr('data-large-file', ewww_attr);
635
+ }
636
+ }
637
+ var ewww_attr = $(this).attr('data-webp-large_image');
638
+ if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
639
+ $(ewww_img).attr('data-large_image', ewww_attr);
640
+ } else {
641
+ var ewww_attr = $(this).attr('data-large_image');
642
+ if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
643
+ $(ewww_img).attr('data-large_image', ewww_attr);
644
+ }
645
+ }
646
+ var ewww_attr = $(this).attr('data-webp-src');
647
+ if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
648
+ $(ewww_img).attr('data-src', ewww_attr);
649
+ } else {
650
+ var ewww_attr = $(this).attr('data-src');
651
+ if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
652
+ $(ewww_img).attr('data-src', ewww_attr);
653
+ }
654
  }
655
  } else {
656
  $(ewww_img).attr('src', $(this).attr('data-img'));
658
  if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
659
  $(ewww_img).attr('srcset', ewww_attr);
660
  }
661
+ var ewww_attr = $(this).attr('data-orig-file');
662
+ if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
663
+ $(ewww_img).attr('data-orig-file', ewww_attr);
664
+ }
665
+ var ewww_attr = $(this).attr('data-medium-file');
666
+ if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
667
+ $(ewww_img).attr('data-medium-file', ewww_attr);
668
+ }
669
+ var ewww_attr = $(this).attr('data-large-file');
670
+ if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
671
+ $(ewww_img).attr('data-large-file', ewww_attr);
672
+ }
673
+ var ewww_attr = $(this).attr('data-large_image');
674
+ if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
675
+ $(ewww_img).attr('data-large_image', ewww_attr);
676
+ }
677
+ var ewww_attr = $(this).attr('data-src');
678
+ if (typeof ewww_attr !== typeof undefined && ewww_attr !== false) {
679
+ $(ewww_img).attr('data-src', ewww_attr);
680
+ }
681
  }
682
  ewww_img = ewww_copy_attrs(this, ewww_img);
683
  $(this).after(ewww_img);
includes/load_webp.min.js CHANGED
@@ -1 +1 @@
1
- function check_webp_feature(a,b){var c={alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"},d=!1,e=new Image;e.onload=function(){var a=e.width>0&&e.height>0;d=!0,b(a)},e.onerror=function(){d=!1,b(!1)},e.src="data:image/webp;base64,"+c[a]}function ewww_load_images(a){jQuery(document).arrive(".ewww_webp",function(){ewww_load_images(a)}),function(b){function d(a,d){for(var e=["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-attachment-id","data-permalink","data-orig-size","data-comments-opened","data-image-meta","data-image-title","data-image-description"],f=0,g=e.length;f<g;f++){var h=b(a).attr(c+e[f]);void 0!==h&&!1!==h&&b(d).attr(e[f],h)}return d}var c="data-";a&&(b(".batch-image img, .image-wrapper a, .ngg-pro-masonry-item a").each(function(){var a=b(this).attr("data-webp");void 0!==a&&!1!==a&&b(this).attr("data-src",a);var a=b(this).attr("data-webp-thumbnail");void 0!==a&&!1!==a&&b(this).attr("data-thumbnail",a)}),b(".image-wrapper a, .ngg-pro-masonry-item a").each(function(){var a=b(this).attr("data-webp");void 0!==a&&!1!==a&&b(this).attr("href",a)}),b(".rev_slider ul li").each(function(){var a=b(this).attr("data-webp-thumb");void 0!==a&&!1!==a&&b(this).attr("data-thumb",a);for(var c=1;c<11;){var a=b(this).attr("data-webp-param"+c);void 0!==a&&!1!==a&&b(this).attr("data-param"+c,a),c++}}),b(".rev_slider img").each(function(){var a=b(this).attr("data-webp-lazyload");void 0!==a&&!1!==a&&b(this).attr("data-lazyload",a)})),b("img.ewww_webp_lazy_retina").each(function(){if(a){var c=b(this).attr("data-srcset-webp");void 0!==c&&!1!==c&&b(this).attr("data-srcset",c)}else{var c=b(this).attr("data-srcset-img");void 0!==c&&!1!==c&&b(this).attr("data-srcset",c)}b(this).removeClass("ewww_webp_lazy_retina")}),b("video").each(function(){if(a){var c=b(this).attr("data-poster-webp");void 0!==c&&!1!==c&&b(this).attr("poster",c)}else{var c=b(this).attr("data-poster-image");void 0!==c&&!1!==c&&b(this).attr("poster",c)}}),b("img.ewww_webp_lazy_load").each(function(){if(a){b(this).attr("data-lazy-src",b(this).attr("data-lazy-webp-src"));var c=b(this).attr("data-srcset-webp");void 0!==c&&!1!==c&&b(this).attr("srcset",c);var c=b(this).attr("data-lazy-srcset-webp");void 0!==c&&!1!==c&&b(this).attr("data-lazy-srcset",c)}else{b(this).attr("data-lazy-src",b(this).attr("data-lazy-img-src"));var c=b(this).attr("data-srcset");void 0!==c&&!1!==c&&b(this).attr("srcset",c);var c=b(this).attr("data-lazy-srcset-img");void 0!==c&&!1!==c&&b(ewww_img).attr("data-lazy-srcset",c)}b(this).removeClass("ewww_webp_lazy_load")}),b(".ewww_webp_lazy_hueman").each(function(){var c=document.createElement("img");if(b(c).attr("src",b(this).attr("data-src")),a){b(c).attr("data-src",b(this).attr("data-webp-src"));var e=b(this).attr("data-srcset-webp");void 0!==e&&!1!==e&&b(c).attr("data-srcset",e)}else{b(c).attr("data-src",b(this).attr("data-img"));var e=b(this).attr("data-srcset-img");void 0!==e&&!1!==e&&b(c).attr("data-srcset",e)}c=d(this,c),b(this).after(c),b(this).removeClass("ewww_webp_lazy_hueman")}),b(".ewww_webp").each(function(){var c=document.createElement("img");if(a){b(c).attr("src",b(this).attr("data-webp"));var e=b(this).attr("data-srcset-webp");void 0!==e&&!1!==e&&b(c).attr("srcset",e);var e=b(this).attr("data-webp-orig-file");void 0!==e&&!1!==e&&b(c).attr("data-orig-file",e);var e=b(this).attr("data-webp-medium-file");void 0!==e&&!1!==e&&b(c).attr("data-medium-file",e);var e=b(this).attr("data-webp-large-file");void 0!==e&&!1!==e&&b(c).attr("data-large-file",e)}else{b(c).attr("src",b(this).attr("data-img"));var e=b(this).attr("data-srcset-img");void 0!==e&&!1!==e&&b(c).attr("srcset",e)}c=d(this,c),b(this).after(c),b(this).removeClass("ewww_webp")})}(jQuery),jQuery.fn.isotope&&jQuery.fn.imagesLoaded&&(jQuery(".fusion-posts-container-infinite").imagesLoaded(function(){jQuery(".fusion-posts-container-infinite").hasClass("isotope")&&jQuery(".fusion-posts-container-infinite").isotope()}),jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").imagesLoaded(function(){jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").isotope()}))}var Arrive=function(a,b,c){"use strict";function l(a,b,c){e.addMethod(b,c,a.unbindEvent),e.addMethod(b,c,a.unbindEventWithSelectorOrCallback),e.addMethod(b,c,a.unbindEventWithSelectorAndCallback)}function m(a){a.arrive=j.bindEvent,l(j,a,"unbindArrive"),a.leave=k.bindEvent,l(k,a,"unbindLeave")}if(a.MutationObserver&&"undefined"!=typeof HTMLElement){var d=0,e=function(){var b=HTMLElement.prototype.matches||HTMLElement.prototype.webkitMatchesSelector||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelector;return{matchesSelector:function(a,c){return a instanceof HTMLElement&&b.call(a,c)},addMethod:function(a,b,c){var d=a[b];a[b]=function(){return c.length==arguments.length?c.apply(this,arguments):"function"==typeof d?d.apply(this,arguments):void 0}},callCallbacks:function(a){for(var c,b=0;c=a[b];b++)c.callback.call(c.elem)},checkChildNodesRecursively:function(a,b,c,d){for(var g,f=0;g=a[f];f++)c(g,b,d)&&d.push({callback:b.callback,elem:g}),g.childNodes.length>0&&e.checkChildNodesRecursively(g.childNodes,b,c,d)},mergeArrays:function(a,b){var d,c={};for(d in a)c[d]=a[d];for(d in b)c[d]=b[d];return c},toElementsArray:function(b){return void 0===b||"number"==typeof b.length&&b!==a||(b=[b]),b}}}(),f=function(){var a=function(){this._eventsBucket=[],this._beforeAdding=null,this._beforeRemoving=null};return a.prototype.addEvent=function(a,b,c,d){var e={target:a,selector:b,options:c,callback:d,firedElems:[]};return this._beforeAdding&&this._beforeAdding(e),this._eventsBucket.push(e),e},a.prototype.removeEvent=function(a){for(var c,b=this._eventsBucket.length-1;c=this._eventsBucket[b];b--)a(c)&&(this._beforeRemoving&&this._beforeRemoving(c),this._eventsBucket.splice(b,1))},a.prototype.beforeAdding=function(a){this._beforeAdding=a},a.prototype.beforeRemoving=function(a){this._beforeRemoving=a},a}(),g=function(b,d){var g=new f,h=this,i={fireOnAttributesModification:!1};return g.beforeAdding(function(c){var i,e=c.target;c.selector,c.callback;e!==a.document&&e!==a||(e=document.getElementsByTagName("html")[0]),i=new MutationObserver(function(a){d.call(this,a,c)});var j=b(c.options);i.observe(e,j),c.observer=i,c.me=h}),g.beforeRemoving(function(a){a.observer.disconnect()}),this.bindEvent=function(a,b,c){b=e.mergeArrays(i,b);for(var d=e.toElementsArray(this),f=0;f<d.length;f++)g.addEvent(d[f],a,b,c)},this.unbindEvent=function(){var a=e.toElementsArray(this);g.removeEvent(function(b){for(var d=0;d<a.length;d++)if(this===c||b.target===a[d])return!0;return!1})},this.unbindEventWithSelectorOrCallback=function(a){var f,b=e.toElementsArray(this),d=a;f="function"==typeof a?function(a){for(var e=0;e<b.length;e++)if((this===c||a.target===b[e])&&a.callback===d)return!0;return!1}:function(d){for(var e=0;e<b.length;e++)if((this===c||d.target===b[e])&&d.selector===a)return!0;return!1},g.removeEvent(f)},this.unbindEventWithSelectorAndCallback=function(a,b){var d=e.toElementsArray(this);g.removeEvent(function(e){for(var f=0;f<d.length;f++)if((this===c||e.target===d[f])&&e.selector===a&&e.callback===b)return!0;return!1})},this},h=function(){function h(a){var b={attributes:!1,childList:!0,subtree:!0};return a.fireOnAttributesModification&&(b.attributes=!0),b}function i(a,b){a.forEach(function(a){var c=a.addedNodes,d=a.target,f=[];null!==c&&c.length>0?e.checkChildNodesRecursively(c,b,k,f):"attributes"===a.type&&k(d,b,f)&&f.push({callback:b.callback,elem:node}),e.callCallbacks(f)})}function k(a,b,f){if(e.matchesSelector(a,b.selector)&&(a._id===c&&(a._id=d++),-1==b.firedElems.indexOf(a._id))){if(b.options.onceOnly){if(0!==b.firedElems.length)return;b.me.unbindEventWithSelectorAndCallback.call(b.target,b.selector,b.callback)}b.firedElems.push(a._id),f.push({callback:b.callback,elem:a})}}var f={fireOnAttributesModification:!1,onceOnly:!1,existing:!1};j=new g(h,i);var l=j.bindEvent;return j.bindEvent=function(a,b,c){void 0===c?(c=b,b=f):b=e.mergeArrays(f,b);var d=e.toElementsArray(this);if(b.existing){for(var g=[],h=0;h<d.length;h++)for(var i=d[h].querySelectorAll(a),j=0;j<i.length;j++)g.push({callback:c,elem:i[j]});if(b.onceOnly&&g.length)return c.call(g[0].elem);setTimeout(e.callCallbacks,1,g)}l.call(this,a,b,c)},j},i=function(){function d(a){return{childList:!0,subtree:!0}}function f(a,b){a.forEach(function(a){var c=a.removedNodes,f=(a.target,[]);null!==c&&c.length>0&&e.checkChildNodesRecursively(c,b,h,f),e.callCallbacks(f)})}function h(a,b){return e.matchesSelector(a,b.selector)}var c={};k=new g(d,f);var i=k.bindEvent;return k.bindEvent=function(a,b,d){void 0===d?(d=b,b=c):b=e.mergeArrays(c,b),i.call(this,a,b,d)},k},j=new h,k=new i;b&&m(b.fn),m(HTMLElement.prototype),m(NodeList.prototype),m(HTMLCollection.prototype),m(HTMLDocument.prototype),m(Window.prototype);var n={};return l(j,n,"unbindAllArrive"),l(k,n,"unbindAllLeave"),n}}(window,"undefined"==typeof jQuery?null:jQuery,void 0);"undefined"!=typeof jQuery&&check_webp_feature("alpha",ewww_load_images);
1
+ function check_webp_feature(t,e){var a={alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"},i=!1,r=new Image;r.onload=function(){var t=r.width>0&&r.height>0;i=!0,e(t)},r.onerror=function(){i=!1,e(!1)},r.src="data:image/webp;base64,"+a[t]}function ewww_load_images(t){jQuery(document).arrive(".ewww_webp",function(){ewww_load_images(t)}),function(e){function a(t,a){for(var r=["align","alt","border","crossorigin","height","hspace","ismap","longdesc","usemap","vspace","width","accesskey","class","contenteditable","contextmenu","dir","draggable","dropzone","hidden","id","lang","spellcheck","style","tabindex","title","translate","sizes","data-caption","data-attachment-id","data-permalink","data-orig-size","data-comments-opened","data-image-meta","data-image-title","data-image-description","data-event-trigger","data-highlight-color","data-highlight-opacity","data-highlight-border-color","data-highlight-border-width","data-highlight-border-opacity","data-no-lazy","data-lazy","data-large_image_width","data-large_image_height"],n=0,o=r.length;n<o;n++){var s=e(t).attr(i+r[n]);void 0!==s&&!1!==s&&e(a).attr(r[n],s)}return a}var i="data-";t&&(e(".batch-image img, .image-wrapper a, .ngg-pro-masonry-item a").each(function(){var t=e(this).attr("data-webp");void 0!==t&&!1!==t&&e(this).attr("data-src",t),void 0!==(t=e(this).attr("data-webp-thumbnail"))&&!1!==t&&e(this).attr("data-thumbnail",t)}),e(".image-wrapper a, .ngg-pro-masonry-item a").each(function(){var t=e(this).attr("data-webp");void 0!==t&&!1!==t&&e(this).attr("href",t)}),e(".rev_slider ul li").each(function(){var t=e(this).attr("data-webp-thumb");void 0!==t&&!1!==t&&e(this).attr("data-thumb",t);for(var a=1;a<11;)void 0!==(t=e(this).attr("data-webp-param"+a))&&!1!==t&&e(this).attr("data-param"+a,t),a++}),e(".rev_slider img").each(function(){var t=e(this).attr("data-webp-lazyload");void 0!==t&&!1!==t&&e(this).attr("data-lazyload",t)}),e("div.woocommerce-product-gallery__image").each(function(){var t=e(this).attr("data-webp-thumb");void 0!==t&&!1!==t&&e(this).attr("data-thumb",t)})),e("img.ewww_webp_lazy_retina").each(function(){if(t)void 0!==(a=e(this).attr("data-srcset-webp"))&&!1!==a&&e(this).attr("data-srcset",a);else{var a=e(this).attr("data-srcset-img");void 0!==a&&!1!==a&&e(this).attr("data-srcset",a)}e(this).removeClass("ewww_webp_lazy_retina")}),e("video").each(function(){if(t)void 0!==(a=e(this).attr("data-poster-webp"))&&!1!==a&&e(this).attr("poster",a);else{var a=e(this).attr("data-poster-image");void 0!==a&&!1!==a&&e(this).attr("poster",a)}}),e("img.ewww_webp_lazy_load").each(function(){if(t)e(this).attr("data-lazy-src",e(this).attr("data-lazy-webp-src")),void 0!==(a=e(this).attr("data-srcset-webp"))&&!1!==a&&e(this).attr("srcset",a),void 0!==(a=e(this).attr("data-lazy-srcset-webp"))&&!1!==a&&e(this).attr("data-lazy-srcset",a);else{e(this).attr("data-lazy-src",e(this).attr("data-lazy-img-src"));var a=e(this).attr("data-srcset");void 0!==a&&!1!==a&&e(this).attr("srcset",a),void 0!==(a=e(this).attr("data-lazy-srcset-img"))&&!1!==a&&e(ewww_img).attr("data-lazy-srcset",a)}e(this).removeClass("ewww_webp_lazy_load")}),e(".ewww_webp_lazy_hueman").each(function(){var i=document.createElement("img");if(e(i).attr("src",e(this).attr("data-src")),t)e(i).attr("data-src",e(this).attr("data-webp-src")),void 0!==(r=e(this).attr("data-srcset-webp"))&&!1!==r&&e(i).attr("data-srcset",r);else{e(i).attr("data-src",e(this).attr("data-img"));var r=e(this).attr("data-srcset-img");void 0!==r&&!1!==r&&e(i).attr("data-srcset",r)}i=a(this,i),e(this).after(i),e(this).removeClass("ewww_webp_lazy_hueman")}),e(".ewww_webp").each(function(){var i=document.createElement("img");if(t)e(i).attr("src",e(this).attr("data-webp")),void 0!==(r=e(this).attr("data-srcset-webp"))&&!1!==r&&e(i).attr("srcset",r),void 0!==(r=e(this).attr("data-webp-orig-file"))&&!1!==r?e(i).attr("data-orig-file",r):void 0!==(r=e(this).attr("data-orig-file"))&&!1!==r&&e(i).attr("data-orig-file",r),void 0!==(r=e(this).attr("data-webp-medium-file"))&&!1!==r?e(i).attr("data-medium-file",r):void 0!==(r=e(this).attr("data-medium-file"))&&!1!==r&&e(i).attr("data-medium-file",r),void 0!==(r=e(this).attr("data-webp-large-file"))&&!1!==r?e(i).attr("data-large-file",r):void 0!==(r=e(this).attr("data-large-file"))&&!1!==r&&e(i).attr("data-large-file",r),void 0!==(r=e(this).attr("data-webp-large_image"))&&!1!==r?e(i).attr("data-large_image",r):void 0!==(r=e(this).attr("data-large_image"))&&!1!==r&&e(i).attr("data-large_image",r),void 0!==(r=e(this).attr("data-webp-src"))&&!1!==r?e(i).attr("data-src",r):void 0!==(r=e(this).attr("data-src"))&&!1!==r&&e(i).attr("data-src",r);else{e(i).attr("src",e(this).attr("data-img"));var r=e(this).attr("data-srcset-img");void 0!==r&&!1!==r&&e(i).attr("srcset",r),void 0!==(r=e(this).attr("data-orig-file"))&&!1!==r&&e(i).attr("data-orig-file",r),void 0!==(r=e(this).attr("data-medium-file"))&&!1!==r&&e(i).attr("data-medium-file",r),void 0!==(r=e(this).attr("data-large-file"))&&!1!==r&&e(i).attr("data-large-file",r),void 0!==(r=e(this).attr("data-large_image"))&&!1!==r&&e(i).attr("data-large_image",r),void 0!==(r=e(this).attr("data-src"))&&!1!==r&&e(i).attr("data-src",r)}i=a(this,i),e(this).after(i),e(this).removeClass("ewww_webp")})}(jQuery),jQuery.fn.isotope&&jQuery.fn.imagesLoaded&&(jQuery(".fusion-posts-container-infinite").imagesLoaded(function(){jQuery(".fusion-posts-container-infinite").hasClass("isotope")&&jQuery(".fusion-posts-container-infinite").isotope()}),jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").imagesLoaded(function(){jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").isotope()}))}var Arrive=function(t,e,a){"use strict";function i(t,e,a){o.addMethod(e,a,t.unbindEvent),o.addMethod(e,a,t.unbindEventWithSelectorOrCallback),o.addMethod(e,a,t.unbindEventWithSelectorAndCallback)}function r(t){t.arrive=l.bindEvent,i(l,t,"unbindArrive"),t.leave=c.bindEvent,i(c,t,"unbindLeave")}if(t.MutationObserver&&"undefined"!=typeof HTMLElement){var n=0,o=function(){var e=HTMLElement.prototype.matches||HTMLElement.prototype.webkitMatchesSelector||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelector;return{matchesSelector:function(t,a){return t instanceof HTMLElement&&e.call(t,a)},addMethod:function(t,e,a){var i=t[e];t[e]=function(){return a.length==arguments.length?a.apply(this,arguments):"function"==typeof i?i.apply(this,arguments):void 0}},callCallbacks:function(t){for(var e,a=0;e=t[a];a++)e.callback.call(e.elem)},checkChildNodesRecursively:function(t,e,a,i){for(var r,n=0;r=t[n];n++)a(r,e,i)&&i.push({callback:e.callback,elem:r}),r.childNodes.length>0&&o.checkChildNodesRecursively(r.childNodes,e,a,i)},mergeArrays:function(t,e){var a,i={};for(a in t)i[a]=t[a];for(a in e)i[a]=e[a];return i},toElementsArray:function(e){return void 0===e||"number"==typeof e.length&&e!==t||(e=[e]),e}}}(),s=function(){var t=function(){this._eventsBucket=[],this._beforeAdding=null,this._beforeRemoving=null};return t.prototype.addEvent=function(t,e,a,i){var r={target:t,selector:e,options:a,callback:i,firedElems:[]};return this._beforeAdding&&this._beforeAdding(r),this._eventsBucket.push(r),r},t.prototype.removeEvent=function(t){for(var e,a=this._eventsBucket.length-1;e=this._eventsBucket[a];a--)t(e)&&(this._beforeRemoving&&this._beforeRemoving(e),this._eventsBucket.splice(a,1))},t.prototype.beforeAdding=function(t){this._beforeAdding=t},t.prototype.beforeRemoving=function(t){this._beforeRemoving=t},t}(),d=function(e,i){var r=new s,n=this,d={fireOnAttributesModification:!1};return r.beforeAdding(function(a){var r,o=a.target;a.selector,a.callback;o!==t.document&&o!==t||(o=document.getElementsByTagName("html")[0]),r=new MutationObserver(function(t){i.call(this,t,a)});var s=e(a.options);r.observe(o,s),a.observer=r,a.me=n}),r.beforeRemoving(function(t){t.observer.disconnect()}),this.bindEvent=function(t,e,a){e=o.mergeArrays(d,e);for(var i=o.toElementsArray(this),n=0;n<i.length;n++)r.addEvent(i[n],t,e,a)},this.unbindEvent=function(){var t=o.toElementsArray(this);r.removeEvent(function(e){for(var i=0;i<t.length;i++)if(this===a||e.target===t[i])return!0;return!1})},this.unbindEventWithSelectorOrCallback=function(t){var e,i=o.toElementsArray(this),n=t;e="function"==typeof t?function(t){for(var e=0;e<i.length;e++)if((this===a||t.target===i[e])&&t.callback===n)return!0;return!1}:function(e){for(var r=0;r<i.length;r++)if((this===a||e.target===i[r])&&e.selector===t)return!0;return!1},r.removeEvent(e)},this.unbindEventWithSelectorAndCallback=function(t,e){var i=o.toElementsArray(this);r.removeEvent(function(r){for(var n=0;n<i.length;n++)if((this===a||r.target===i[n])&&r.selector===t&&r.callback===e)return!0;return!1})},this},l=new function(){function t(t,e,i){if(o.matchesSelector(t,e.selector)&&(t._id===a&&(t._id=n++),-1==e.firedElems.indexOf(t._id))){if(e.options.onceOnly){if(0!==e.firedElems.length)return;e.me.unbindEventWithSelectorAndCallback.call(e.target,e.selector,e.callback)}e.firedElems.push(t._id),i.push({callback:e.callback,elem:t})}}var e={fireOnAttributesModification:!1,onceOnly:!1,existing:!1},i=(l=new d(function(t){var e={attributes:!1,childList:!0,subtree:!0};return t.fireOnAttributesModification&&(e.attributes=!0),e},function(e,a){e.forEach(function(e){var i=e.addedNodes,r=e.target,n=[];null!==i&&i.length>0?o.checkChildNodesRecursively(i,a,t,n):"attributes"===e.type&&t(r,a,n)&&n.push({callback:a.callback,elem:node}),o.callCallbacks(n)})})).bindEvent;return l.bindEvent=function(t,a,r){void 0===r?(r=a,a=e):a=o.mergeArrays(e,a);var n=o.toElementsArray(this);if(a.existing){for(var s=[],d=0;d<n.length;d++)for(var l=n[d].querySelectorAll(t),c=0;c<l.length;c++)s.push({callback:r,elem:l[c]});if(a.onceOnly&&s.length)return r.call(s[0].elem);setTimeout(o.callCallbacks,1,s)}i.call(this,t,a,r)},l},c=new function(){function t(t,e){return o.matchesSelector(t,e.selector)}var e={},a=(c=new d(function(t){return{childList:!0,subtree:!0}},function(e,a){e.forEach(function(e){var i=e.removedNodes,r=(e.target,[]);null!==i&&i.length>0&&o.checkChildNodesRecursively(i,a,t,r),o.callCallbacks(r)})})).bindEvent;return c.bindEvent=function(t,i,r){void 0===r?(r=i,i=e):i=o.mergeArrays(e,i),a.call(this,t,i,r)},c};e&&r(e.fn),r(HTMLElement.prototype),r(NodeList.prototype),r(HTMLCollection.prototype),r(HTMLDocument.prototype),r(Window.prototype);var h={};return i(l,h,"unbindAllArrive"),i(c,h,"unbindAllLeave"),h}}(window,"undefined"==typeof jQuery?null:jQuery,void 0);"undefined"!=typeof jQuery&&check_webp_feature("alpha",ewww_load_images);
includes/resize_detection.js CHANGED
@@ -18,12 +18,12 @@ function checkImageSizes() {
18
  if ((img.naturalWidth != 1) && (img.naturalHeight != 1)) {
19
  // For each image with a natural width which isn't
20
  // a 1x1 image, check its size.
21
- var wrongWidth = (img.width != img.naturalWidth);
22
- var wrongHeight = (img.height != img.naturalHeight);
23
  if (wrongWidth || wrongHeight) {
24
- img.style.border = "3px red dotted";
25
  img.style.margin = "-3px";
26
- img.style.background = "yellow";
27
  img.title = "Forced to wrong size: " +
28
  img.width + "x" + img.height + ", natural is " +
29
  img.naturalWidth + "x" + img.naturalHeight + "!";
18
  if ((img.naturalWidth != 1) && (img.naturalHeight != 1)) {
19
  // For each image with a natural width which isn't
20
  // a 1x1 image, check its size.
21
+ var wrongWidth = (img.width * 1.5 < img.naturalWidth);
22
+ var wrongHeight = (img.height * 1.5 < img.naturalHeight);
23
  if (wrongWidth || wrongHeight) {
24
+ img.style.border = "3px #3eadc9 dotted";
25
  img.style.margin = "-3px";
26
+ img.style.background = "black";
27
  img.title = "Forced to wrong size: " +
28
  img.width + "x" + img.height + ", natural is " +
29
  img.naturalWidth + "x" + img.naturalHeight + "!";
mwebp.php CHANGED
@@ -18,7 +18,7 @@ function ewww_image_optimizer_webp_migrate_preview() {
18
  <h1><?php esc_html_e( 'Migrate WebP Images', 'ewww-image-optimizer' ); ?></h1>
19
  <?php
20
  esc_html_e( 'The migration is split into two parts. First, the plugin needs to scan all folders for webp images. Once it has obtained the list of images to rename, it will proceed with the renaming' );
21
- $button_text = esc_attr__( 'Start Migration', 'ewww-image-optimizer' );
22
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
23
  // Create the html for the migration form and status divs.
24
  ?>
@@ -42,10 +42,10 @@ function ewww_image_optimizer_webp_migrate_preview() {
42
  */
43
  function ewww_image_optimizer_webp_scan() {
44
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
45
- $list = array();
46
- $dir = get_home_path();
47
- $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir ), RecursiveIteratorIterator::CHILD_FIRST );
48
- $start = microtime( true );
49
  $file_counter = 0;
50
  foreach ( $iterator as $path ) {
51
  if ( ewww_image_optimizer_stl_check() ) {
@@ -56,7 +56,7 @@ function ewww_image_optimizer_webp_scan() {
56
  continue;
57
  } else {
58
  $file_counter++;
59
- $path = $path->getPathname();
60
  $newwebpformat = preg_replace( '/\.webp/', '', $path );
61
  if ( file_exists( $newwebpformat ) ) {
62
  continue;
@@ -105,7 +105,8 @@ function ewww_image_optimizer_webp_initialize() {
105
  // Verify that an authorized user has started the migration.
106
  $permissions = apply_filters( 'ewww_image_optimizer_admin_permissions', '' );
107
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-webp' ) || ! current_user_can( $permissions ) ) {
108
- wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
 
109
  }
110
  if ( get_option( 'ewww_image_optimizer_webp_skipped' ) ) {
111
  delete_option( 'ewww_image_optimizer_webp_skipped' );
@@ -114,8 +115,8 @@ function ewww_image_optimizer_webp_initialize() {
114
  // Generate the WP spinner image for display.
115
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
116
  // Let the user know that we are beginning.
117
- echo '<p>' . esc_html__( 'Scanning', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' /></p>";
118
- die();
119
  }
120
 
121
  /**
@@ -125,7 +126,8 @@ function ewww_image_optimizer_webp_loop() {
125
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
126
  $permissions = apply_filters( 'ewww_image_optimizer_admin_permissions', '' );
127
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-webp' ) || ! current_user_can( $permissions ) ) {
128
- wp_die( esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) );
 
129
  }
130
  // Retrieve the time when the migration starts.
131
  $started = microtime( true );
@@ -135,8 +137,8 @@ function ewww_image_optimizer_webp_loop() {
135
  $images = array();
136
  ewwwio_debug_message( 'renaming images now' );
137
  $images_processed = 0;
138
- $images_skipped = '';
139
- $images = get_option( 'ewww_image_optimizer_webp_images' );
140
  if ( $images ) {
141
  /* translators: %d: number of images */
142
  printf( esc_html__( '%d Webp images left to rename.', 'ewww-image-optimizer' ), count( $images ) );
@@ -149,42 +151,42 @@ function ewww_image_optimizer_webp_loop() {
149
  ewwwio_debug_message( 'hit 1000, breaking loop' );
150
  break;
151
  }
152
- $image = array_pop( $images );
153
  $replace_base = '';
154
- $skip = true;
155
- $pngfile = preg_replace( '/webp$/', 'png', $image );
156
- $upngfile = preg_replace( '/webp$/', 'PNG', $image );
157
- $jpgfile = preg_replace( '/webp$/', 'jpg', $image );
158
- $jpegfile = preg_replace( '/webp$/', 'jpeg', $image );
159
- $ujpgfile = preg_replace( '/webp$/', 'JPG', $image );
160
  if ( file_exists( $pngfile ) ) {
161
  $replace_base = $pngfile;
162
- $skip = false;
163
  } if ( file_exists( $upngfile ) ) {
164
  if ( empty( $replace_base ) ) {
165
  $replace_base = $upngfile;
166
- $skip = false;
167
  } else {
168
  $skip = true;
169
  }
170
  } if ( file_exists( $jpgfile ) ) {
171
  if ( empty( $replace_base ) ) {
172
  $replace_base = $jpgfile;
173
- $skip = false;
174
  } else {
175
  $skip = true;
176
  }
177
  } if ( file_exists( $jpegfile ) ) {
178
  if ( empty( $replace_base ) ) {
179
  $replace_base = $jpegfile;
180
- $skip = false;
181
  } else {
182
  $skip = true;
183
  }
184
  } if ( file_exists( $ujpgfile ) ) {
185
  if ( empty( $replace_base ) ) {
186
  $replace_base = $ujpgfile;
187
- $skip = false;
188
  } else {
189
  $skip = true;
190
  }
@@ -219,19 +221,20 @@ function ewww_image_optimizer_webp_loop() {
219
  function ewww_image_optimizer_webp_cleanup() {
220
  $permissions = apply_filters( 'ewww_image_optimizer_admin_permissions', '' );
221
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-webp' ) || ! current_user_can( $permissions ) ) {
222
- wp_die( esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) );
 
223
  }
224
  $skipped = get_option( 'ewww_image_optimizer_webp_skipped' );
225
  // All done, so we can remove the webp options...
226
  delete_option( 'ewww_image_optimizer_webp_images' );
227
  delete_option( 'ewww_image_optimizer_webp_skipped', '' );
 
228
  if ( $skipped ) {
229
  echo '<p><b>' . esc_html__( 'Skipped:', 'ewww-image-optimizer' ) . '</b></p>';
230
  echo "<p>$skipped</p>";
231
  }
232
  // and let the user know we are done.
233
- echo '<p><b>' . esc_html__( 'Finished', 'ewww-image-optimizer' ) . '</b></p>';
234
- die();
235
  }
236
  add_action( 'admin_enqueue_scripts', 'ewww_image_optimizer_webp_script' );
237
  add_action( 'wp_ajax_webp_init', 'ewww_image_optimizer_webp_initialize' );
18
  <h1><?php esc_html_e( 'Migrate WebP Images', 'ewww-image-optimizer' ); ?></h1>
19
  <?php
20
  esc_html_e( 'The migration is split into two parts. First, the plugin needs to scan all folders for webp images. Once it has obtained the list of images to rename, it will proceed with the renaming' );
21
+ $button_text = esc_attr__( 'Start Migration', 'ewww-image-optimizer' );
22
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
23
  // Create the html for the migration form and status divs.
24
  ?>
42
  */
43
  function ewww_image_optimizer_webp_scan() {
44
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
45
+ $list = array();
46
+ $dir = get_home_path();
47
+ $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir ), RecursiveIteratorIterator::CHILD_FIRST );
48
+ $start = microtime( true );
49
  $file_counter = 0;
50
  foreach ( $iterator as $path ) {
51
  if ( ewww_image_optimizer_stl_check() ) {
56
  continue;
57
  } else {
58
  $file_counter++;
59
+ $path = $path->getPathname();
60
  $newwebpformat = preg_replace( '/\.webp/', '', $path );
61
  if ( file_exists( $newwebpformat ) ) {
62
  continue;
105
  // Verify that an authorized user has started the migration.
106
  $permissions = apply_filters( 'ewww_image_optimizer_admin_permissions', '' );
107
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-webp' ) || ! current_user_can( $permissions ) ) {
108
+ ewwwio_ob_clean();
109
+ die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
110
  }
111
  if ( get_option( 'ewww_image_optimizer_webp_skipped' ) ) {
112
  delete_option( 'ewww_image_optimizer_webp_skipped' );
115
  // Generate the WP spinner image for display.
116
  $loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
117
  // Let the user know that we are beginning.
118
+ ewwwio_ob_clean();
119
+ die( '<p>' . esc_html__( 'Scanning', 'ewww-image-optimizer' ) . "&nbsp;<img src='$loading_image' /></p>" );
120
  }
121
 
122
  /**
126
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
127
  $permissions = apply_filters( 'ewww_image_optimizer_admin_permissions', '' );
128
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-webp' ) || ! current_user_can( $permissions ) ) {
129
+ ewwwio_ob_clean();
130
+ die( esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) );
131
  }
132
  // Retrieve the time when the migration starts.
133
  $started = microtime( true );
137
  $images = array();
138
  ewwwio_debug_message( 'renaming images now' );
139
  $images_processed = 0;
140
+ $images_skipped = '';
141
+ $images = get_option( 'ewww_image_optimizer_webp_images' );
142
  if ( $images ) {
143
  /* translators: %d: number of images */
144
  printf( esc_html__( '%d Webp images left to rename.', 'ewww-image-optimizer' ), count( $images ) );
151
  ewwwio_debug_message( 'hit 1000, breaking loop' );
152
  break;
153
  }
154
+ $image = array_pop( $images );
155
  $replace_base = '';
156
+ $skip = true;
157
+ $pngfile = preg_replace( '/webp$/', 'png', $image );
158
+ $upngfile = preg_replace( '/webp$/', 'PNG', $image );
159
+ $jpgfile = preg_replace( '/webp$/', 'jpg', $image );
160
+ $jpegfile = preg_replace( '/webp$/', 'jpeg', $image );
161
+ $ujpgfile = preg_replace( '/webp$/', 'JPG', $image );
162
  if ( file_exists( $pngfile ) ) {
163
  $replace_base = $pngfile;
164
+ $skip = false;
165
  } if ( file_exists( $upngfile ) ) {
166
  if ( empty( $replace_base ) ) {
167
  $replace_base = $upngfile;
168
+ $skip = false;
169
  } else {
170
  $skip = true;
171
  }
172
  } if ( file_exists( $jpgfile ) ) {
173
  if ( empty( $replace_base ) ) {
174
  $replace_base = $jpgfile;
175
+ $skip = false;
176
  } else {
177
  $skip = true;
178
  }
179
  } if ( file_exists( $jpegfile ) ) {
180
  if ( empty( $replace_base ) ) {
181
  $replace_base = $jpegfile;
182
+ $skip = false;
183
  } else {
184
  $skip = true;
185
  }
186
  } if ( file_exists( $ujpgfile ) ) {
187
  if ( empty( $replace_base ) ) {
188
  $replace_base = $ujpgfile;
189
+ $skip = false;
190
  } else {
191
  $skip = true;
192
  }
221
  function ewww_image_optimizer_webp_cleanup() {
222
  $permissions = apply_filters( 'ewww_image_optimizer_admin_permissions', '' );
223
  if ( ! wp_verify_nonce( $_REQUEST['ewww_wpnonce'], 'ewww-image-optimizer-webp' ) || ! current_user_can( $permissions ) ) {
224
+ ewwwio_ob_clean();
225
+ die( esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) );
226
  }
227
  $skipped = get_option( 'ewww_image_optimizer_webp_skipped' );
228
  // All done, so we can remove the webp options...
229
  delete_option( 'ewww_image_optimizer_webp_images' );
230
  delete_option( 'ewww_image_optimizer_webp_skipped', '' );
231
+ ewwwio_ob_clean();
232
  if ( $skipped ) {
233
  echo '<p><b>' . esc_html__( 'Skipped:', 'ewww-image-optimizer' ) . '</b></p>';
234
  echo "<p>$skipped</p>";
235
  }
236
  // and let the user know we are done.
237
+ die( '<p><b>' . esc_html__( 'Finished', 'ewww-image-optimizer' ) . '</b></p>' );
 
238
  }
239
  add_action( 'admin_enqueue_scripts', 'ewww_image_optimizer_webp_script' );
240
  add_action( 'wp_ajax_webp_init', 'ewww_image_optimizer_webp_initialize' );
phpcs.ruleset.xml CHANGED
@@ -2,6 +2,9 @@
2
  <ruleset name="WordPress Coding Standards for Plugins">
3
  <description>Generally-applicable sniffs for WordPress plugins</description>
4
 
 
 
 
5
  <rule ref="WordPress-Core" />
6
  <rule ref="WordPress-Docs" />
7
 
@@ -21,7 +24,4 @@
21
  <property name="customVariablesWhitelist" type="array" value="formatOutput,parentNode,nextSibling,documentElement" />
22
  </properties>
23
  </rule>
24
-
25
- <exclude-pattern>*/vendor/*</exclude-pattern>
26
- <exclude-pattern>*/tests/*</exclude-pattern>
27
  </ruleset>
2
  <ruleset name="WordPress Coding Standards for Plugins">
3
  <description>Generally-applicable sniffs for WordPress plugins</description>
4
 
5
+ <exclude-pattern>*/vendor/*</exclude-pattern>
6
+ <exclude-pattern>*/tests/*</exclude-pattern>
7
+
8
  <rule ref="WordPress-Core" />
9
  <rule ref="WordPress-Docs" />
10
 
24
  <property name="customVariablesWhitelist" type="array" value="formatOutput,parentNode,nextSibling,documentElement" />
25
  </properties>
26
  </rule>
 
 
 
27
  </ruleset>
readme.txt CHANGED
@@ -1,10 +1,11 @@
1
  === EWWW Image Optimizer ===
2
  Contributors: nosilver4u
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MKMQKCBFFG3WW
4
- Tags: image, compress, optimize, optimization, lossless, lossy, photo, picture, seo, jpegmini, tinyjpg, tinypng, webp, wp-cli
5
  Requires at least: 4.6
6
- Tested up to: 4.8.1
7
- Stable tag: 3.6.1
 
8
  License: GPLv3
9
 
10
  Speed up your website and improve your visitors' experience by automatically compressing and resizing images and PDFs. Boost SEO and improve sales.
@@ -31,6 +32,10 @@ Images can be optimized using tools on your own server for free (jpegtran, optip
31
 
32
  If you need a version of this plugin for API use only, see [EWWW Image Optimizer Cloud](https://wordpress.org/plugins/ewww-image-optimizer-cloud/). It is much more compact as it does not contain any binaries or any mention of the exec() function.
33
 
 
 
 
 
34
  = Support =
35
 
36
  If you need assistance using the plugin, please visit our [Support Page](https://ewww.io/contact-us/). The forums are community supported only.
@@ -110,47 +115,7 @@ If these steps do not work, additional documentation is available at http://docs
110
 
111
  = Webhosts =
112
 
113
- In general, these lists only apply to shared hosting services. If the providers below have VPS or dedicated server options, those will likely work just fine. If you have any contributions or corrections to these lists, please contact me via the form at https://ewww.io
114
-
115
- Webhosts where things work (mostly) out of the box:
116
-
117
- * [A2 Hosting](https://www.a2hosting.com/): EWWW IO is installed automatically for A2 Optimized sites.
118
- * [aghosted](https://aghosted.com/)
119
- * [Arvixe](http://www.arvixe.com)
120
- * [Bluehost](https://www.bluehost.com)
121
- * [CiviHosting](https://civihosting.com/)
122
- * [DigitalBerg](https://www.digitalberg.com)
123
- * [Dreamhost](https://www.dreamhost.com)
124
- * [GoDaddy](https://www.godaddy.com) (only with PHP 5.3+)
125
- * [gPowerHost](https://gpowerhost.com/)
126
- * [HostGator](http://www.hostgator.com)
127
- * [Hetzner Online](https://www.hetzner.de)
128
- * [Hosterdam](http://www.hosterdam.com) (FreeBSD)
129
- * [HostMonster](https://www.hostmonster.com)
130
- * [iFastNet](https://ifastnet.com/portal/) (with custom php.ini from customer support)
131
- * [inmotion](http://www.inmotionhosting.com)
132
- * [Liquid Web](https://www.liquidweb.com)
133
- * [Namecheap](https://www.namecheap.com)
134
- * [The Open Host](https://theopenhost.com)
135
- * [OVH](https://www.ovh.co.uk)
136
- * [Site5](https://www.site5.com) (tools must be built manually, or contact Site5 support for assistance)
137
- * [SiteGround](https://www.siteground.com)
138
- * [Spry Servers](https://www.spryservers.net)
139
- * [WebFaction](https://www.webfaction.com)
140
- * [1&1](https://www.1and1.com) (pngout requires manual upload and permissions fix)
141
-
142
- Webhosts where the plugin will only work in cloud mode or only some tools are installed locally:
143
-
144
- * Cloudways
145
- * Flywheel
146
- * Gandi
147
- * Hostwinds
148
- * ipage (JPG only)
149
- * ipower
150
- * Kinsta - use EWWW Image Optimizer Cloud fork: https://wordpress.org/plugins/ewww-image-optimizer-cloud/
151
- * one.com - may not even work in cloud mode
152
- * WP Engine - use EWWW Image Optimizer Cloud fork: https://wordpress.org/plugins/ewww-image-optimizer-cloud/
153
-
154
 
155
  == Frequently Asked Questions ==
156
 
@@ -168,7 +133,7 @@ Yes, but only if the optimized version is smaller. The plugin should NEVER creat
168
 
169
  = Can I resize my images with this plugin? =
170
 
171
- Yes, you can, set it up on the Advanced tab.
172
 
173
  = Can I lower the compression setting for JPGs to save more space? =
174
 
@@ -211,61 +176,79 @@ Pngout, TinyJPG/TinyPNG, JPEGmini, and Pngquant were recommended by EWWW IO user
211
 
212
  == Changelog ==
213
 
214
- * Thank you to everyone who donated for a new Macbook, new binaries are here!
215
  * Feature requests can be submitted via https://ewww.io/contact-us/ and commented on here: https://trello.com/b/Fp81dWof/ewww-image-optimizer
216
  * 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/
217
 
218
- = 3.6.1 =
219
- * fixed: bulk optimizer fails to initialize if the bulk_attachments array is set to an empty string
220
- * fixed: misplaced parenthesis breaks option overrides
221
-
222
- = 3.6.0 =
223
- In an effort to simplify the settings page and make room for new features, many settings have been "hidden" and/or rearranged. It is my hope that this will make it easier for new users to get going with EWWW IO.
224
- You can find more information about overriding options in the [Documentation](http://docs.ewww.io)
225
- * added: ability to override any boolean/integer options by defining constant of the same name
226
- * added: debug information included automatically with help beacon requests when debugging is enabled
227
- * added: use wp_raise_memory_limit (WP 4.6+) to avoid memory issues
228
- * added: use wp_is_ini_value_changeable (WP 4.6+) to avoid errors when raising max_execution_time
229
- * added: notice to use cloud version on Kinsta sites
230
- * changed: Better Lossless and Maximum Lossless have been combined for PNG images with more intelligent usage of advpng on the API
231
- * changed: resize settings moved to new tab
232
- * changed: various options have been removed from the settings page, but are still available via constants, see removals
233
- * changed: bulk optimizer will auto-adjust settings if an image fails to optimize
234
- * changed: bulk scanner will go into fall-back mode if the normal mode is too slow or if the image table takes longer than 5 seconds to load
235
- * changed: images previously compressed by TinyPNG/JPG will be skipped during bulk optimization
236
- * fixed: Optipng not working properly on Windows servers.
237
- * fixed: notice on settings and bulk pages when debug mode is disabled
238
- * removed: ewww_image_optimizer_delay (Bulk Delay), can be selected on the bulk page instead
239
- * removed: ewww_image_optimizer_optipng_level (OptiPNG level) option
240
- * removed: ewww_image_optimizer_pngout_level (PNGOUT level) option
241
- * removed: ewww_image_optimizer_disable_pngout (Disable PNGOUT) option
242
- * removed: ewww_image_optimizer_skip_size (Skip Small Images) option
243
- * removed: ewww_image_optimizer_skip_png_size (Skip Large PNG Images) option
244
- * removed: ewww_image_optimizer_lossy_skip_full (Exclude full-size images from lossy optimization) option
245
- * removed: ewww_image_optimizer_metadata_skip_full (Exclude full-size images from metadata removal) option
246
- * removed: ewww_image_optimizer_skip_bundle (Use System Paths) option
247
-
248
- = 3.5.1 =
249
- * added: optional help beacons on bulk and settings pages
250
- * added: disable deferring of WP Offload S3 uploads with EWWW_IMAGE_OPTIMIZER_NO_DEFER_S3
251
- * added: override use of wp_add_inline_script with non-standard jQuery by defining EWWW_IMAGE_OPTIMIZER_WEBP_INLINE_FALLBACK
252
- * fixed: javascript for bulk optimizers in NextGEN, NextCellent and FlaGallery
253
-
254
- = 3.5.0 =
255
- * added: compatibility with S3 Uploads by Human Made
256
- * added: MediaPress uploads fully optimized on upload
257
- * changed: WebP .htaccess rewrite rule verifier more flexible
258
- * changed: WebP .htaccess rewrite rules allow appending type=original to access non-WebP image
259
- * changed: if an image is too small for resizing, but the dimensions in the metadata are incorrect, it will attempt to update them
260
- * fixed: fatal error if image metadata cannot be read by PEL
261
- * fixed: WebP .htaccess rewrite rules work better on LiteSpeed
262
- * fixed: WP Symposium integration using old options, scanner now includes avatars folder by default
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263
 
264
  = Earlier versions =
265
  Please refer to the separate changelog.txt file.
266
 
267
  == Upgrade Notice ==
268
 
 
 
 
269
  = 3.6.0 =
270
  * API functions have been rewritten to use core WP detection for https capability, please report any errors right away.
271
  * Several options have been removed from the user interface, see the changelog for details.
@@ -276,16 +259,9 @@ Please refer to the separate changelog.txt file.
276
  = 3.3.0 =
277
  * Requires PHP 5.3+. All sites hosted on Pantheon will now use "relative" paths. Existing Pantheon sites will need to update the ewwwio_images table to match (contact support for help), or disable this function by setting EWWW_IMAGE_OPTIMIZER_RELATIVE to false in wp-config.php.
278
 
279
- = 3.2.3 =
280
- * The bulk scanner will now attempt to auto-detect how much memory is available to avoid exceeding memory limits within PHP. Some webhosts do not allow the ini_get() function, so the plugin will fall back to the current memory usage plug 16MB. If you need to set the memory limit for EWWW IO manually, you can do so with the EWWW_MEMORY_LIMIT constant in wp-config.php.
281
-
282
- = 2.9.0 =
283
- * changed: JPG quality setting applies to conversion AND image editing (but not regular optimization), so that you can override the WP default of 82 (it is NOT recommended to increase the quality)
284
- * added: parallel optimization for Media uploads (original and resizes are done concurrently), turn off under Advanced if it affects site performance
285
-
286
  == Contact and Credits ==
287
 
288
- 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.
289
 
290
  = optipng =
291
 
1
  === EWWW Image Optimizer ===
2
  Contributors: nosilver4u
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MKMQKCBFFG3WW
4
+ Tags: image, compress, optimize, optimization, lossless, lossy, seo, jpegmini, tinyjpg, tinypng, webp, wp-cli
5
  Requires at least: 4.6
6
+ Tested up to: 4.9
7
+ Requires PHP: 5.3
8
+ Stable tag: 4.0.6
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.
32
 
33
  If you need a version of this plugin for API use only, see [EWWW Image Optimizer Cloud](https://wordpress.org/plugins/ewww-image-optimizer-cloud/). It is much more compact as it does not contain any binaries or any mention of the exec() function.
34
 
35
+ = Automatic Resizing =
36
+
37
+ With ExactDN support, images will be automatically resized to fit the page and device size. ExactDN also enables basic retina support and automatic lossless compression.
38
+
39
  = Support =
40
 
41
  If you need assistance using the plugin, please visit our [Support Page](https://ewww.io/contact-us/). The forums are community supported only.
115
 
116
  = Webhosts =
117
 
118
+ To find out if your webhost works with the EWWW Image Optimizer, you can check the [official list](http://docs.ewww.io/article/43-supported-web-hosts).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
 
120
  == Frequently Asked Questions ==
121
 
133
 
134
  = Can I resize my images with this plugin? =
135
 
136
+ Yes, you can, set it up on the Resize tab.
137
 
138
  = Can I lower the compression setting for JPGs to save more space? =
139
 
176
 
177
  == Changelog ==
178
 
 
179
  * Feature requests can be submitted via https://ewww.io/contact-us/ and commented on here: https://trello.com/b/Fp81dWof/ewww-image-optimizer
180
  * 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/
181
 
182
+ = 4.0.6 =
183
+ * changed: dummy images have no args appended with exactdn except for ssl flag
184
+ * fixed: resize_detection.js being combined with other scripts by Autoptimize
185
+ * fixed: retina optimization not deferred in async mode
186
+ * fixed: PDF files could trigger license exceeded message
187
+ * fixed: binary detection not fully functional with MacOS and PHP 7.2
188
+ * fixed: compatibility with Regenerate Thumbnails version 3
189
+
190
+ = 4.0.5 =
191
+ * added: enable lossy compression with ExactDN: http://docs.ewww.io/article/47-getting-more-from-exactdn
192
+ * added: CSS/JS minification with ExactDN, see http://docs.ewww.io/article/47-getting-more-from-exactdn
193
+ * added: disable WebP for specific files with ewww_image_optimizer_bypass_webp filter
194
+ * added: ExactDN obeys focus point from Theia Smart Thumbnails plugin
195
+ * added: admin-ajax requests for eddvbugm loader work with ExactDN
196
+ * fixed: multisite settings would not save in certain circumstances
197
+ * fixed: compression levels reset for API users on multisite after toggling single-site override on and off
198
+ * fixed: media library items with non-local images rewritten incorrectly by ExactDN
199
+ * fixed: restoring images throws errors on PHP 7.1
200
+ * fixed: has_cap with invalid argument not recognizing utf8-mb4 v5.2
201
+
202
+ = 4.0.4 =
203
+ * fixed: ExactDN domain validation failing on length check for some domains
204
+ * updated: PEL for better EXIF preservation
205
+
206
+ = 4.0.3 =
207
+ * added: support for additional ExactDN root domains
208
+ * added: button to remove WebP rewrite rules
209
+ * added: informational notice on thumbnail rebuild pages of how the plugins interact
210
+ * changed: WebP rewrite rules removed automatically when ExactDN is enabled, use Alt WebP instead
211
+ * changed: ExactDN now removes metadata if option is enabled
212
+ * fixed: multisite settings set to defaults when single-site resize settings are submitted
213
+
214
+ = 4.0.2 =
215
+ * fixed: WooCommerce images still not working with Alt WebP in all cases
216
+ * fixed: ob_clean() breaks AJAX actions when there is no buffer to clean
217
+ * fixed: notice on NextCellent gallery management pages
218
+ * fixed: missing JS for AJAX actions in NextCellent
219
+
220
+ = 4.0.1 =
221
+ * fixed: ExactDN option not disabled when verification fails too many times
222
+ * fixed: theme scanner sometimes skipped images on PHP 5.3
223
+ * fixed: invalid (float) width parameters for srcset attributes
224
+ * fixed: Jetpack lightbox and carousel were not fully working with Alt WebP
225
+ * fixed: WooCommerce lightbox and gallery not working with Alt WebP
226
+ * fixed: incorrect message about scanning scope when selecting images from media library for bulk optimization
227
+ * security: fixed wildcard LIKE queries to allow proper escaping
228
+
229
+ = 4.0.0 =
230
+ * added: ExactDN with CDN and automatic image resizing
231
+ * added: image resize detection for admin users
232
+ * changed: WP core, theme, and plugin images are excluded from lossy optimization
233
+ * fixed: files fetched from S3 not detected by PHP in some cases
234
+ * fixed: option override conflict preventing webp conversion
235
+ * fixed: Alt WebP breaks Draw Attention image maps
236
+ * fixed: customized WP_Background_Process class conflicts with other plugins using the same class
237
+ * fixed: image deletion could cause deletion of images on source site after cloning database
238
+ * fixed: WebP .htaccess rules using REQUEST_FILENAME instead of REQUEST_URI does not work on some servers
239
+ * fixed: per-site resize settings hidden when API is active network-wide
240
+ * fixed: network-wide settings not saving properly
241
+ * fixed: notice of undefined index with some configurations of the Shield security plugin
242
+ * deprecated: PHP 5.3 support will be removed by March 2018
243
 
244
  = Earlier versions =
245
  Please refer to the separate changelog.txt file.
246
 
247
  == Upgrade Notice ==
248
 
249
+ = 4.0.0 =
250
+ * Introduced new ExactDN with CDN and automatic image resizing.
251
+
252
  = 3.6.0 =
253
  * API functions have been rewritten to use core WP detection for https capability, please report any errors right away.
254
  * Several options have been removed from the user interface, see the changelog for details.
259
  = 3.3.0 =
260
  * Requires PHP 5.3+. All sites hosted on Pantheon will now use "relative" paths. Existing Pantheon sites will need to update the ewwwio_images table to match (contact support for help), or disable this function by setting EWWW_IMAGE_OPTIMIZER_RELATIVE to false in wp-config.php.
261
 
 
 
 
 
 
 
 
262
  == Contact and Credits ==
263
 
264
+ 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.
265
 
266
  = optipng =
267
 
tests/test-optimize.php CHANGED
@@ -239,7 +239,7 @@ class EWWWIO_Optimize_Tests extends WP_UnitTestCase {
239
  $results = $this->optimize_jpg();
240
  update_option( 'ewww_image_optimizer_cloud_key', '' );
241
  update_site_option( 'ewww_image_optimizer_cloud_key', '' );
242
- $this->assertEquals( 698633, filesize( $results[0] ) );
243
  unlink( $results[0] );
244
  }
245
 
239
  $results = $this->optimize_jpg();
240
  update_option( 'ewww_image_optimizer_cloud_key', '' );
241
  update_site_option( 'ewww_image_optimizer_cloud_key', '' );
242
+ $this->assertEquals( 344192, filesize( $results[0] ) );
243
  unlink( $results[0] );
244
  }
245
 
unique.php CHANGED
@@ -127,67 +127,67 @@ function ewww_image_optimizer_install_paths() {
127
  $tool_path = trailingslashit( EWWW_IMAGE_OPTIMIZER_TOOL_PATH );
128
  if ( PHP_OS == 'WINNT' ) {
129
  $gifsicle_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'gifsicle.exe';
130
- $optipng_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'optipng.exe';
131
  $jpegtran_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'jpegtran.exe';
132
  $pngquant_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngquant.exe';
133
- $webp_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'cwebp.exe';
134
  $gifsicle_dst = $tool_path . 'gifsicle.exe';
135
- $optipng_dst = $tool_path . 'optipng.exe';
136
  $jpegtran_dst = $tool_path . 'jpegtran.exe';
137
  $pngquant_dst = $tool_path . 'pngquant.exe';
138
- $webp_dst = $tool_path . 'cwebp.exe';
139
  }
140
  if ( PHP_OS == 'Darwin' ) {
141
  $gifsicle_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'gifsicle-mac';
142
- $optipng_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'optipng-mac';
143
  $jpegtran_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'jpegtran-mac';
144
  $pngquant_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngquant-mac';
145
- $webp_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'cwebp-mac12';
146
  $gifsicle_dst = $tool_path . 'gifsicle';
147
- $optipng_dst = $tool_path . 'optipng';
148
  $jpegtran_dst = $tool_path . 'jpegtran';
149
  $pngquant_dst = $tool_path . 'pngquant';
150
- $webp_dst = $tool_path . 'cwebp';
151
  }
152
  if ( PHP_OS == 'SunOS' ) {
153
  $gifsicle_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'gifsicle-sol';
154
- $optipng_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'optipng-sol';
155
  $jpegtran_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'jpegtran-sol';
156
  $pngquant_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngquant-sol';
157
- $webp_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'cwebp-sol';
158
  $gifsicle_dst = $tool_path . 'gifsicle';
159
- $optipng_dst = $tool_path . 'optipng';
160
  $jpegtran_dst = $tool_path . 'jpegtran';
161
  $pngquant_dst = $tool_path . 'pngquant';
162
- $webp_dst = $tool_path . 'cwebp';
163
  }
164
  if ( PHP_OS == 'FreeBSD' ) {
165
  $arch_type = php_uname( 'm' );
166
  ewwwio_debug_message( "CPU architecture: $arch_type" );
167
  $gifsicle_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'gifsicle-fbsd';
168
- $optipng_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'optipng-fbsd';
169
  $jpegtran_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'jpegtran-fbsd';
170
  $pngquant_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngquant-fbsd';
171
- $webp_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'cwebp-fbsd';
172
  $gifsicle_dst = $tool_path . 'gifsicle';
173
- $optipng_dst = $tool_path . 'optipng';
174
  $jpegtran_dst = $tool_path . 'jpegtran';
175
  $pngquant_dst = $tool_path . 'pngquant';
176
- $webp_dst = $tool_path . 'cwebp';
177
  }
178
  if ( PHP_OS == 'Linux' ) {
179
  $arch_type = php_uname( 'm' );
180
  ewwwio_debug_message( "CPU architecture: $arch_type" );
181
  $gifsicle_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'gifsicle-linux';
182
- $optipng_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'optipng-linux';
183
  $jpegtran_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'jpegtran-linux';
184
  $pngquant_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngquant-linux';
185
- $webp_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'cwebp-linux';
186
  $gifsicle_dst = $tool_path . 'gifsicle';
187
- $optipng_dst = $tool_path . 'optipng';
188
  $jpegtran_dst = $tool_path . 'jpegtran';
189
  $pngquant_dst = $tool_path . 'pngquant';
190
- $webp_dst = $tool_path . 'cwebp';
191
  }
192
  ewwwio_debug_message( "generated paths:<br>$jpegtran_src<br>$optipng_src<br>$gifsicle_src<br>$pngquant_src<br>$webp_src<br>$jpegtran_dst<br>$optipng_dst<br>$gifsicle_dst<br>$pngquant_dst<br>$webp_dst" );
193
  ewwwio_memory( __FUNCTION__ );
@@ -402,12 +402,12 @@ function ewww_image_optimizer_install_tools() {
402
  function ewww_image_optimizer_skip_tools() {
403
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
404
  $skip['jpegtran'] = false;
405
- $skip['optipng'] = false;
406
  $skip['gifsicle'] = false;
407
- $skip['pngout'] = false;
408
  // Except these which are off by default.
409
  $skip['pngquant'] = true;
410
- $skip['webp'] = true;
411
  // If the user has disabled a tool, we aren't going to bother checking to see if it is there.
412
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) == 0 || ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) > 10 ) {
413
  $skip['jpegtran'] = true;
@@ -498,7 +498,7 @@ function ewww_image_optimizer_notice_utils( $quiet = null ) {
498
  $skip = ewww_image_optimizer_skip_tools();
499
  // Attempt to retrieve values for utility paths, and store them in the appropriate variables.
500
  $required = ewww_image_optimizer_path_check( ! $skip['jpegtran'], ! $skip['optipng'], ! $skip['gifsicle'], ! $skip['pngout'], ! $skip['pngquant'], ! $skip['webp'] );
501
- $missing = array();
502
  // Go through each of the required tools.
503
  foreach ( $required as $key => $req ) {
504
  // if the tool wasn't found, add it to the $missing array if we are supposed to check the tool in question.
@@ -506,7 +506,7 @@ function ewww_image_optimizer_notice_utils( $quiet = null ) {
506
  case 'JPEGTRAN':
507
  if ( ! $skip['jpegtran'] && empty( $req ) ) {
508
  $missing[] = 'jpegtran';
509
- $req = false;
510
  }
511
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_' . $key ) ) {
512
  ewwwio_debug_message( "defining EWWW_IMAGE_OPTIMIZER_$key" );
@@ -516,7 +516,7 @@ function ewww_image_optimizer_notice_utils( $quiet = null ) {
516
  case 'OPTIPNG':
517
  if ( ! $skip['optipng'] && empty( $req ) ) {
518
  $missing[] = 'optipng';
519
- $req = false;
520
  }
521
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_' . $key ) ) {
522
  ewwwio_debug_message( "defining EWWW_IMAGE_OPTIMIZER_$key" );
@@ -526,7 +526,7 @@ function ewww_image_optimizer_notice_utils( $quiet = null ) {
526
  case 'GIFSICLE':
527
  if ( ! $skip['gifsicle'] && empty( $req ) ) {
528
  $missing[] = 'gifsicle';
529
- $req = false;
530
  }
531
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_' . $key ) ) {
532
  ewwwio_debug_message( "defining EWWW_IMAGE_OPTIMIZER_$key" );
@@ -536,7 +536,7 @@ function ewww_image_optimizer_notice_utils( $quiet = null ) {
536
  case 'PNGOUT':
537
  if ( ! $skip['pngout'] && empty( $req ) ) {
538
  $missing[] = 'pngout';
539
- $req = false;
540
  }
541
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_' . $key ) ) {
542
  ewwwio_debug_message( "defining EWWW_IMAGE_OPTIMIZER_$key" );
@@ -546,17 +546,17 @@ function ewww_image_optimizer_notice_utils( $quiet = null ) {
546
  case 'PNGQUANT':
547
  if ( ! $skip['pngquant'] && empty( $req ) ) {
548
  $missing[] = 'pngquant';
549
- $req = false;
550
  }
551
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_' . $key ) ) {
552
  ewwwio_debug_message( "defining EWWW_IMAGE_OPTIMIZER_$key" );
553
  define( 'EWWW_IMAGE_OPTIMIZER_' . $key, $req );
554
  }
555
  break;
556
- case 'WEBP':
557
  if ( ! $skip['webp'] && empty( $req ) ) {
558
  $missing[] = 'webp';
559
- $req = false;
560
  }
561
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_' . $key ) ) {
562
  ewwwio_debug_message( "defining EWWW_IMAGE_OPTIMIZER_$key" );
@@ -632,25 +632,25 @@ function ewww_image_optimizer_safemode_check() {
632
  * @param bool $p True to check pngout.
633
  * @param bool $q True to check pngquant.
634
  * @param bool $w True to check cwebp.
635
- * @return array Path for each tool (indexes JPEGTRAN, OPTIPNG, GIFSICLE, PNGOUT, PNGQUANT, WEBP),
636
  * or false for disabled/missing tools.
637
  */
638
  function ewww_image_optimizer_path_check( $j = true, $o = true, $g = true, $p = true, $q = true, $w = true ) {
639
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
640
  $jpegtran = false;
641
- $optipng = false;
642
  $gifsicle = false;
643
- $pngout = false;
644
  $pngquant = false;
645
- $webp = false;
646
  if ( EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
647
  return array(
648
  'JPEGTRAN' => false,
649
- 'OPTIPNG' => false,
650
  'GIFSICLE' => false,
651
- 'PNGOUT' => false,
652
  'PNGQUANT' => false,
653
- 'WEBP' => false,
654
  );
655
  }
656
  if ( 'WINNT' == PHP_OS ) {
@@ -700,12 +700,12 @@ function ewww_image_optimizer_path_check( $j = true, $o = true, $g = true, $p =
700
  }
701
  }
702
  if ( $w ) {
703
- if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_WEBP' ) ) {
704
  $webp = ewww_image_optimizer_find_win_binary( 'cwebp', 'w' );
705
- ewwwio_debug_message( 'defining EWWW_IMAGE_OPTIMIZER_WEBP' );
706
- define( 'EWWW_IMAGE_OPTIMIZER_WEBP', $webp );
707
  } else {
708
- $webp = EWWW_IMAGE_OPTIMIZER_WEBP;
709
  }
710
  }
711
  } else {
@@ -777,15 +777,15 @@ function ewww_image_optimizer_path_check( $j = true, $o = true, $g = true, $p =
777
  }
778
  }
779
  if ( $w ) {
780
- if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_WEBP' ) ) {
781
  $webp = ewww_image_optimizer_find_nix_binary( 'cwebp', 'w' );
782
  if ( ! $webp ) {
783
  $webp = ewww_image_optimizer_find_nix_binary( 'cwebp', 'wb' );
784
  }
785
- ewwwio_debug_message( 'defining EWWW_IMAGE_OPTIMIZER_WEBP' );
786
- define( 'EWWW_IMAGE_OPTIMIZER_WEBP', $webp );
787
  } else {
788
- $webp = EWWW_IMAGE_OPTIMIZER_WEBP;
789
  }
790
  }
791
  } // End if().
@@ -810,11 +810,11 @@ function ewww_image_optimizer_path_check( $j = true, $o = true, $g = true, $p =
810
  ewwwio_memory( __FUNCTION__ );
811
  return array(
812
  'JPEGTRAN' => $jpegtran,
813
- 'OPTIPNG' => $optipng,
814
  'GIFSICLE' => $gifsicle,
815
- 'PNGOUT' => $pngout,
816
  'PNGQUANT' => $pngquant,
817
- 'WEBP' => $webp,
818
  );
819
  }
820
 
@@ -829,161 +829,161 @@ function ewww_image_optimizer_md5check( $path ) {
829
  $binary_sum = hash_file( 'sha256', $path );
830
  ewwwio_debug_message( "$path: $binary_sum" );
831
  $valid_sums = array(
832
- '463de9ba684d54d27185cb6487a0b22b7571a87419abde4dee72c9b107f23315', // jpegtran-mac 9, EWWW 1.3.0
833
- '0b94f82e3d740d1853281e9aaee5cc7122c27fd63da9d6d62ed3398997cbed1e', // jpegtran-linux 9, EWWW 1.4.0
834
- 'f5f079bfe6f3f48c17738679292f35cdee44afe8f8413cdbc4f555cee7de4173', // jpegtran-linux64 9, EWWW 1.4.0
835
- 'ec71f638d2101f08fab66f4d139746d4042352bc75d55bd093aa446081892e0c', // jpegtran-fbsd 9, EWWW 1.4.0
836
- '356532227fce51fcb9df29f143ab9d202fbd40f18e2b8234aee95937c93bd67e', // jpegtran-fbsd64 9, EWWW 1.4.0
837
- '7be857837764dff4f0d7d2c5d546bf4d2573af7f326ced908ac229d60fd054c6', // jpegtran.exe 9, EWWW 1.4.0
838
- 'bce5205bb240532c01273b5442a44244a8a27a74fb47e2ce467c18b91fabea6b', // jpegtran-sol 9, EWWW 1.7.4
839
- 'cadc7be4688632bf2860562a1596f1b2b54b9a9c8b27df7ecabca49b1dcd8a5f', // jpegtran-fbsd 9a, EWWW 2.0.0
840
- 'bab4aa853c143534503464eeb35893d16799cf859ff22f9a4e62aa383f4fc99c', // jpegtran-fbsd64 9a, EWWW 2.0.0
841
- 'deb7e0f579fac767196611aa110052864e3093017970ff74de709b41e265e8b1', // jpegtran-linux 9a, EWWW 2.0.0
842
- 'b991fde396ebcc0e4f805df44b1797fe369f7f19e9392684dd4052e3f23c441e', // jpegtran-linux64 9a, EWWW 2.0.0
843
- '436835bd42b27d2f05440bc5dc5174f2a896d38f8a550d96704d39969951d9ac', // jpegtran-mac 9a, EWWW 2.0.0
844
- 'bdf3c6b6cb16287a3f62e7cde8f69f8bda5d310abca28e00068c526f9f37cc89', // jpegtran-sol 9a, EWWW 2.0.0
845
- '3c2746d0b1ae150b13b767715af45ff601e394c01ada929cbe16e6dcd18fb199', // jpegtran.exe 9a, EWWW 2.0.0
846
- '8e11f7df5735b36d3ecc95c84b0e355355a766d3ccafbf751bcf343a8952432c', // jpegtran-fbsd 9b, EWWW 2.6.0
847
- '21d8046e07cb298dfd2f3b1e321c67c378a4d35fa8adc3521acc42b5b8088d64', // jpegtran-linux 9b, EWWW 2.6.0
848
- '4d1a1c601d291f96dc03ea7e42ab9137a17f93ebc391353db65b4e32c1e9fbdb', // jpegtran-mac 9b, EWWW 2.6.0
849
- '7e8719703d31e1ab9bf2b2ad7ab633649012ab6aae46ea40462365b9c00876d5', // jpegtran-sol 9b, EWWW 2.6.0
850
- '9767f05ae1b59d4fea25a73b276dcd1245f5281b53386dc03784539265bffbea', // jpegtran.exe 9b, EWWW 2.6.0
851
  // end jpegtran.
852
- '6deddb5562ac13ffc3e46a0af79b592e92fb4553c5df294b6e0052bc890fd0e3', // optipng-linux 0.7.4, EWWW 1.2.0
853
- '51df81fa8c765efbe0aa4c1cf5293e25e7e2e7f6962f5161615239c54aec4c01', // optipng-linux 0.7.4, EWWW 1.3.0
854
- '7a56cca66471ce2b6cdff4460db0d75258ef05de8da1eda0448e4d4ad9ae252f', // optipng-mac 0.7.4, EWWW 1.3.0
855
- '2f9140cdc3ef1f7687baa710f0bba84c5f7f11e3f62c3ce43124e23b849ac5ff', // optipng-linux 0.7.4, EWWW 1.3.7
856
- '5d59467363c457bf743f4df121c365dd43365357f1cdea5f3752a7ca1b3e315a', // optipng-fbsd 0.7.4, EWWW 1.4.0
857
- '1af8077958a88a3064a71903841f901179e27fe137774085565619fb199c653a', // optipng.exe 0.7.4, EWWW 1.4.0
858
- 'f692fef395b8689de033b9f2ce80c867c8a229c52e948df733377e20b62773a9', // optipng-sol 0.7.4, EWWW 1.7.4
859
- 'e17d327cd89ab34eff7f994806fe9f2c124d6cc6cd309fa4c3911d5ce90312c9', // optipng-fbsd 0.7.5, EWWW 2.0.0
860
- 'd263ecfb5b29ed08920e26cf604a86d3484daee5b80605e445cf97aa14d8aebc', // optipng-linux 0.7.5, EWWW 2.0.0
861
- '6f15cb2e8d25e51037efa7bcec7499c96eb11e576536a478edfee500207655ae', // optipng-mac 0.7.5, EWWW 2.0.0
862
- '1d2de40b009f16e9c709f9b0c15a47abb8da57668a918ac9a0723ddc6de6c30a', // optipng-sol 0.7.5, EWWW 2.0.0
863
- 'fad3a0fd95706d53576f72593bf13d3e31d1c896c852bfd5b9ba602eca0bd2b6', // optipng.exe 0.7.5, EWWW 2.0.0
864
- '9d60eaeb9dc5167a57a5f3af236d56b4149d1043b543f2faa38a0936fa6b54b2', // optipng-fbsd 0.7.6, EWWW 2.8.0
865
- '853ca5936a2dd92a17b3518fd55db6be35e1b2bebfabca3949c34700072e08b8', // optipng-linux 0.7.6, EWWW 2.8.0
866
- 'd4f11e96733aed64a72e744843dcd0929e144a7fc97f40d405a034a72eb9bbc6', // optipng-mac 0.7.6, EWWW 2.8.0
867
- '1ed9343194cfca0a1c32677c974192746adfd48cb4cea6a2df668452df0e68f7', // optipng-sol 0.7.6, EWWW 2.8.0
868
- '03b86ce2c08e2cc78d76d3d3dd173986b498b055c3c19e13a97a7c3c674772c6', // optipng.exe 0.7.6, EWWW 2.8.0
869
  // end optipng.
870
- 'a2292c0085863a65c99cb41ff8418ce63033e162906df72e8fdde52f0633579b', // gifsicle linux 1.67, EWWW 1.2.0
871
- 'd7f9609b6fd0000b2eaad2bd0c3cb85476988b18705762e915bda3f2e6007801', // gifsicle-linux 1.68, EWWW 1.3.0
872
- '204a839a50367adb8cd23fae5d1913a5ca8b41307f054156ed152748d3e7934d', // gifsicle-linux 1.68, EWWW 1.3.7
873
- '23e208099fa7ce75a3f98144190d6362d69b90c6f0a534ffa45dbbf789f7d99c', // gifsicle-mac 1.68, EWWW 1.3.0
874
- '8b08243a7cc655512a03403f6c3814176e28bbd140df7c059bd321a9a0151c18', // gifsicle-fbsd 1.70, EWWW 1.4.0
875
- 'fd074673967ee9d387208f047c081a6331663b4076f4a6a608d6f646622af718', // gifsicle-linux 1.70, EWWW 1.4.0 - 1.7.4
876
- 'bc32a390e86d2d8f40e970b2dc059015b51afe26794d92a936c1fe7216db805d', // gifsicle-mac 1.70, EWWW 1.4.0
877
- '41e67a35cd178f781b5224d196185e4243e6c2b3bece43277130fe07cdda402f', // gifsicle-sol 1.70, EWWW 1.7.4
878
- '3c6d9fabd1ea1014b8f58063dd00a653980c06bc1b45e96a47d866247263a1e1', // gifsicle.exe 1.70, EWWW 1.4.0
879
- 'decba7a95b637bee53847af680fd37bde8bd568528412c514b7bd794056fd4ff', // gifsicle-fbsd 1.78, EWWW 1.7.5
880
- 'c28e5e4b5344f77f415973d013e4cb393fc550e8de44117b090d534e98b30d1c', // gifsicle-linux 1.78, EWWW 1.7.5 - 1.9.3
881
- 'fc2de863e8579b0d540003300e918cee450bc8e026018c631dffc0ed851a8c1c', // gifsicle-mac 1.78, EWWW 1.7.5
882
- '74d011ee1b6d9fe6d5d8bdb4cd17db0c5987fa6e3d495b42439cd70b0763c07a', // gifsicle-sol 1.78, EWWW 1.7.5
883
- '7c10da38f4afb28373779d40a30710aa9fb369e82f7f29363554bea965d132df', // gifsicle.exe 1.78, EWWW 1.7.5
884
- 'e75acedd0725fba64ee72855b796cdfa8dac9959d63e89a9e0e5ba059ae013c2', // gifsicle-fbsd 1.84, EWWW 2.0.0
885
- 'a4f0f21bc4bea51f5d304fe944262c12f671d70a3e5f688061da7bb036e84ff8', // gifsicle-linux 1.84, EWWW 2.0.0 - 2.4.3
886
- '5f4176b3fe69f975563d2ce7e76615ab558f5f1839b9bfa6f6de1b3c3fa11c02', // gifsicle-mac 1.84, EWWW 2.0.0
887
- '9f0027bed22d4be60012488ab726c3a131d9f3e1e276e9400c578173347a9a48', // gifsicle-sol 1.84, EWWW 2.0.0
888
- '72f0077e8591292d09efee09a181458b34fb3c0e9a6ac7e8e11cec574bf619ac', // gifsicle.exe 1.84, EWWW 2.0.0
889
- 'c64936b429e46b6a75339df00eb8daa39d335844c906fa16d4d0af481851e91e', // gifsicle-fbsd 1.87, EWWW 2.4.4
890
- 'deea065a91c8429edecf42ccef78636065f7ae0dad867df7696128c6711e4735', // gifsicle-linux 1.87, EWWW 2.4.4
891
- '2e0d8b7413173555bbec6e019c3cd7c55f7d582a017a0af7b14cfd24a6921f51', // gifsicle-mac 1.87, EWWW 2.4.4
892
- '3966e01474601059c6a13aefbe4f313c6cb6d49c799f7850966950892a9ab45a', // gifsicle-sol 1.87, EWWW 2.4.4
893
- '40b86b2ea6642f4c921152923af1e631922b624f7d23189f53c659506c7179b5', // gifsicle.exe 1.87, EWWW 2.4.4
894
- '3da9e1a764a459d78dc1468ba60d882ff042050a86f82d895777b172b50f2f19', // gifsicle.exe 1.87, EWWW 2.4.5
895
  // end gifsicle.
896
- 'bdea95497d6e60aae8938cae8e999ef74a255ad603531bf523dcdb531f61fc8f', // 20110722-bsd/i686/pngout
897
- '57c09b3ebd7d4623d16f6056efd7951e8f98e2362a27993a7d865af677875c00', // 20110722-bsd-static/i686/pngout-static
898
- '17960599ca28a61aeb883a68b2eb52c513b730a410a0db75a7c2c22e0a3f925a', // 20110722-linux/i686/pngout
899
- '689f68bcbf39e68cdf0f0a350d59c0acafdbcf7ff122e25b5a8b58ed3a8f18ef', // 20110722-linux/x86_64/pngout
900
- '2028eea62f04b074b7693e5ce625c848ff6521206782616c893ca93637644a51', // 20110722-linux-static/i686/pngout-static
901
- '7d071c3a6ac9c4e8077f029dbba1cde49008d38adf897401e951f9c2e7ce8bb1', // 20110722-linux-static/x86_64/pngout-static
902
- '89c510b551718d263433bb37e67364cab582a71bf7f5558213a121bb86cb5f98', // 20110722-mac/pngout
903
- 'e383a5293e3b1934c87367799f6eaefbd6714cfa004262f273fb7f2f4d15930b', // 20130221-bsd/i686/pngout
904
- 'd2b70c882be527543818d84552cc4e6faf40da3cec45286e5c36ed73e9611b7b', // 20130221-bsd/amd64/pngout
905
- 'bc08e1f883ba92a04e44fe4e756e1afc3b77fc1d072519adff6ce2f7787109bb', // 20130221-bsd-static/i686/pngout-static
906
- '860779de32c1fe34f211da036471d6e4ecc0d35527727d476f29623785cf6f82', // 20130221-bsd-static/amd64/pngout-static
907
- 'edd8e6173bf3b862c6c40c4b5aad6514169a58ee9b0b34d8c37e475005889592', // 20130221-linux/i686/pngout
908
- 'f6a053d1c03b69e2ac4435aaa5b5e13ea5169d9a262286595f9f455d8da5caf1', // 20130221-linux/x86_64/pngout
909
- '9591669b3984a19f0aab3a8e8fad98c5274b3c30daecf46b35d22df934546618', // 20130221-linux-static/i686/pngout-static
910
- '25d2aab99796c26f1e9cf1f2a9713920be40ce1b99e02c2c50b67fa6e3da06be', // 20130221-linux-static/x86_64/pngout-static
911
- '57fd225f3ae921309ee4570f1970629d31cb02946983405d1b1f648aeaab30a1', // 20130221-mac/pngout
912
- '3dfeb927e96853d2470350b0a916dc263cd4ebe878b402773dba105a6644e796', // 20150319-bsd/i686/pngout
913
- '60a2848c79551a3e79ffcea7f54964767e25bb05c2255b0ea6a1eb03605661d2', // 20150319-bsd/amd64/pngout
914
- '52dd45f15221f2ff30739151f30aedb5e3377dd6bccd350d4bce9429d7fa5e8b', // 20150319-bsd-static/i686/pngout-static
915
- '12ffa454936e1d35dc96749208d740695fea26d07267b6a17b9890db0f156026', // 20150319-bsd-static/amd64/pngout-static
916
- '5b97595c2b4e5f47ba797b105b3b56dbb769437bdc9092f07f6c57bc457ee667', // 20150319-linux/i686/pngout
917
- 'a496985d02c785c05f21f653fc4d61a5a171a68f691119448bc3c3152246f0d7', // 20150319-linux/x86_64/pngout
918
- 'b6641cb01b684c42e40076b91f98485dd115f6200d3f0baf989f1a4ae43c603a', // 20150319-linux-static/i686/pngout-static
919
- '2b8245fe21a648101b8e7399a9dfcc4cf42a39dafa7aab673a7c47901bf82e4a', // 20150319-linux-static/x86_64/pngout-static
920
- '12afd90e04387d4c3be985042c1eada89e0c4504f84c0b4739c459c7b3831774', // 20150319-mac/pngout
921
- '843f0be42e86680c1663c4ef58eb0677ace15fc29ab23897c83f4b7e5af3ef36', // 20150319-windows/pngout.exe 20150319
922
- 'aa3993937455094c0f66ac77d60bf53be441fdf8f14618520c2af68f2253085d', // 20150920-mac/pngout
923
  // end pngout.
924
- '8417d5d60bc66442ecc666e31ec7b9e1b7c55f48291e74b4b81f35703e2aef2e', // pngquant-fbsd 2.0.2, EWWW 1.8.3
925
- '78668c38d0be70764b18f3f4e0ea2b647df2ae87cedb2216d0ef69c8c55b688a', // pngquant-linux 2.0.2, EWWW 1.8.3
926
- '7df1b7f6ed73a189083dd931fb3380d236d34790318f00233b59c8f26f90665f', // pngquant-mac 2.0.2, EWWW 1.8.3
927
- '56d2c6212eb595f5eab8a7469e56fa8d3d0e6ffc231aef27742134fba4a39298', // pngquant-sol 2.0.2, EWWW 1.8.3
928
- 'd3851c962cd59d74a35174bf3ce71d876dfcd8bdf76f81cd428b2ab7e53c0515', // pngquant.exe 2.0.2, EWWW 1.8.3
929
- '0ee6f1dbf4fa168b11ce60860e5700ca0e5125323a43540a78c76644835abc84', // pngquant-fbsd 2.3.0, EWWW 2.0.0
930
- '85d8a70930a554f50181a1d061577cf67ef2e76e2cbd5bcb1b7f006064ff1444', // pngquant-linux 2.3.0, EWWW 2.0.0
931
- 'a807f769922fdad0ba07307c548df8cf8eeced649d04237d13dfc95757161459', // pngquant-mac 2.3.0, EWWW 2.0.0
932
- 'cf2cc40274c438b35e93bd0346c2a6d871bd7a7bdd90c52f4e79f369cb8ded74', // pngquant-sol 2.3.0, EWWW 2.0.0
933
- '7454aba77b1a2b63a42d8a5870d3c2d733c7efb2d828643d5e64784af1f65f2a', // pngquant.exe 2.3.0, EWWW 2.0.0
934
- '6287f1bb7179c7b6d71a41112222347ed97b6eae4e79b180d7e1e332a4bde3e2', // pngquant-fbsd 2.5.2, EWWW 2.5.4
935
- 'fcfe4d3a602e7b491f4126a2707144f5f9cc9359d13f443575d7ea6a74e85ddb', // pngquant-linux 2.5.2, EWWW 2.5.4
936
- '35794819a35e949dc0c0d6f90d0bb675791fa9bc3f405eb19f48ea31bb6456a8', // pngquant-mac 2.5.2, EWWW 2.5.4
937
- 'c242586c70d83af544334f1846b838ef68c6ab4fc247b2cff9ad4b714f825866', // pngquant-sol 2.5.2, EWWW 2.5.4
938
- 'ad79d9b3395d41404b28362972bd68db3c58d5be5f063884df3a595fc38c6a98', // pngquant.exe 2.5.2, EWWW 2.5.4
939
- '54d632fc4446d88ad4d1beeaf73420d68d87786f02adc9d3363766cb93ec95a4', // pngquant-fbsd 2.9.1, EWWW 3.4.0
940
- '91f704f02468f86766007e46973a1ef9e282d6ccadc54caf339dc537c9b2b61d', // pngquant-linux 2.9.1, EWWW 3.4.0
941
- '65dc20f05af588d948fc6f4df37c294f4a3a1c1ad207a8b56d13e6829773165a', // pngquant-mac 2.9.1, EWWW 3.4.0
942
- 'dbc9e12d5bb3e806aaf5e2c3d30d122d569069027a633485761cbf072cf2236d', // pngquant-sol 2.9.1, EWWW 3.4.0
943
- '84e63e6f9f9630a1a0c3e782609349c12b8df9ea9d02c5a29230819379e56b3c', // pngquant.exe 2.8.1, EWWW 3.4.0
944
  // end pngquant.
945
- 'bf0e12f996802dc114a864e5150647ce41089a5a2b5e36c3a270ac848b655c26', // cwebp-fbsd 0.4.1, EWWW 2.0.0
946
- '5349646072c3ef5f8b4588bbee8635e882c245439e2d86b863f04b7e27f4fafe', // cwebp-fbsd64 0.4.1, EWWW 2.0.0
947
- '3044c02cfef53f4361f7b2db49c5679f894ed346f665d4c8d91c6675d84dbf67', // cwebp-linux6 0.4.1, EWWW 2.0.0
948
- 'c9899718a5e272a082fd7c9d93d7c23d8a50f49d1b739a9aa1ef404f78cd7baf', // cwebp-linux664 0.4.1, EWWW 2.0.0
949
- '2a0dff5c80fd5fa170babd0c0571f4499606f8d09bf820938da41a311d6dec6f', // cwebp-linux8 0.4.1, EWWW 2.0.0
950
- 'c1dfbbad935e31bde2e517dff43911c0651a8e5f78c022a252a864278065ae11', // cwebp-linux864 0.4.1, EWWW 2.0.0
951
- 'bae23f1614d391b136e8618a21590e4a9f0614c8716b86a6a7067527e9950d87', // cwebp-mac7 0.4.1, EWWW 2.0.0
952
- 'bc72654fead42c6d4fd841cecdee6ccbf21b2407292593ec982f31d39b566955', // cwebp-mac8 0.4.1, EWWW 2.0.0
953
- '7fa005dc6a18563e4f6574bec83c92cabf786d8ee845503d80fa52e370dc4903', // cwebp-sol 0.4.1, EWWW 2.0.0
954
- '6486779c8e1e9cc7c63ae03c416fc6d5dc7598c58a6cddbe9a41e70d804410f9', // cwebp.exe 0.4.1, EWWW 2.0.0
955
- '814a168f190c4712df231b1f7d1910185ef823953b54c9fb8b354f415172a371', // cwebp-fbsd64 0.4.3, EWWW 2.4.4
956
- '0f867ea2db0db895612bd15916ad31bc71c89ef2ad74552b7e878df09b843da5', // cwebp-linux6 0.4.3, EWWW 2.4.4
957
- '179c7b9a2fbc1af542b3653bff58ca4dcb35bebf346687c12bb667ab49e9e21b', // cwebp-linux664 0.4.3, EWWW 2.4.4
958
- '212e59654bbb6147ee8a554bf8eb7b5c11f75b9ef14ac3e6ee92ad726a47339a', // cwebp-linux8 0.4.3, EWWW 2.4.4
959
- 'b491509221f7c97e8dcc3bdd6f7fc201f40bc93062618bfba06f84aac7704558', // cwebp-linux864 0.4.3, EWWW 2.4.4
960
- '2e8c5f53f44656ec80f11cca3c985200f502c88ea47bb34063e09eb6313e04a6', // cwebp-mac8 0.4.2, EWWW 2.4.4
961
- '963a09a2c45ba036291b32ecb665541e40c232bb0f2474810ac2a9ddf8837fe4', // cwebp-mac9 0.4.3, EWWW 2.4.4
962
- '2642d98bb75bc2fd2d969ba1d27b8628fd7fa73a7a204ed8f71a65e124abcac0', // cwebp-sol 0.4.3, EWWW 2.4.4
963
- '64cd62e33201b0d14ec4823b64d93f92825f2e8f5239726f5b00ed9ff944a581', // cwebp.exe 0.4.3, EWWW 2.4.4
964
- '7d7329671d445924dafcaacee7f2db6f4ce33567ffca41aa5b5818ebff806bc5', // cwebp-fbsd64 0.4.4, EWWW 2.5.4
965
- 'f1a48031d0ab602080f5646695ce8a3e84d5470f1be99d1b8fc20aded9c7839b', // cwebp-linux6 0.4.4, EWWW 2.5.4
966
- 'b2bef90b62d80b35d4c5a41f793454e95e5159bf0aec2e4bd8c19fc3de3556bd', // cwebp-linux664 0.4.4, EWWW 2.5.4
967
- 'd3c358524efd50f6e078362733870229ca1e1db8885580b6814c2535b4d20612', // cwebp-linux8 0.4.4, EWWW 2.5.4
968
- '271deeec579c252e364495addad03d9c1f3248c2177a01638002b25eee787ded', // cwebp-linux864 0.4.4, EWWW 2.5.4
969
- '379e2b95e20dd33f4667c134099df358e178f6a6bf32f3a5b6b78bbb6950b4b5', // cwebp-mac9 0.4.4, EWWW 2.5.4
970
- '118ea3f0bcdcce6128d64e34159c93c3324cb038c9e5a51efaf530ea52af7070', // cwebp-sol 0.4.4, EWWW 2.5.4
971
- '43941c1d7169e66fb1fd62a1950286b230d3e5bec3bbb14fdb4ac091ca7a0f9f', // cwebp.exe 0.4.4, EWWW 2.5.4
972
- '26d5d88dee2993d1d0e16f5e60318cd8adec485614facd6c7f9c22c71eb7b2e5', // cwebp-fbsd 0.5.0 EWWW 2.6.0
973
- '60b1738d6502691227a46658cd7656b4a52702680f169e8e04d72077e967aeed', // cwebp-linux 0.5.0, EWWW 2.6.0
974
- '276a0221a4c978825903572c2b68b3010399375d6b9dc7429286caf625cae95a', // cwebp-mac9 0.5.0, EWWW 2.6.0
975
- 'be3e81ec7267e7878ddd4ee01df1553966952f74bbfd30a5523d12d53f019ecb', // cwebp-sol 0.5.0, EWWW 2.6.0
976
- 'b41123ec06f21765f50ec1b017839f99ab4f28497d87da722817a6023e4a3b32', // cwebp.exe 0.5.0, EWWW 2.6.0
977
- 'f0547a6219c5c05d0af29c5e411e054b9d795567f4ae2e27893815af9383c60f', // cwebp-fbsd 0.5.1, EWWW 2.9.9
978
- '9eaf670bb2d567421c7e2918112dc00406c60f008b120f648cf0bdba73ee9b6b', // cwebp-linux 0.5.1, EWWW 2.9.9
979
- '1202ea932b315913d3736460dd3d50bc5b251b7a0a8f0468c63144ba427679c2', // cwebp-mac9 0.5.1, EWWW 2.9.9
980
- '27ba0abce52e74744f6235fcde9b153b5052b9c15cd78e74feffaea9dafcc178', // cwebp-sol 0.5.1, EWWW 2.9.9
981
- 'b02864989f0a1a263caa796c5b8caf18c1f774ed0ba08a9350e8820459875f51', // cwebp.exe 0.5.1, EWWW 2.9.9
982
- 'e5cbea11c97fadffe221fdf57c093c19af2737e4bbd2cb3cd5e908de64286573', // cwebp-fbsd 0.6.0, EWWW 3.4.0
983
- '43ca351e8f5d457b898c587151ebe3d8f6cce8dcfb7de44f6cb70148a31a68bc', // cwebp-linux 0.6.0, EWWW 3.4.0
984
- 'a06a3ee436e375c89dbc1b0b2e8bd7729a55139ae072ed3f7bd2e07de0ebb379', // cwebp-mac12 0.6.0, EWWW 3.4.0
985
- '1febaffbb18e52dc2c524cda9eefd00c6db95bc388732868999c0f48deb73b4f', // cwebp-sol 0.6.0, EWWW 3.4.0
986
- '49e9cb98db30bfa27936933e6fd94d407e0386802cb192800d9fd824f6476873', // cwebp.exe 0.6.0, EWWW 3.4.0
987
  // end cwebp.
988
  );
989
  foreach ( $valid_sums as $checksum ) {
@@ -1055,15 +1055,16 @@ function ewww_image_optimizer_mimetype( $path, $case ) {
1055
  ewwwio_debug_message( "file command: {$filetype[0]}" );
1056
  // If we've found a proper binary.
1057
  if ( ( strpos( $filetype[0], 'ELF' ) && strpos( $filetype[0], 'executable' ) )
1058
- || strpos( $filetype[0], 'Mach-O universal binary' )
1059
- || strpos( $filetype[0], 'Mach-O fat file with' )
 
1060
  ) {
1061
  $type = 'application/x-executable';
1062
  }
1063
  }
1064
  }
1065
  // If we are dealing with a binary, and found an executable.
1066
- if ( 'b' === $case && preg_match( '/executable|octet-stream|dosexec/', $type ) ) {
1067
  ewwwio_memory( __FUNCTION__ );
1068
  return $type;
1069
  // Otherwise, if we are dealing with an image.
@@ -1115,7 +1116,7 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1115
  break;
1116
  case 'jb':
1117
  $upload_dir = wp_upload_dir();
1118
- $testjpg = trailingslashit( $upload_dir['basedir'] ) . 'testopti.jpg';
1119
  exec( $path . ' -copy none -optimize -outfile ' . ewww_image_optimizer_escapeshellarg( $testjpg ) . ' ' . ewww_image_optimizer_escapeshellarg( EWWW_IMAGE_OPTIMIZER_IMAGES_PATH . 'testorig.jpg' ) );
1120
  $testjpgsize = ewww_image_optimizer_filesize( $testjpg );
1121
  ewwwio_debug_message( "blind testing jpegtran, is $testjpgsize smaller than 5700?" );
@@ -1139,7 +1140,7 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1139
  break;
1140
  case 'ob':
1141
  $upload_dir = wp_upload_dir();
1142
- $testpng = trailingslashit( $upload_dir['basedir'] ) . 'testopti.png';
1143
  exec( $path . ' -out ' . ewww_image_optimizer_escapeshellarg( $testpng ) . ' -o1 -quiet -strip all ' . ewww_image_optimizer_escapeshellarg( EWWW_IMAGE_OPTIMIZER_IMAGES_PATH . 'testorig.png' ) );
1144
  $testpngsize = ewww_image_optimizer_filesize( $testpng );
1145
  ewwwio_debug_message( "blind testing optipng, is $testpngsize smaller than 110?" );
@@ -1163,7 +1164,7 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1163
  break;
1164
  case 'gb':
1165
  $upload_dir = wp_upload_dir();
1166
- $testgif = trailingslashit( $upload_dir['basedir'] ) . 'testopti.gif';
1167
  exec( $path . ' -O3 -o ' . ewww_image_optimizer_escapeshellarg( $testgif ) . ' ' . ewww_image_optimizer_escapeshellarg( EWWW_IMAGE_OPTIMIZER_IMAGES_PATH . 'testorig.gif' ) );
1168
  $testgifsize = ewww_image_optimizer_filesize( $testgif );
1169
  ewwwio_debug_message( "blind testing gifsicle, is $testgifsize smaller than 12000?" );
@@ -1187,7 +1188,7 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1187
  break;
1188
  case 'pb':
1189
  $upload_dir = wp_upload_dir();
1190
- $testpng = trailingslashit( $upload_dir['basedir'] ) . 'testopti.png';
1191
  exec( $path . ' -s3 -q ' . ewww_image_optimizer_escapeshellarg( EWWW_IMAGE_OPTIMIZER_IMAGES_PATH . 'testorig.png' ) . ' ' . ewww_image_optimizer_escapeshellarg( $testpng ) );
1192
  $testpngsize = ewww_image_optimizer_filesize( $testpng );
1193
  ewwwio_debug_message( "blind testing pngout, is $testpngsize smaller than 110?" );
@@ -1211,7 +1212,7 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1211
  break;
1212
  case 'qb':
1213
  $upload_dir = wp_upload_dir();
1214
- $testpng = trailingslashit( $upload_dir['basedir'] ) . 'testopti.png';
1215
  exec( $path . ' -o ' . ewww_image_optimizer_escapeshellarg( $testpng ) . ' ' . ewww_image_optimizer_escapeshellarg( EWWW_IMAGE_OPTIMIZER_IMAGES_PATH . 'testorig.png' ) );
1216
  $testpngsize = ewww_image_optimizer_filesize( $testpng );
1217
  ewwwio_debug_message( "blind testing pngquant, is $testpngsize smaller than 114?" );
@@ -1284,7 +1285,7 @@ function ewww_image_optimizer_tool_found( $path, $tool ) {
1284
  break;
1285
  case 'wb':
1286
  $upload_dir = wp_upload_dir();
1287
- $testpng = trailingslashit( $upload_dir['basedir'] ) . 'testopti.png';
1288
  exec( $path . ' -lossless -quiet ' . ewww_image_optimizer_escapeshellarg( EWWW_IMAGE_OPTIMIZER_IMAGES_PATH . 'testorig.png' ) . ' -o ' . ewww_image_optimizer_escapeshellarg( $testpng ) );
1289
  $testpngsize = ewww_image_optimizer_filesize( $testpng );
1290
  ewwwio_debug_message( "blind testing cwebp, is $testpngsize smaller than 114?" );
@@ -1318,7 +1319,7 @@ function ewww_image_optimizer_find_win_binary( $binary, $switch ) {
1318
  return '';
1319
  }
1320
  $use_system = ewww_image_optimizer_get_option( 'ewww_image_optimizer_skip_bundle' );
1321
- $tool_path = trailingslashit( EWWW_IMAGE_OPTIMIZER_TOOL_PATH );
1322
  if ( file_exists( $tool_path . $binary . '.exe' ) && ! $use_system ) {
1323
  $binary_path = $tool_path . $binary . '.exe';
1324
  ewwwio_debug_message( "found $binary_path, testing..." );
@@ -1364,7 +1365,7 @@ function ewww_image_optimizer_find_nix_binary( $binary, $switch ) {
1364
  return '';
1365
  }
1366
  $use_system = ewww_image_optimizer_get_option( 'ewww_image_optimizer_skip_bundle' );
1367
- $tool_path = trailingslashit( EWWW_IMAGE_OPTIMIZER_TOOL_PATH );
1368
  // First check for the binary in the ewww tool folder.
1369
  if ( file_exists( $tool_path . $binary ) && ! $use_system ) {
1370
  $binary_path = $tool_path . $binary;
@@ -1543,7 +1544,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1543
  $s3_uploads_image = false;
1544
  }
1545
  if ( strpos( $file, 's3' ) === 0 && class_exists( 'S3_Uploads' ) ) {
1546
- $s3_uploads_image = $file;
1547
  $s3_uploads_instance = S3_Uploads::get_instance();
1548
  $s3_uploads_instance->setup();
1549
  if ( ! function_exists( 'wp_tempnam' ) ) {
@@ -1553,7 +1554,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1553
  }
1554
  // Initialize the original filename.
1555
  $original = $file;
1556
- $result = '';
1557
  if ( false === is_file( $file ) ) {
1558
  /* translators: %s: Image filename */
1559
  $msg = sprintf( __( 'Could not find %s', 'ewww-image-optimizer' ), $file );
@@ -1620,11 +1621,11 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1620
  $skip = ewww_image_optimizer_skip_tools();
1621
  if ( EWWW_IMAGE_OPTIMIZER_CLOUD ) {
1622
  $skip['jpegtran'] = true;
1623
- $skip['optipng'] = true;
1624
  $skip['gifsicle'] = true;
1625
- $skip['pngout'] = true;
1626
  $skip['pngquant'] = true;
1627
- $skip['webp'] = true;
1628
  }
1629
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_skip_full' ) && $fullsize ) {
1630
  $keep_metadata = true;
@@ -1657,7 +1658,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1657
  rename( $file, $refile );
1658
  ewwwio_debug_message( "moved $file to $refile" );
1659
  // And set $file to the new filename.
1660
- $file = $refile;
1661
  $original = $file;
1662
  }
1663
  // Get the original image size.
@@ -1682,7 +1683,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1682
  return array( false, __( 'Optimization skipped', 'ewww-image-optimizer' ), $converted, $file );
1683
  }
1684
  $backup_hash = '';
1685
- $new_size = 0;
1686
  // Set the optimization process to OFF.
1687
  $optimize = false;
1688
  // Toggle the convert process to ON.
@@ -1786,7 +1787,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1786
  // Copy all the metadata.
1787
  $copy_opt = 'all';
1788
  }
1789
- if ( $orig_size > 102400 ) {
1790
  $progressive = '-progressive';
1791
  } else {
1792
  $progressive = '';
@@ -1809,12 +1810,12 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1809
  unlink( $progfile );
1810
  }
1811
  // Store the results.
1812
- $result = 'unchanged';
1813
  $new_size = $orig_size;
1814
  }
1815
  } elseif ( ! $convert ) {
1816
  // If conversion and optimization are both turned OFF, finish the JPG processing.
1817
- ewww_image_optimizer_webp_create( $file, $orig_size, $type, $tools['WEBP'] );
1818
  break;
1819
  } // End if().
1820
  // If the conversion process is turned ON, or if this is a resize and the full-size was converted.
@@ -1920,7 +1921,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1920
  }
1921
  }
1922
  } // End if().
1923
- ewww_image_optimizer_webp_create( $file, $new_size, $type, $tools['WEBP'], $orig_size != $new_size );
1924
  break;
1925
  case 'image/png':
1926
  $jpg_size = 0;
@@ -1930,9 +1931,9 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1930
  && 1 == $gallery_type && ! $skip_lossy ) {
1931
  ewwwio_debug_message( 'PNG to JPG conversion turned on' );
1932
  $cloud_background = '';
1933
- $r = '';
1934
- $g = '';
1935
- $b = '';
1936
  // If the user set a fill background for transparency.
1937
  $background = ewww_image_optimizer_jpg_background();
1938
  if ( $background ) {
@@ -1966,13 +1967,13 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
1966
  } else {
1967
  ewwwio_debug_message( 'PNG to JPG conversion turned off' );
1968
  // Turn the conversion process OFF.
1969
- $convert = false;
1970
- $jpgfile = '';
1971
- $r = null;
1972
- $g = null;
1973
- $b = null;
1974
  $cloud_background = '';
1975
- $gquality = null;
1976
  } // End if().
1977
  // Check for previous optimization, so long as the force flag is on and this isn't a new image that needs converting.
1978
  if ( empty( $_REQUEST['ewww_force'] ) && ! ( $new && $convert ) ) {
@@ -2098,13 +2099,13 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2098
  unlink( $tempfile );
2099
  }
2100
  // Store the results.
2101
- $result = 'unchanged';
2102
  $new_size = $orig_size;
2103
  }
2104
  } elseif ( ! $convert ) {
2105
  // If conversion and optimization are both disabled we are done here.
2106
  ewwwio_debug_message( 'calling webp, but neither convert or optimize' );
2107
- ewww_image_optimizer_webp_create( $file, $orig_size, $type, $tools['WEBP'] );
2108
  break;
2109
  } // End if().
2110
  // Retrieve the new filesize of the PNG.
@@ -2129,7 +2130,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2129
  try {
2130
  if ( ewww_image_optimizer_png_alpha( $file ) ) {
2131
  $gmagick_overlay = new Gmagick( $file );
2132
- $gmagick = new Gmagick();
2133
  $gmagick->newimage( $gmagick_overlay->getimagewidth(), $gmagick_overlay->getimageheight(), '#' . $magick_background );
2134
  $gmagick->compositeimage( $gmagick_overlay, 1, 0, 0 );
2135
  } else {
@@ -2198,7 +2199,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2198
  // Copy all the metadata.
2199
  $copy_opt = 'all';
2200
  }
2201
- if ( $jpg_size > 102400 ) {
2202
  $progressive = '-progressive';
2203
  } else {
2204
  $progressive = '';
@@ -2243,7 +2244,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2243
  }
2244
  }
2245
  } // End if().
2246
- ewww_image_optimizer_webp_create( $file, $new_size, $type, $tools['WEBP'], $orig_size != $new_size );
2247
  break;
2248
  case 'image/gif':
2249
  // If gif2png is turned on, and the image is in the WordPress media library.
@@ -2339,7 +2340,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2339
  unlink( $tempfile );
2340
  }
2341
  // Store the results.
2342
- $result = 'unchanged';
2343
  $new_size = $orig_size;
2344
  }
2345
  } elseif ( ! $convert ) {
@@ -2394,7 +2395,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2394
  // Let webp know what we're dealing with now.
2395
  $type = 'image/png';
2396
  // Normally this would be at the end of the section, but we only want to do webp if the image was successfully converted to a png.
2397
- ewww_image_optimizer_webp_create( $file, $new_size, $type, $tools['WEBP'], $orig_size != $new_size );
2398
  // Successful conversion, so we store the increment.
2399
  $converted = $filenum;
2400
  } else {
@@ -2442,7 +2443,7 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2442
  }
2443
  if ( ! empty( $new_size ) ) {
2444
  // Set correct file permissions.
2445
- $stat = stat( dirname( $file ) );
2446
  $perms = $stat['mode'] & 0000666; // Same permissions as parent folder, strip off the executable bits.
2447
  chmod( $file, $perms );
2448
 
@@ -2476,8 +2477,12 @@ function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $ne
2476
  function ewww_image_optimizer_webp_create( $file, $orig_size, $type, $tool, $recreate = false ) {
2477
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
2478
  // Change the file extension.
2479
- $webpfile = $file . '.webp';
2480
- if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) ) {
 
 
 
 
2481
  return;
2482
  } elseif ( is_file( $webpfile ) && empty( $_REQUEST['ewww_force'] ) && ! $recreate ) {
2483
  ewwwio_debug_message( 'webp file exists, not forcing or recreating' );
@@ -2513,7 +2518,7 @@ function ewww_image_optimizer_webp_create( $file, $orig_size, $type, $tool, $rec
2513
  unlink( $webpfile );
2514
  } elseif ( is_file( $webpfile ) ) {
2515
  // Set correct file permissions.
2516
- $stat = stat( dirname( $webpfile ) );
2517
  $perms = $stat['mode'] & 0000666; // Same permissions as parent folder, strip off the executable bits.
2518
  chmod( $webpfile, $perms );
2519
  }
@@ -2553,7 +2558,7 @@ function ewww_image_optimizer_install_pngout() {
2553
  if ( PHP_OS == 'FreeBSD' ) {
2554
  $os_string = 'bsd';
2555
  }
2556
- $latest = '20150319';
2557
  $tool_path = trailingslashit( EWWW_IMAGE_OPTIMIZER_TOOL_PATH );
2558
  if ( empty( $pngout_error ) ) {
2559
  if ( PHP_OS == 'Linux' || PHP_OS == 'FreeBSD' ) {
@@ -2624,7 +2629,7 @@ function ewww_image_optimizer_install_pngout() {
2624
  $sendback = add_query_arg(
2625
  array(
2626
  'ewww_pngout' => 'failed',
2627
- 'ewww_error' => urlencode( $pngout_error ),
2628
  ),
2629
  remove_query_arg( array( 'ewww_pngout', 'ewww_error' ), wp_get_referer() )
2630
  );
127
  $tool_path = trailingslashit( EWWW_IMAGE_OPTIMIZER_TOOL_PATH );
128
  if ( PHP_OS == 'WINNT' ) {
129
  $gifsicle_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'gifsicle.exe';
130
+ $optipng_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'optipng.exe';
131
  $jpegtran_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'jpegtran.exe';
132
  $pngquant_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngquant.exe';
133
+ $webp_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'cwebp.exe';
134
  $gifsicle_dst = $tool_path . 'gifsicle.exe';
135
+ $optipng_dst = $tool_path . 'optipng.exe';
136
  $jpegtran_dst = $tool_path . 'jpegtran.exe';
137
  $pngquant_dst = $tool_path . 'pngquant.exe';
138
+ $webp_dst = $tool_path . 'cwebp.exe';
139
  }
140
  if ( PHP_OS == 'Darwin' ) {
141
  $gifsicle_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'gifsicle-mac';
142
+ $optipng_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'optipng-mac';
143
  $jpegtran_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'jpegtran-mac';
144
  $pngquant_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngquant-mac';
145
+ $webp_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'cwebp-mac12';
146
  $gifsicle_dst = $tool_path . 'gifsicle';
147
+ $optipng_dst = $tool_path . 'optipng';
148
  $jpegtran_dst = $tool_path . 'jpegtran';
149
  $pngquant_dst = $tool_path . 'pngquant';
150
+ $webp_dst = $tool_path . 'cwebp';
151
  }
152
  if ( PHP_OS == 'SunOS' ) {
153
  $gifsicle_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'gifsicle-sol';
154
+ $optipng_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'optipng-sol';
155
  $jpegtran_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'jpegtran-sol';
156
  $pngquant_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngquant-sol';
157
+ $webp_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'cwebp-sol';
158
  $gifsicle_dst = $tool_path . 'gifsicle';
159
+ $optipng_dst = $tool_path . 'optipng';
160
  $jpegtran_dst = $tool_path . 'jpegtran';
161
  $pngquant_dst = $tool_path . 'pngquant';
162
+ $webp_dst = $tool_path . 'cwebp';
163
  }
164
  if ( PHP_OS == 'FreeBSD' ) {
165
  $arch_type = php_uname( 'm' );
166
  ewwwio_debug_message( "CPU architecture: $arch_type" );
167
  $gifsicle_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'gifsicle-fbsd';
168
+ $optipng_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'optipng-fbsd';
169
  $jpegtran_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'jpegtran-fbsd';
170
  $pngquant_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngquant-fbsd';
171
+ $webp_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'cwebp-fbsd';
172
  $gifsicle_dst = $tool_path . 'gifsicle';
173
+ $optipng_dst = $tool_path . 'optipng';
174
  $jpegtran_dst = $tool_path . 'jpegtran';
175
  $pngquant_dst = $tool_path . 'pngquant';
176
+ $webp_dst = $tool_path . 'cwebp';
177
  }
178
  if ( PHP_OS == 'Linux' ) {
179
  $arch_type = php_uname( 'm' );
180
  ewwwio_debug_message( "CPU architecture: $arch_type" );
181
  $gifsicle_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'gifsicle-linux';
182
+ $optipng_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'optipng-linux';
183
  $jpegtran_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'jpegtran-linux';
184
  $pngquant_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngquant-linux';
185
+ $webp_src = EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'cwebp-linux';
186
  $gifsicle_dst = $tool_path . 'gifsicle';
187
+ $optipng_dst = $tool_path . 'optipng';
188
  $jpegtran_dst = $tool_path . 'jpegtran';
189
  $pngquant_dst = $tool_path . 'pngquant';
190
+ $webp_dst = $tool_path . 'cwebp';
191
  }
192
  ewwwio_debug_message( "generated paths:<br>$jpegtran_src<br>$optipng_src<br>$gifsicle_src<br>$pngquant_src<br>$webp_src<br>$jpegtran_dst<br>$optipng_dst<br>$gifsicle_dst<br>$pngquant_dst<br>$webp_dst" );
193
  ewwwio_memory( __FUNCTION__ );
402
  function ewww_image_optimizer_skip_tools() {
403
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
404
  $skip['jpegtran'] = false;
405
+ $skip['optipng'] = false;
406
  $skip['gifsicle'] = false;
407
+ $skip['pngout'] = false;
408
  // Except these which are off by default.
409
  $skip['pngquant'] = true;
410
+ $skip['webp'] = true;
411
  // If the user has disabled a tool, we aren't going to bother checking to see if it is there.
412
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) == 0 || ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) > 10 ) {
413
  $skip['jpegtran'] = true;
498
  $skip = ewww_image_optimizer_skip_tools();
499
  // Attempt to retrieve values for utility paths, and store them in the appropriate variables.
500
  $required = ewww_image_optimizer_path_check( ! $skip['jpegtran'], ! $skip['optipng'], ! $skip['gifsicle'], ! $skip['pngout'], ! $skip['pngquant'], ! $skip['webp'] );
501
+ $missing = array();
502
  // Go through each of the required tools.
503
  foreach ( $required as $key => $req ) {
504
  // if the tool wasn't found, add it to the $missing array if we are supposed to check the tool in question.
506
  case 'JPEGTRAN':
507
  if ( ! $skip['jpegtran'] && empty( $req ) ) {
508
  $missing[] = 'jpegtran';
509
+ $req = false;
510
  }
511
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_' . $key ) ) {
512
  ewwwio_debug_message( "defining EWWW_IMAGE_OPTIMIZER_$key" );
516
  case 'OPTIPNG':
517
  if ( ! $skip['optipng'] && empty( $req ) ) {
518
  $missing[] = 'optipng';
519
+ $req = false;
520
  }
521
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_' . $key ) ) {
522
  ewwwio_debug_message( "defining EWWW_IMAGE_OPTIMIZER_$key" );
526
  case 'GIFSICLE':
527
  if ( ! $skip['gifsicle'] && empty( $req ) ) {
528
  $missing[] = 'gifsicle';
529
+ $req = false;
530
  }
531
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_' . $key ) ) {
532
  ewwwio_debug_message( "defining EWWW_IMAGE_OPTIMIZER_$key" );
536
  case 'PNGOUT':
537
  if ( ! $skip['pngout'] && empty( $req ) ) {
538
  $missing[] = 'pngout';
539
+ $req = false;
540
  }
541
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_' . $key ) ) {
542
  ewwwio_debug_message( "defining EWWW_IMAGE_OPTIMIZER_$key" );
546
  case 'PNGQUANT':
547
  if ( ! $skip['pngquant'] && empty( $req ) ) {
548
  $missing[] = 'pngquant';
549
+ $req = false;
550
  }
551
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_' . $key ) ) {
552
  ewwwio_debug_message( "defining EWWW_IMAGE_OPTIMIZER_$key" );
553
  define( 'EWWW_IMAGE_OPTIMIZER_' . $key, $req );
554
  }
555
  break;
556
+ case 'CWEBP':
557
  if ( ! $skip['webp'] && empty( $req ) ) {
558
  $missing[] = 'webp';
559
+ $req = false;
560
  }
561
  if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_' . $key ) ) {
562
  ewwwio_debug_message( "defining EWWW_IMAGE_OPTIMIZER_$key" );
632
  * @param bool $p True to check pngout.
633
  * @param bool $q True to check pngquant.
634
  * @param bool $w True to check cwebp.
635
+ * @return array Path for each tool (indexes JPEGTRAN, OPTIPNG, GIFSICLE, PNGOUT, PNGQUANT, CWEBP),
636
  * or false for disabled/missing tools.
637
  */
638
  function ewww_image_optimizer_path_check( $j = true, $o = true, $g = true, $p = true, $q = true, $w = true ) {
639
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
640
  $jpegtran = false;
641
+ $optipng = false;
642
  $gifsicle = false;
643
+ $pngout = false;
644
  $pngquant = false;
645
+ $webp = false;
646
  if ( EWWW_IMAGE_OPTIMIZER_NOEXEC ) {
647
  return array(
648
  'JPEGTRAN' => false,
649
+ 'OPTIPNG' => false,
650
  'GIFSICLE' => false,
651
+ 'PNGOUT' => false,
652
  'PNGQUANT' => false,
653
+ 'CWEBP' => false,
654
  );
655
  }
656
  if ( 'WINNT' == PHP_OS ) {
700
  }
701
  }
702
  if ( $w ) {
703
+ if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_CWEBP' ) ) {
704
  $webp = ewww_image_optimizer_find_win_binary( 'cwebp', 'w' );
705
+ ewwwio_debug_message( 'defining EWWW_IMAGE_OPTIMIZER_CWEBP' );
706
+ define( 'EWWW_IMAGE_OPTIMIZER_CWEBP', $webp );
707
  } else {
708
+ $webp = EWWW_IMAGE_OPTIMIZER_CWEBP;
709
  }
710
  }
711
  } else {
777
  }
778
  }
779
  if ( $w ) {
780
+ if ( ! defined( 'EWWW_IMAGE_OPTIMIZER_CWEBP' ) ) {
781
  $webp = ewww_image_optimizer_find_nix_binary( 'cwebp', 'w' );
782
  if ( ! $webp ) {
783
  $webp = ewww_image_optimizer_find_nix_binary( 'cwebp', 'wb' );
784
  }
785
+ ewwwio_debug_message( 'defining EWWW_IMAGE_OPTIMIZER_CWEBP' );
786
+ define( 'EWWW_IMAGE_OPTIMIZER_CWEBP', $webp );
787
  } else {
788
+ $webp = EWWW_IMAGE_OPTIMIZER_CWEBP;
789
  }
790
  }
791
  } // End if().
810
  ewwwio_memory( __FUNCTION__ );
811
  return array(
812
  'JPEGTRAN' => $jpegtran,
813
+ 'OPTIPNG' => $optipng,
814
  'GIFSICLE' => $gifsicle,
815
+ 'PNGOUT' => $pngout,
816
  'PNGQUANT' => $pngquant,
817
+ 'CWEBP' => $webp,
818
  );
819
  }
820
 
829
  $binary_sum = hash_file( 'sha256', $path );
830
  ewwwio_debug_message( "$path: $binary_sum" );
831
  $valid_sums = array(
832
+ '463de9ba684d54d27185cb6487a0b22b7571a87419abde4dee72c9b107f23315', // jpegtran-mac 9, EWWW 1.3.0.
833
+ '0b94f82e3d740d1853281e9aaee5cc7122c27fd63da9d6d62ed3398997cbed1e', // jpegtran-linux 9, EWWW 1.4.0.
834
+ 'f5f079bfe6f3f48c17738679292f35cdee44afe8f8413cdbc4f555cee7de4173', // jpegtran-linux64 9, EWWW 1.4.0.
835
+ 'ec71f638d2101f08fab66f4d139746d4042352bc75d55bd093aa446081892e0c', // jpegtran-fbsd 9, EWWW 1.4.0.
836
+ '356532227fce51fcb9df29f143ab9d202fbd40f18e2b8234aee95937c93bd67e', // jpegtran-fbsd64 9, EWWW 1.4.0.
837
+ '7be857837764dff4f0d7d2c5d546bf4d2573af7f326ced908ac229d60fd054c6', // jpegtran.exe 9, EWWW 1.4.0.
838
+ 'bce5205bb240532c01273b5442a44244a8a27a74fb47e2ce467c18b91fabea6b', // jpegtran-sol 9, EWWW 1.7.4.
839
+ 'cadc7be4688632bf2860562a1596f1b2b54b9a9c8b27df7ecabca49b1dcd8a5f', // jpegtran-fbsd 9a, EWWW 2.0.0.
840
+ 'bab4aa853c143534503464eeb35893d16799cf859ff22f9a4e62aa383f4fc99c', // jpegtran-fbsd64 9a, EWWW 2.0.0.
841
+ 'deb7e0f579fac767196611aa110052864e3093017970ff74de709b41e265e8b1', // jpegtran-linux 9a, EWWW 2.0.0.
842
+ 'b991fde396ebcc0e4f805df44b1797fe369f7f19e9392684dd4052e3f23c441e', // jpegtran-linux64 9a, EWWW 2.0.0.
843
+ '436835bd42b27d2f05440bc5dc5174f2a896d38f8a550d96704d39969951d9ac', // jpegtran-mac 9a, EWWW 2.0.0.
844
+ 'bdf3c6b6cb16287a3f62e7cde8f69f8bda5d310abca28e00068c526f9f37cc89', // jpegtran-sol 9a, EWWW 2.0.0.
845
+ '3c2746d0b1ae150b13b767715af45ff601e394c01ada929cbe16e6dcd18fb199', // jpegtran.exe 9a, EWWW 2.0.0.
846
+ '8e11f7df5735b36d3ecc95c84b0e355355a766d3ccafbf751bcf343a8952432c', // jpegtran-fbsd 9b, EWWW 2.6.0.
847
+ '21d8046e07cb298dfd2f3b1e321c67c378a4d35fa8adc3521acc42b5b8088d64', // jpegtran-linux 9b, EWWW 2.6.0.
848
+ '4d1a1c601d291f96dc03ea7e42ab9137a17f93ebc391353db65b4e32c1e9fbdb', // jpegtran-mac 9b, EWWW 2.6.0.
849
+ '7e8719703d31e1ab9bf2b2ad7ab633649012ab6aae46ea40462365b9c00876d5', // jpegtran-sol 9b, EWWW 2.6.0.
850
+ '9767f05ae1b59d4fea25a73b276dcd1245f5281b53386dc03784539265bffbea', // jpegtran.exe 9b, EWWW 2.6.0.
851
  // end jpegtran.
852
+ '6deddb5562ac13ffc3e46a0af79b592e92fb4553c5df294b6e0052bc890fd0e3', // optipng-linux 0.7.4, EWWW 1.2.0.
853
+ '51df81fa8c765efbe0aa4c1cf5293e25e7e2e7f6962f5161615239c54aec4c01', // optipng-linux 0.7.4, EWWW 1.3.0.
854
+ '7a56cca66471ce2b6cdff4460db0d75258ef05de8da1eda0448e4d4ad9ae252f', // optipng-mac 0.7.4, EWWW 1.3.0.
855
+ '2f9140cdc3ef1f7687baa710f0bba84c5f7f11e3f62c3ce43124e23b849ac5ff', // optipng-linux 0.7.4, EWWW 1.3.7.
856
+ '5d59467363c457bf743f4df121c365dd43365357f1cdea5f3752a7ca1b3e315a', // optipng-fbsd 0.7.4, EWWW 1.4.0.
857
+ '1af8077958a88a3064a71903841f901179e27fe137774085565619fb199c653a', // optipng.exe 0.7.4, EWWW 1.4.0.
858
+ 'f692fef395b8689de033b9f2ce80c867c8a229c52e948df733377e20b62773a9', // optipng-sol 0.7.4, EWWW 1.7.4.
859
+ 'e17d327cd89ab34eff7f994806fe9f2c124d6cc6cd309fa4c3911d5ce90312c9', // optipng-fbsd 0.7.5, EWWW 2.0.0.
860
+ 'd263ecfb5b29ed08920e26cf604a86d3484daee5b80605e445cf97aa14d8aebc', // optipng-linux 0.7.5, EWWW 2.0.0.
861
+ '6f15cb2e8d25e51037efa7bcec7499c96eb11e576536a478edfee500207655ae', // optipng-mac 0.7.5, EWWW 2.0.0.
862
+ '1d2de40b009f16e9c709f9b0c15a47abb8da57668a918ac9a0723ddc6de6c30a', // optipng-sol 0.7.5, EWWW 2.0.0.
863
+ 'fad3a0fd95706d53576f72593bf13d3e31d1c896c852bfd5b9ba602eca0bd2b6', // optipng.exe 0.7.5, EWWW 2.0.0.
864
+ '9d60eaeb9dc5167a57a5f3af236d56b4149d1043b543f2faa38a0936fa6b54b2', // optipng-fbsd 0.7.6, EWWW 2.8.0.
865
+ '853ca5936a2dd92a17b3518fd55db6be35e1b2bebfabca3949c34700072e08b8', // optipng-linux 0.7.6, EWWW 2.8.0.
866
+ 'd4f11e96733aed64a72e744843dcd0929e144a7fc97f40d405a034a72eb9bbc6', // optipng-mac 0.7.6, EWWW 2.8.0.
867
+ '1ed9343194cfca0a1c32677c974192746adfd48cb4cea6a2df668452df0e68f7', // optipng-sol 0.7.6, EWWW 2.8.0.
868
+ '03b86ce2c08e2cc78d76d3d3dd173986b498b055c3c19e13a97a7c3c674772c6', // optipng.exe 0.7.6, EWWW 2.8.0.
869
  // end optipng.
870
+ 'a2292c0085863a65c99cb41ff8418ce63033e162906df72e8fdde52f0633579b', // gifsicle linux 1.67, EWWW 1.2.0.
871
+ 'd7f9609b6fd0000b2eaad2bd0c3cb85476988b18705762e915bda3f2e6007801', // gifsicle-linux 1.68, EWWW 1.3.0.
872
+ '204a839a50367adb8cd23fae5d1913a5ca8b41307f054156ed152748d3e7934d', // gifsicle-linux 1.68, EWWW 1.3.7.
873
+ '23e208099fa7ce75a3f98144190d6362d69b90c6f0a534ffa45dbbf789f7d99c', // gifsicle-mac 1.68, EWWW 1.3.0.
874
+ '8b08243a7cc655512a03403f6c3814176e28bbd140df7c059bd321a9a0151c18', // gifsicle-fbsd 1.70, EWWW 1.4.0.
875
+ 'fd074673967ee9d387208f047c081a6331663b4076f4a6a608d6f646622af718', // gifsicle-linux 1.70, EWWW 1.4.0 - 1.7.4.
876
+ 'bc32a390e86d2d8f40e970b2dc059015b51afe26794d92a936c1fe7216db805d', // gifsicle-mac 1.70, EWWW 1.4.0.
877
+ '41e67a35cd178f781b5224d196185e4243e6c2b3bece43277130fe07cdda402f', // gifsicle-sol 1.70, EWWW 1.7.4.
878
+ '3c6d9fabd1ea1014b8f58063dd00a653980c06bc1b45e96a47d866247263a1e1', // gifsicle.exe 1.70, EWWW 1.4.0.
879
+ 'decba7a95b637bee53847af680fd37bde8bd568528412c514b7bd794056fd4ff', // gifsicle-fbsd 1.78, EWWW 1.7.5.
880
+ 'c28e5e4b5344f77f415973d013e4cb393fc550e8de44117b090d534e98b30d1c', // gifsicle-linux 1.78, EWWW 1.7.5 - 1.9.3.
881
+ 'fc2de863e8579b0d540003300e918cee450bc8e026018c631dffc0ed851a8c1c', // gifsicle-mac 1.78, EWWW 1.7.5.
882
+ '74d011ee1b6d9fe6d5d8bdb4cd17db0c5987fa6e3d495b42439cd70b0763c07a', // gifsicle-sol 1.78, EWWW 1.7.5.
883
+ '7c10da38f4afb28373779d40a30710aa9fb369e82f7f29363554bea965d132df', // gifsicle.exe 1.78, EWWW 1.7.5.
884
+ 'e75acedd0725fba64ee72855b796cdfa8dac9959d63e89a9e0e5ba059ae013c2', // gifsicle-fbsd 1.84, EWWW 2.0.0.
885
+ 'a4f0f21bc4bea51f5d304fe944262c12f671d70a3e5f688061da7bb036e84ff8', // gifsicle-linux 1.84, EWWW 2.0.0 - 2.4.3.
886
+ '5f4176b3fe69f975563d2ce7e76615ab558f5f1839b9bfa6f6de1b3c3fa11c02', // gifsicle-mac 1.84, EWWW 2.0.0.
887
+ '9f0027bed22d4be60012488ab726c3a131d9f3e1e276e9400c578173347a9a48', // gifsicle-sol 1.84, EWWW 2.0.0.
888
+ '72f0077e8591292d09efee09a181458b34fb3c0e9a6ac7e8e11cec574bf619ac', // gifsicle.exe 1.84, EWWW 2.0.0.
889
+ 'c64936b429e46b6a75339df00eb8daa39d335844c906fa16d4d0af481851e91e', // gifsicle-fbsd 1.87, EWWW 2.4.4.
890
+ 'deea065a91c8429edecf42ccef78636065f7ae0dad867df7696128c6711e4735', // gifsicle-linux 1.87, EWWW 2.4.4.
891
+ '2e0d8b7413173555bbec6e019c3cd7c55f7d582a017a0af7b14cfd24a6921f51', // gifsicle-mac 1.87, EWWW 2.4.4.
892
+ '3966e01474601059c6a13aefbe4f313c6cb6d49c799f7850966950892a9ab45a', // gifsicle-sol 1.87, EWWW 2.4.4.
893
+ '40b86b2ea6642f4c921152923af1e631922b624f7d23189f53c659506c7179b5', // gifsicle.exe 1.87, EWWW 2.4.4.
894
+ '3da9e1a764a459d78dc1468ba60d882ff042050a86f82d895777b172b50f2f19', // gifsicle.exe 1.87, EWWW 2.4.5.
895
  // end gifsicle.
896
+ 'bdea95497d6e60aae8938cae8e999ef74a255ad603531bf523dcdb531f61fc8f', // 20110722-bsd/i686/pngout.
897
+ '57c09b3ebd7d4623d16f6056efd7951e8f98e2362a27993a7d865af677875c00', // 20110722-bsd-static/i686/pngout-static.
898
+ '17960599ca28a61aeb883a68b2eb52c513b730a410a0db75a7c2c22e0a3f925a', // 20110722-linux/i686/pngout.
899
+ '689f68bcbf39e68cdf0f0a350d59c0acafdbcf7ff122e25b5a8b58ed3a8f18ef', // 20110722-linux/x86_64/pngout.
900
+ '2028eea62f04b074b7693e5ce625c848ff6521206782616c893ca93637644a51', // 20110722-linux-static/i686/pngout-static.
901
+ '7d071c3a6ac9c4e8077f029dbba1cde49008d38adf897401e951f9c2e7ce8bb1', // 20110722-linux-static/x86_64/pngout-static.
902
+ '89c510b551718d263433bb37e67364cab582a71bf7f5558213a121bb86cb5f98', // 20110722-mac/pngout.
903
+ 'e383a5293e3b1934c87367799f6eaefbd6714cfa004262f273fb7f2f4d15930b', // 20130221-bsd/i686/pngout.
904
+ 'd2b70c882be527543818d84552cc4e6faf40da3cec45286e5c36ed73e9611b7b', // 20130221-bsd/amd64/pngout.
905
+ 'bc08e1f883ba92a04e44fe4e756e1afc3b77fc1d072519adff6ce2f7787109bb', // 20130221-bsd-static/i686/pngout-static.
906
+ '860779de32c1fe34f211da036471d6e4ecc0d35527727d476f29623785cf6f82', // 20130221-bsd-static/amd64/pngout-static.
907
+ 'edd8e6173bf3b862c6c40c4b5aad6514169a58ee9b0b34d8c37e475005889592', // 20130221-linux/i686/pngout.
908
+ 'f6a053d1c03b69e2ac4435aaa5b5e13ea5169d9a262286595f9f455d8da5caf1', // 20130221-linux/x86_64/pngout.
909
+ '9591669b3984a19f0aab3a8e8fad98c5274b3c30daecf46b35d22df934546618', // 20130221-linux-static/i686/pngout-static.
910
+ '25d2aab99796c26f1e9cf1f2a9713920be40ce1b99e02c2c50b67fa6e3da06be', // 20130221-linux-static/x86_64/pngout-static.
911
+ '57fd225f3ae921309ee4570f1970629d31cb02946983405d1b1f648aeaab30a1', // 20130221-mac/pngout.
912
+ '3dfeb927e96853d2470350b0a916dc263cd4ebe878b402773dba105a6644e796', // 20150319-bsd/i686/pngout.
913
+ '60a2848c79551a3e79ffcea7f54964767e25bb05c2255b0ea6a1eb03605661d2', // 20150319-bsd/amd64/pngout.
914
+ '52dd45f15221f2ff30739151f30aedb5e3377dd6bccd350d4bce9429d7fa5e8b', // 20150319-bsd-static/i686/pngout-static.
915
+ '12ffa454936e1d35dc96749208d740695fea26d07267b6a17b9890db0f156026', // 20150319-bsd-static/amd64/pngout-static.
916
+ '5b97595c2b4e5f47ba797b105b3b56dbb769437bdc9092f07f6c57bc457ee667', // 20150319-linux/i686/pngout.
917
+ 'a496985d02c785c05f21f653fc4d61a5a171a68f691119448bc3c3152246f0d7', // 20150319-linux/x86_64/pngout.
918
+ 'b6641cb01b684c42e40076b91f98485dd115f6200d3f0baf989f1a4ae43c603a', // 20150319-linux-static/i686/pngout-static.
919
+ '2b8245fe21a648101b8e7399a9dfcc4cf42a39dafa7aab673a7c47901bf82e4a', // 20150319-linux-static/x86_64/pngout-static.
920
+ '12afd90e04387d4c3be985042c1eada89e0c4504f84c0b4739c459c7b3831774', // 20150319-mac/pngout.
921
+ '843f0be42e86680c1663c4ef58eb0677ace15fc29ab23897c83f4b7e5af3ef36', // 20150319-windows/pngout.exe 20150319.
922
+ 'aa3993937455094c0f66ac77d60bf53be441fdf8f14618520c2af68f2253085d', // 20150920-mac/pngout.
923
  // end pngout.
924
+ '8417d5d60bc66442ecc666e31ec7b9e1b7c55f48291e74b4b81f35703e2aef2e', // pngquant-fbsd 2.0.2, EWWW 1.8.3.
925
+ '78668c38d0be70764b18f3f4e0ea2b647df2ae87cedb2216d0ef69c8c55b688a', // pngquant-linux 2.0.2, EWWW 1.8.3.
926
+ '7df1b7f6ed73a189083dd931fb3380d236d34790318f00233b59c8f26f90665f', // pngquant-mac 2.0.2, EWWW 1.8.3.
927
+ '56d2c6212eb595f5eab8a7469e56fa8d3d0e6ffc231aef27742134fba4a39298', // pngquant-sol 2.0.2, EWWW 1.8.3.
928
+ 'd3851c962cd59d74a35174bf3ce71d876dfcd8bdf76f81cd428b2ab7e53c0515', // pngquant.exe 2.0.2, EWWW 1.8.3.
929
+ '0ee6f1dbf4fa168b11ce60860e5700ca0e5125323a43540a78c76644835abc84', // pngquant-fbsd 2.3.0, EWWW 2.0.0.
930
+ '85d8a70930a554f50181a1d061577cf67ef2e76e2cbd5bcb1b7f006064ff1444', // pngquant-linux 2.3.0, EWWW 2.0.0.
931
+ 'a807f769922fdad0ba07307c548df8cf8eeced649d04237d13dfc95757161459', // pngquant-mac 2.3.0, EWWW 2.0.0.
932
+ 'cf2cc40274c438b35e93bd0346c2a6d871bd7a7bdd90c52f4e79f369cb8ded74', // pngquant-sol 2.3.0, EWWW 2.0.0.
933
+ '7454aba77b1a2b63a42d8a5870d3c2d733c7efb2d828643d5e64784af1f65f2a', // pngquant.exe 2.3.0, EWWW 2.0.0.
934
+ '6287f1bb7179c7b6d71a41112222347ed97b6eae4e79b180d7e1e332a4bde3e2', // pngquant-fbsd 2.5.2, EWWW 2.5.4.
935
+ 'fcfe4d3a602e7b491f4126a2707144f5f9cc9359d13f443575d7ea6a74e85ddb', // pngquant-linux 2.5.2, EWWW 2.5.4.
936
+ '35794819a35e949dc0c0d6f90d0bb675791fa9bc3f405eb19f48ea31bb6456a8', // pngquant-mac 2.5.2, EWWW 2.5.4.
937
+ 'c242586c70d83af544334f1846b838ef68c6ab4fc247b2cff9ad4b714f825866', // pngquant-sol 2.5.2, EWWW 2.5.4.
938
+ 'ad79d9b3395d41404b28362972bd68db3c58d5be5f063884df3a595fc38c6a98', // pngquant.exe 2.5.2, EWWW 2.5.4.
939
+ '54d632fc4446d88ad4d1beeaf73420d68d87786f02adc9d3363766cb93ec95a4', // pngquant-fbsd 2.9.1, EWWW 3.4.0.
940
+ '91f704f02468f86766007e46973a1ef9e282d6ccadc54caf339dc537c9b2b61d', // pngquant-linux 2.9.1, EWWW 3.4.0.
941
+ '65dc20f05af588d948fc6f4df37c294f4a3a1c1ad207a8b56d13e6829773165a', // pngquant-mac 2.9.1, EWWW 3.4.0.
942
+ 'dbc9e12d5bb3e806aaf5e2c3d30d122d569069027a633485761cbf072cf2236d', // pngquant-sol 2.9.1, EWWW 3.4.0.
943
+ '84e63e6f9f9630a1a0c3e782609349c12b8df9ea9d02c5a29230819379e56b3c', // pngquant.exe 2.8.1, EWWW 3.4.0.
944
  // end pngquant.
945
+ 'bf0e12f996802dc114a864e5150647ce41089a5a2b5e36c3a270ac848b655c26', // cwebp-fbsd 0.4.1, EWWW 2.0.0.
946
+ '5349646072c3ef5f8b4588bbee8635e882c245439e2d86b863f04b7e27f4fafe', // cwebp-fbsd64 0.4.1, EWWW 2.0.0.
947
+ '3044c02cfef53f4361f7b2db49c5679f894ed346f665d4c8d91c6675d84dbf67', // cwebp-linux6 0.4.1, EWWW 2.0.0.
948
+ 'c9899718a5e272a082fd7c9d93d7c23d8a50f49d1b739a9aa1ef404f78cd7baf', // cwebp-linux664 0.4.1, EWWW 2.0.0.
949
+ '2a0dff5c80fd5fa170babd0c0571f4499606f8d09bf820938da41a311d6dec6f', // cwebp-linux8 0.4.1, EWWW 2.0.0.
950
+ 'c1dfbbad935e31bde2e517dff43911c0651a8e5f78c022a252a864278065ae11', // cwebp-linux864 0.4.1, EWWW 2.0.0.
951
+ 'bae23f1614d391b136e8618a21590e4a9f0614c8716b86a6a7067527e9950d87', // cwebp-mac7 0.4.1, EWWW 2.0.0.
952
+ 'bc72654fead42c6d4fd841cecdee6ccbf21b2407292593ec982f31d39b566955', // cwebp-mac8 0.4.1, EWWW 2.0.0.
953
+ '7fa005dc6a18563e4f6574bec83c92cabf786d8ee845503d80fa52e370dc4903', // cwebp-sol 0.4.1, EWWW 2.0.0.
954
+ '6486779c8e1e9cc7c63ae03c416fc6d5dc7598c58a6cddbe9a41e70d804410f9', // cwebp.exe 0.4.1, EWWW 2.0.0.
955
+ '814a168f190c4712df231b1f7d1910185ef823953b54c9fb8b354f415172a371', // cwebp-fbsd64 0.4.3, EWWW 2.4.4.
956
+ '0f867ea2db0db895612bd15916ad31bc71c89ef2ad74552b7e878df09b843da5', // cwebp-linux6 0.4.3, EWWW 2.4.4.
957
+ '179c7b9a2fbc1af542b3653bff58ca4dcb35bebf346687c12bb667ab49e9e21b', // cwebp-linux664 0.4.3, EWWW 2.4.4.
958
+ '212e59654bbb6147ee8a554bf8eb7b5c11f75b9ef14ac3e6ee92ad726a47339a', // cwebp-linux8 0.4.3, EWWW 2.4.4.
959
+ 'b491509221f7c97e8dcc3bdd6f7fc201f40bc93062618bfba06f84aac7704558', // cwebp-linux864 0.4.3, EWWW 2.4.4.
960
+ '2e8c5f53f44656ec80f11cca3c985200f502c88ea47bb34063e09eb6313e04a6', // cwebp-mac8 0.4.2, EWWW 2.4.4.
961
+ '963a09a2c45ba036291b32ecb665541e40c232bb0f2474810ac2a9ddf8837fe4', // cwebp-mac9 0.4.3, EWWW 2.4.4.
962
+ '2642d98bb75bc2fd2d969ba1d27b8628fd7fa73a7a204ed8f71a65e124abcac0', // cwebp-sol 0.4.3, EWWW 2.4.4.
963
+ '64cd62e33201b0d14ec4823b64d93f92825f2e8f5239726f5b00ed9ff944a581', // cwebp.exe 0.4.3, EWWW 2.4.4.
964
+ '7d7329671d445924dafcaacee7f2db6f4ce33567ffca41aa5b5818ebff806bc5', // cwebp-fbsd64 0.4.4, EWWW 2.5.4.
965
+ 'f1a48031d0ab602080f5646695ce8a3e84d5470f1be99d1b8fc20aded9c7839b', // cwebp-linux6 0.4.4, EWWW 2.5.4.
966
+ 'b2bef90b62d80b35d4c5a41f793454e95e5159bf0aec2e4bd8c19fc3de3556bd', // cwebp-linux664 0.4.4, EWWW 2.5.4.
967
+ 'd3c358524efd50f6e078362733870229ca1e1db8885580b6814c2535b4d20612', // cwebp-linux8 0.4.4, EWWW 2.5.4.
968
+ '271deeec579c252e364495addad03d9c1f3248c2177a01638002b25eee787ded', // cwebp-linux864 0.4.4, EWWW 2.5.4.
969
+ '379e2b95e20dd33f4667c134099df358e178f6a6bf32f3a5b6b78bbb6950b4b5', // cwebp-mac9 0.4.4, EWWW 2.5.4.
970
+ '118ea3f0bcdcce6128d64e34159c93c3324cb038c9e5a51efaf530ea52af7070', // cwebp-sol 0.4.4, EWWW 2.5.4.
971
+ '43941c1d7169e66fb1fd62a1950286b230d3e5bec3bbb14fdb4ac091ca7a0f9f', // cwebp.exe 0.4.4, EWWW 2.5.4.
972
+ '26d5d88dee2993d1d0e16f5e60318cd8adec485614facd6c7f9c22c71eb7b2e5', // cwebp-fbsd 0.5.0 EWWW 2.6.0.
973
+ '60b1738d6502691227a46658cd7656b4a52702680f169e8e04d72077e967aeed', // cwebp-linux 0.5.0, EWWW 2.6.0.
974
+ '276a0221a4c978825903572c2b68b3010399375d6b9dc7429286caf625cae95a', // cwebp-mac9 0.5.0, EWWW 2.6.0.
975
+ 'be3e81ec7267e7878ddd4ee01df1553966952f74bbfd30a5523d12d53f019ecb', // cwebp-sol 0.5.0, EWWW 2.6.0.
976
+ 'b41123ec06f21765f50ec1b017839f99ab4f28497d87da722817a6023e4a3b32', // cwebp.exe 0.5.0, EWWW 2.6.0.
977
+ 'f0547a6219c5c05d0af29c5e411e054b9d795567f4ae2e27893815af9383c60f', // cwebp-fbsd 0.5.1, EWWW 2.9.9.
978
+ '9eaf670bb2d567421c7e2918112dc00406c60f008b120f648cf0bdba73ee9b6b', // cwebp-linux 0.5.1, EWWW 2.9.9.
979
+ '1202ea932b315913d3736460dd3d50bc5b251b7a0a8f0468c63144ba427679c2', // cwebp-mac9 0.5.1, EWWW 2.9.9.
980
+ '27ba0abce52e74744f6235fcde9b153b5052b9c15cd78e74feffaea9dafcc178', // cwebp-sol 0.5.1, EWWW 2.9.9.
981
+ 'b02864989f0a1a263caa796c5b8caf18c1f774ed0ba08a9350e8820459875f51', // cwebp.exe 0.5.1, EWWW 2.9.9.
982
+ 'e5cbea11c97fadffe221fdf57c093c19af2737e4bbd2cb3cd5e908de64286573', // cwebp-fbsd 0.6.0, EWWW 3.4.0.
983
+ '43ca351e8f5d457b898c587151ebe3d8f6cce8dcfb7de44f6cb70148a31a68bc', // cwebp-linux 0.6.0, EWWW 3.4.0.
984
+ 'a06a3ee436e375c89dbc1b0b2e8bd7729a55139ae072ed3f7bd2e07de0ebb379', // cwebp-mac12 0.6.0, EWWW 3.4.0.
985
+ '1febaffbb18e52dc2c524cda9eefd00c6db95bc388732868999c0f48deb73b4f', // cwebp-sol 0.6.0, EWWW 3.4.0.
986
+ '49e9cb98db30bfa27936933e6fd94d407e0386802cb192800d9fd824f6476873', // cwebp.exe 0.6.0, EWWW 3.4.0.
987
  // end cwebp.
988
  );
989
  foreach ( $valid_sums as $checksum ) {
1055
  ewwwio_debug_message( "file command: {$filetype[0]}" );
1056
  // If we've found a proper binary.
1057
  if ( ( strpos( $filetype[0], 'ELF' ) && strpos( $filetype[0], 'executable' ) )
1058
+ || false !== strpos( $filetype[0], 'Mach-O universal binary' )
1059
+ || false !== strpos( $filetype[0], 'Mach-O fat file with' )
1060
+ || false !== strpos( $filetype[0], 'Mach-O 64-bit x86_64 executable' )
1061
  ) {
1062
  $type = 'application/x-executable';
1063
  }
1064
  }
1065
  }
1066
  // If we are dealing with a binary, and found an executable.
1067
+ if ( 'b' === $case && preg_match( '/executable|octet-stream|dosexec|x-mach-binary/', $type ) ) {
1068
  ewwwio_memory( __FUNCTION__ );
1069
  return $type;
1070
  // Otherwise, if we are dealing with an image.
1116
  break;
1117
  case 'jb':
1118
  $upload_dir = wp_upload_dir();
1119
+ $testjpg = trailingslashit( $upload_dir['basedir'] ) . 'testopti.jpg';
1120
  exec( $path . ' -copy none -optimize -outfile ' . ewww_image_optimizer_escapeshellarg( $testjpg ) . ' ' . ewww_image_optimizer_escapeshellarg( EWWW_IMAGE_OPTIMIZER_IMAGES_PATH . 'testorig.jpg' ) );
1121
  $testjpgsize = ewww_image_optimizer_filesize( $testjpg );
1122
  ewwwio_debug_message( "blind testing jpegtran, is $testjpgsize smaller than 5700?" );
1140
  break;
1141
  case 'ob':
1142
  $upload_dir = wp_upload_dir();
1143
+ $testpng = trailingslashit( $upload_dir['basedir'] ) . 'testopti.png';
1144
  exec( $path . ' -out ' . ewww_image_optimizer_escapeshellarg( $testpng ) . ' -o1 -quiet -strip all ' . ewww_image_optimizer_escapeshellarg( EWWW_IMAGE_OPTIMIZER_IMAGES_PATH . 'testorig.png' ) );
1145
  $testpngsize = ewww_image_optimizer_filesize( $testpng );
1146
  ewwwio_debug_message( "blind testing optipng, is $testpngsize smaller than 110?" );
1164
  break;
1165
  case 'gb':
1166
  $upload_dir = wp_upload_dir();
1167
+ $testgif = trailingslashit( $upload_dir['basedir'] ) . 'testopti.gif';
1168
  exec( $path . ' -O3 -o ' . ewww_image_optimizer_escapeshellarg( $testgif ) . ' ' . ewww_image_optimizer_escapeshellarg( EWWW_IMAGE_OPTIMIZER_IMAGES_PATH . 'testorig.gif' ) );
1169
  $testgifsize = ewww_image_optimizer_filesize( $testgif );
1170
  ewwwio_debug_message( "blind testing gifsicle, is $testgifsize smaller than 12000?" );
1188
  break;
1189
  case 'pb':
1190
  $upload_dir = wp_upload_dir();
1191
+ $testpng = trailingslashit( $upload_dir['basedir'] ) . 'testopti.png';
1192
  exec( $path . ' -s3 -q ' . ewww_image_optimizer_escapeshellarg( EWWW_IMAGE_OPTIMIZER_IMAGES_PATH . 'testorig.png' ) . ' ' . ewww_image_optimizer_escapeshellarg( $testpng ) );
1193
  $testpngsize = ewww_image_optimizer_filesize( $testpng );
1194
  ewwwio_debug_message( "blind testing pngout, is $testpngsize smaller than 110?" );
1212
  break;
1213
  case 'qb':
1214
  $upload_dir = wp_upload_dir();
1215
+ $testpng = trailingslashit( $upload_dir['basedir'] ) . 'testopti.png';
1216
  exec( $path . ' -o ' . ewww_image_optimizer_escapeshellarg( $testpng ) . ' ' . ewww_image_optimizer_escapeshellarg( EWWW_IMAGE_OPTIMIZER_IMAGES_PATH . 'testorig.png' ) );
1217
  $testpngsize = ewww_image_optimizer_filesize( $testpng );
1218
  ewwwio_debug_message( "blind testing pngquant, is $testpngsize smaller than 114?" );
1285
  break;
1286
  case 'wb':
1287
  $upload_dir = wp_upload_dir();
1288
+ $testpng = trailingslashit( $upload_dir['basedir'] ) . 'testopti.png';
1289
  exec( $path . ' -lossless -quiet ' . ewww_image_optimizer_escapeshellarg( EWWW_IMAGE_OPTIMIZER_IMAGES_PATH . 'testorig.png' ) . ' -o ' . ewww_image_optimizer_escapeshellarg( $testpng ) );
1290
  $testpngsize = ewww_image_optimizer_filesize( $testpng );
1291
  ewwwio_debug_message( "blind testing cwebp, is $testpngsize smaller than 114?" );
1319
  return '';
1320
  }
1321
  $use_system = ewww_image_optimizer_get_option( 'ewww_image_optimizer_skip_bundle' );
1322
+ $tool_path = trailingslashit( EWWW_IMAGE_OPTIMIZER_TOOL_PATH );
1323
  if ( file_exists( $tool_path . $binary . '.exe' ) && ! $use_system ) {
1324
  $binary_path = $tool_path . $binary . '.exe';
1325
  ewwwio_debug_message( "found $binary_path, testing..." );
1365
  return '';
1366
  }
1367
  $use_system = ewww_image_optimizer_get_option( 'ewww_image_optimizer_skip_bundle' );
1368
+ $tool_path = trailingslashit( EWWW_IMAGE_OPTIMIZER_TOOL_PATH );
1369
  // First check for the binary in the ewww tool folder.
1370
  if ( file_exists( $tool_path . $binary ) && ! $use_system ) {
1371
  $binary_path = $tool_path . $binary;
1544
  $s3_uploads_image = false;
1545
  }
1546
  if ( strpos( $file, 's3' ) === 0 && class_exists( 'S3_Uploads' ) ) {
1547
+ $s3_uploads_image = $file;
1548
  $s3_uploads_instance = S3_Uploads::get_instance();
1549
  $s3_uploads_instance->setup();
1550
  if ( ! function_exists( 'wp_tempnam' ) ) {
1554
  }
1555
  // Initialize the original filename.
1556
  $original = $file;
1557
+ $result = '';
1558
  if ( false === is_file( $file ) ) {
1559
  /* translators: %s: Image filename */
1560
  $msg = sprintf( __( 'Could not find %s', 'ewww-image-optimizer' ), $file );
1621
  $skip = ewww_image_optimizer_skip_tools();
1622
  if ( EWWW_IMAGE_OPTIMIZER_CLOUD ) {
1623
  $skip['jpegtran'] = true;
1624
+ $skip['optipng'] = true;
1625
  $skip['gifsicle'] = true;
1626
+ $skip['pngout'] = true;
1627
  $skip['pngquant'] = true;
1628
+ $skip['webp'] = true;
1629
  }
1630
  if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_skip_full' ) && $fullsize ) {
1631
  $keep_metadata = true;
1658
  rename( $file, $refile );
1659
  ewwwio_debug_message( "moved $file to $refile" );
1660
  // And set $file to the new filename.
1661
+ $file = $refile;
1662
  $original = $file;
1663
  }
1664
  // Get the original image size.
1683
  return array( false, __( 'Optimization skipped', 'ewww-image-optimizer' ), $converted, $file );
1684
  }
1685
  $backup_hash = '';
1686
+ $new_size = 0;
1687
  // Set the optimization process to OFF.
1688
  $optimize = false;
1689
  // Toggle the convert process to ON.
1787
  // Copy all the metadata.
1788
  $copy_opt = 'all';
1789
  }
1790
+ if ( $orig_size > 10240 ) {
1791
  $progressive = '-progressive';
1792
  } else {
1793
  $progressive = '';
1810
  unlink( $progfile );
1811
  }
1812
  // Store the results.
1813
+ $result = 'unchanged';
1814
  $new_size = $orig_size;
1815
  }
1816
  } elseif ( ! $convert ) {
1817
  // If conversion and optimization are both turned OFF, finish the JPG processing.
1818
+ ewww_image_optimizer_webp_create( $file, $orig_size, $type, $tools['CWEBP'] );
1819
  break;
1820
  } // End if().
1821
  // If the conversion process is turned ON, or if this is a resize and the full-size was converted.
1921
  }
1922
  }
1923
  } // End if().
1924
+ ewww_image_optimizer_webp_create( $file, $new_size, $type, $tools['CWEBP'], $orig_size != $new_size );
1925
  break;
1926
  case 'image/png':
1927
  $jpg_size = 0;
1931
  && 1 == $gallery_type && ! $skip_lossy ) {
1932
  ewwwio_debug_message( 'PNG to JPG conversion turned on' );
1933
  $cloud_background = '';
1934
+ $r = '';
1935
+ $g = '';
1936
+ $b = '';
1937
  // If the user set a fill background for transparency.
1938
  $background = ewww_image_optimizer_jpg_background();
1939
  if ( $background ) {
1967
  } else {
1968
  ewwwio_debug_message( 'PNG to JPG conversion turned off' );
1969
  // Turn the conversion process OFF.
1970
+ $convert = false;
1971
+ $jpgfile = '';
1972
+ $r = null;
1973
+ $g = null;
1974
+ $b = null;
1975
  $cloud_background = '';
1976
+ $gquality = null;
1977
  } // End if().
1978
  // Check for previous optimization, so long as the force flag is on and this isn't a new image that needs converting.
1979
  if ( empty( $_REQUEST['ewww_force'] ) && ! ( $new && $convert ) ) {
2099
  unlink( $tempfile );
2100
  }
2101
  // Store the results.
2102
+ $result = 'unchanged';
2103
  $new_size = $orig_size;
2104
  }
2105
  } elseif ( ! $convert ) {
2106
  // If conversion and optimization are both disabled we are done here.
2107
  ewwwio_debug_message( 'calling webp, but neither convert or optimize' );
2108
+ ewww_image_optimizer_webp_create( $file, $orig_size, $type, $tools['CWEBP'] );
2109
  break;
2110
  } // End if().
2111
  // Retrieve the new filesize of the PNG.
2130
  try {
2131
  if ( ewww_image_optimizer_png_alpha( $file ) ) {
2132
  $gmagick_overlay = new Gmagick( $file );
2133
+ $gmagick = new Gmagick();
2134
  $gmagick->newimage( $gmagick_overlay->getimagewidth(), $gmagick_overlay->getimageheight(), '#' . $magick_background );
2135
  $gmagick->compositeimage( $gmagick_overlay, 1, 0, 0 );
2136
  } else {
2199
  // Copy all the metadata.
2200
  $copy_opt = 'all';
2201
  }
2202
+ if ( $jpg_size > 10240 ) {
2203
  $progressive = '-progressive';
2204
  } else {
2205
  $progressive = '';
2244
  }
2245
  }
2246
  } // End if().
2247
+ ewww_image_optimizer_webp_create( $file, $new_size, $type, $tools['CWEBP'], $orig_size != $new_size );
2248
  break;
2249
  case 'image/gif':
2250
  // If gif2png is turned on, and the image is in the WordPress media library.
2340
  unlink( $tempfile );
2341
  }
2342
  // Store the results.
2343
+ $result = 'unchanged';
2344
  $new_size = $orig_size;
2345
  }
2346
  } elseif ( ! $convert ) {
2395
  // Let webp know what we're dealing with now.
2396
  $type = 'image/png';
2397
  // Normally this would be at the end of the section, but we only want to do webp if the image was successfully converted to a png.
2398
+ ewww_image_optimizer_webp_create( $file, $new_size, $type, $tools['CWEBP'], $orig_size != $new_size );
2399
  // Successful conversion, so we store the increment.
2400
  $converted = $filenum;
2401
  } else {
2443
  }
2444
  if ( ! empty( $new_size ) ) {
2445
  // Set correct file permissions.
2446
+ $stat = stat( dirname( $file ) );
2447
  $perms = $stat['mode'] & 0000666; // Same permissions as parent folder, strip off the executable bits.
2448
  chmod( $file, $perms );
2449
 
2477
  function ewww_image_optimizer_webp_create( $file, $orig_size, $type, $tool, $recreate = false ) {
2478
  ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
2479
  // Change the file extension.
2480
+ $webpfile = $file . '.webp';
2481
+ $bypass_webp = apply_filters( 'ewww_image_optimizer_bypass_webp', false, $file );
2482
+ if ( true === $bypass_webp ) {
2483
+ ewwwio_debug_message( "webp generation bypassed: $file" );
2484
+ return;
2485
+ } elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) ) {
2486
  return;
2487
  } elseif ( is_file( $webpfile ) && empty( $_REQUEST['ewww_force'] ) && ! $recreate ) {
2488
  ewwwio_debug_message( 'webp file exists, not forcing or recreating' );
2518
  unlink( $webpfile );
2519
  } elseif ( is_file( $webpfile ) ) {
2520
  // Set correct file permissions.
2521
+ $stat = stat( dirname( $webpfile ) );
2522
  $perms = $stat['mode'] & 0000666; // Same permissions as parent folder, strip off the executable bits.
2523
  chmod( $webpfile, $perms );
2524
  }
2558
  if ( PHP_OS == 'FreeBSD' ) {
2559
  $os_string = 'bsd';
2560
  }
2561
+ $latest = '20150319';
2562
  $tool_path = trailingslashit( EWWW_IMAGE_OPTIMIZER_TOOL_PATH );
2563
  if ( empty( $pngout_error ) ) {
2564
  if ( PHP_OS == 'Linux' || PHP_OS == 'FreeBSD' ) {
2629
  $sendback = add_query_arg(
2630
  array(
2631
  'ewww_pngout' => 'failed',
2632
+ 'ewww_error' => urlencode( $pngout_error ),
2633
  ),
2634
  remove_query_arg( array( 'ewww_pngout', 'ewww_error' ), wp_get_referer() )
2635
  );
vendor/pel/AUTHORS ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ AUTHORS file for PEL: PHP Exif Library. A library with support for
2
+ reading and writing Exif headers in JPEG and TIFF images using PHP.
3
+
4
+ Copyright (C) 2004, 2005, 2006, 2007 Martin Geisler.
5
+ Copyright (c) 2008, 2009 Lars Olesen
6
+ Copyright (c) 2015 Johannes Weberhofer
7
+ Licensed under the GNU GPL, see COPYING for details.
8
+
9
+
10
+ Credits
11
+ *******
12
+
13
+ PEL is written by Martin Geisler <mgeisler@users.sourceforge.net> and
14
+ is now maintained by Lars Olesen <lars@intraface.dk>
15
+ and <jweberhofer@weberhofer.at>
16
+
17
+ The source started out as a port of the nice, clean C code found in
18
+ libexif. Most of the translations included with PEL also originates
19
+ from the libexif project, see below for details.
20
+
21
+
22
+ Test Image Contributors
23
+ ***********************
24
+
25
+ Bernhard Bittel: Nikon E950 and E5000 test images.
26
+
27
+ Stéphanie Bittel: Canon IXUS II test image.
28
+
29
+ Lars Geisler: Nikon Coolscan IV ED test image.
30
+
31
+ Mikkel Krøigård: Canon PowerShot S60 test image.
32
+
33
+ Paul Mitchum: Pentax *ist DS and Olympus C-5050z test images.
34
+
35
+ Lisbeth Nygaard Pedersen: Leica D-LUX test image.
36
+
37
+ Thomas B. Pedersen: Olympus C-50z and C-765z test images.
38
+
39
+
40
+ Translators
41
+ ***********
42
+
43
+ Danish: Martin Geisler.
44
+
45
+ French: Arnaud Launay (for libexif) and David Lesieur.
46
+
47
+ German: Hans Ulrich Niedermann, Lutz Möller (for libexif).
48
+
49
+ Japanese: Tadashi Jokagi.
50
+
51
+ Polish: Jakub Bogusz (for libexif).
52
+
53
+ Spanish: Fabian Mandelbaum (for libexif).
vendor/pel/src/PelCanonMakerNotes.php ADDED
@@ -0,0 +1,336 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * PEL: PHP Exif Library.
4
+ * A library with support for reading and
5
+ * writing all Exif headers in JPEG and TIFF images using PHP.
6
+ *
7
+ * Copyright (C) 2004, 2005 Martin Geisler.
8
+ * Copyright (C) 2017 Johannes Weberhofer.
9
+ *
10
+ * This program is free software; you can redistribute it and/or modify
11
+ * it under the terms of the GNU General Public License as published by
12
+ * the Free Software Foundation; either version 2 of the License, or
13
+ * (at your option) any later version.
14
+ *
15
+ * This program is distributed in the hope that it will be useful,
16
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
+ * GNU General Public License for more details.
19
+ *
20
+ * You should have received a copy of the GNU General Public License
21
+ * along with this program in the file COPYING; if not, write to the
22
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
23
+ * Boston, MA 02110-1301 USA
24
+ */
25
+ namespace lsolesen\pel;
26
+
27
+ /**
28
+ * Namespace for functions operating on Exif formats.
29
+ *
30
+ * This class defines the constants that are to be used whenever one
31
+ * has to refer to the format of an Exif tag. They will be
32
+ * collectively denoted by the pseudo-type PelFormat throughout the
33
+ * documentation.
34
+ *
35
+ * All the methods defined here are static, and they all operate on a
36
+ * single argument which should be one of the class constants.
37
+ *
38
+ * @author Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com>
39
+ * @author Thanks to Benedikt Rosenkranz <beluro@web.de>
40
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
41
+ * License (GPL)
42
+ * @package
43
+ *
44
+ */
45
+ class PelCanonMakerNotes extends PelMakerNotes
46
+ {
47
+ private $undefinedMakerNotesTags = array(
48
+ 0x0000,
49
+ 0x0003,
50
+ 0x000a,
51
+ 0x000e,
52
+ 0x0011,
53
+ 0x0014,
54
+ 0x0016,
55
+ 0x0017,
56
+ 0x0018,
57
+ 0x0019,
58
+ 0x001b,
59
+ 0x001c,
60
+ 0x001d,
61
+ 0x001f,
62
+ 0x0020,
63
+ 0x0021,
64
+ 0x0022,
65
+ 0x0023,
66
+ 0x0024,
67
+ 0x0025,
68
+ 0x0031,
69
+ 0x0035,
70
+ 0x0098,
71
+ 0x009a,
72
+ 0x00b5,
73
+ 0x00c0,
74
+ 0x00c1,
75
+ 0x4008,
76
+ 0x4009,
77
+ 0x4010,
78
+ 0x4011,
79
+ 0x4012,
80
+ 0x4013,
81
+ 0x4015,
82
+ 0x4016,
83
+ 0x4018,
84
+ 0x4019,
85
+ 0x4020,
86
+ 0x4025,
87
+ 0x4027
88
+ );
89
+
90
+ private $undefinedCameraSettingsTags = array(
91
+ 0x0006,
92
+ 0x0008,
93
+ 0x0015,
94
+ 0x001e,
95
+ 0x001f,
96
+ 0x0026,
97
+ 0x002b,
98
+ 0x002c,
99
+ 0x002d,
100
+ 0x002f,
101
+ 0x0030,
102
+ 0x0031
103
+ );
104
+
105
+ private $undefinedShotInfoTags = array(
106
+ 0x0001,
107
+ 0x0006,
108
+ 0x000a,
109
+ 0x000b,
110
+ 0x000c,
111
+ 0x000d,
112
+ 0x0011,
113
+ 0x0012,
114
+ 0x0014,
115
+ 0x0018,
116
+ 0x0019,
117
+ 0x001d,
118
+ 0x001e,
119
+ 0x001f,
120
+ 0x0020,
121
+ 0x0021,
122
+ 0x0022
123
+ );
124
+
125
+ private $undefinedPanoramaTags = array(
126
+ 0x0001,
127
+ 0x0003,
128
+ 0x0004
129
+ );
130
+
131
+ private $undefinedPicInfoTags = array(
132
+ 0x0001,
133
+ 0x0006,
134
+ 0x0007,
135
+ 0x0008,
136
+ 0x0009,
137
+ 0x000a,
138
+ 0x000b,
139
+ 0x000c,
140
+ 0x000d,
141
+ 0x000e,
142
+ 0x000f,
143
+ 0x0010,
144
+ 0x0011,
145
+ 0x0012,
146
+ 0x0013,
147
+ 0x0014,
148
+ 0x0015,
149
+ 0x0017,
150
+ 0x0018,
151
+ 0x0019,
152
+ 0x001b,
153
+ 0x001c
154
+ );
155
+
156
+ private $undefinedFileInfoTags = array(
157
+ 0x0002,
158
+ 0x000a,
159
+ 0x000b,
160
+ 0x0011,
161
+ 0x0012,
162
+ 0x0016,
163
+ 0x0017,
164
+ 0x0018,
165
+ 0x001a,
166
+ 0x001b,
167
+ 0x001c,
168
+ 0x001d,
169
+ 0x001e,
170
+ 0x001f,
171
+ 0x0020
172
+ );
173
+
174
+ public function __construct($parent, $data, $size, $offset)
175
+ {
176
+ parent::__construct($parent, $data, $size, $offset);
177
+ $this->type = PelIfd::CANON_MAKER_NOTES;
178
+ }
179
+
180
+ public function load()
181
+ {
182
+ $this->components = $this->data->getShort($this->offset);
183
+ $this->offset += 2;
184
+ Pel::debug('Loading %d components in maker notes.', $this->components);
185
+ $mkNotesIfd = new PelIfd(PelIfd::CANON_MAKER_NOTES);
186
+
187
+ for ($i = 0; $i < $this->components; $i++) {
188
+ $tag = $this->data->getShort($this->offset + 12 * $i);
189
+ $type = $this->data->getShort($this->offset + 12 * $i + 2);
190
+ $components = $this->data->getLong($this->offset + 12 * $i + 4);
191
+ $data = $this->data->getLong($this->offset + 12 * $i + 8);
192
+ // check if tag is defined
193
+ if (in_array($tag, $this->undefinedMakerNotesTags)) {
194
+ continue;
195
+ }
196
+ switch ($tag) {
197
+ case PelTag::CANON_CAMERA_SETTINGS:
198
+ $this->parseCameraSettings($mkNotesIfd, $this->data, $data, $components);
199
+ break;
200
+ case PelTag::CANON_SHOT_INFO:
201
+ $this->parseShotInfo($mkNotesIfd, $this->data, $data, $components);
202
+ break;
203
+ case PelTag::CANON_PANORAMA:
204
+ $this->parsePanorama($mkNotesIfd, $this->data, $data, $components);
205
+ break;
206
+ case PelTag::CANON_PICTURE_INFO:
207
+ // $this->parsePictureInfo($mkNotesIfd, $this->data, $data, $components);
208
+ break;
209
+ case PelTag::CANON_FILE_INFO:
210
+ $this->parseFileInfo($mkNotesIfd, $this->data, $data, $components);
211
+ break;
212
+ case PelTag::CANON_CUSTOM_FUNCTIONS:
213
+ //TODO
214
+ default:
215
+ $mkNotesIfd->loadSingleValue($this->data, $this->offset, $i, $tag);
216
+ break;
217
+ }
218
+ }
219
+ $this->parent->addSubIfd($mkNotesIfd);
220
+ }
221
+
222
+ private function parseCameraSettings($parent, $data, $offset, $components)
223
+ {
224
+ $type = PelIfd::CANON_CAMERA_SETTINGS;
225
+ Pel::debug('Found Canon Camera Settings sub IFD at offset %d', $offset);
226
+ $size = $data->getShort($offset);
227
+ $offset += 2;
228
+ $elemSize = PelFormat::getSize(PelFormat::SSHORT);
229
+ if ($size / $components !== $elemSize) {
230
+ throw new PelMakerNotesMalformedException('Size of Canon Camera Settings does not match the number of entries.');
231
+ }
232
+ $camIfd = new PelIfd($type);
233
+
234
+ for ($i=0; $i<$components; $i++) {
235
+ // check if tag is defined
236
+ if (in_array($i+1, $this->undefinedCameraSettingsTags)) {
237
+ continue;
238
+ }
239
+ $camIfd->loadSingleMakerNotesValue($type, $data, $offset, $size, $i, PelFormat::SSHORT);
240
+ }
241
+ $parent->addSubIfd($camIfd);
242
+ }
243
+
244
+ private function parseShotInfo($parent, $data, $offset, $components)
245
+ {
246
+ $type = PelIfd::CANON_SHOT_INFO;
247
+ Pel::debug('Found Canon Shot Info sub IFD at offset %d', $offset);
248
+ $size = $data->getShort($offset);
249
+ $offset += 2;
250
+ $elemSize = PelFormat::getSize(PelFormat::SHORT);
251
+ if ($size / $components !== $elemSize) {
252
+ throw new PelMakerNotesMalformedException('Size of Canon Shot Info does not match the number of entries.');
253
+ }
254
+ $shotIfd = new PelIfd($type);
255
+
256
+ for ($i=0; $i<$components; $i++) {
257
+ // check if tag is defined
258
+ if (in_array($i+1, $this->undefinedShotInfoTags)) {
259
+ continue;
260
+ }
261
+ $shotIfd->loadSingleMakerNotesValue($type, $data, $offset, $size, $i, PelFormat::SHORT);
262
+ }
263
+ $parent->addSubIfd($shotIfd);
264
+ }
265
+
266
+ private function parsePanorama($parent, $data, $offset, $components)
267
+ {
268
+ $type = PelIfd::CANON_PANORAMA;
269
+ Pel::debug('Found Canon Panorama sub IFD at offset %d', $offset);
270
+ $size = $data->getShort($offset);
271
+ $offset += 2;
272
+ $elemSize = PelFormat::getSize(PelFormat::SHORT);
273
+ if ($size / $components !== $elemSize) {
274
+ throw new PelMakerNotesMalformedException('Size of Canon Panorama does not match the number of entries.');
275
+ }
276
+ $panoramaIfd = new PelIfd($type);
277
+
278
+ for ($i=0; $i<$components; $i++) {
279
+ // check if tag is defined
280
+ if (in_array($i+1, $this->undefinedPanoramaTags)) {
281
+ continue;
282
+ }
283
+ $panoramaIfd->loadSingleMakerNotesValue($type, $data, $offset, $size, $i, PelFormat::SHORT);
284
+ }
285
+ $parent->addSubIfd($panoramaIfd);
286
+ }
287
+
288
+ private function parsePictureInfo($parent, $data, $offset, $components)
289
+ {
290
+ $type = PelIfd::CANON_PICTURE_INFO;
291
+ Pel::debug('Found Canon Picture Info sub IFD at offset %d', $offset);
292
+ $size = $data->getShort($offset);
293
+ $offset += 2;
294
+ $elemSize = PelFormat::getSize(PelFormat::SHORT);
295
+ if ($size / $components !== $elemSize) {
296
+ throw new PelMakerNotesMalformedException('Size of Canon Picture Info does not match the number of entries. ' . $size . '/' . $components . ' = ' . $elemSize);
297
+ }
298
+ $picIfd = new PelIfd($type);
299
+
300
+ for ($i=0; $i<$components; $i++) {
301
+ // check if tag is defined
302
+ printf("Current Tag: %d\n", ($i+1));
303
+ if (in_array($i+1, $this->undefinedPicInfoTags)) {
304
+ continue;
305
+ }
306
+ $picIfd->loadSingleMakerNotesValue($type, $data, $offset, $size, $i, PelFormat::SHORT);
307
+ }
308
+ $parent->addSubIfd($picIfd);
309
+ }
310
+
311
+ private function parseFileInfo($parent, $data, $offset, $components)
312
+ {
313
+ $type = PelIfd::CANON_FILE_INFO;
314
+ Pel::debug('Found Canon File Info sub IFD at offset %d', $offset);
315
+ $size = $data->getShort($offset);
316
+ $offset += 2;
317
+ $elemSize = PelFormat::getSize(PelFormat::SSHORT);
318
+ if ($size === $elemSize*($components-1) + PelFormat::getSize(PelFormat::LONG)) {
319
+ throw new PelMakerNotesMalformedException('Size of Canon File Info does not match the number of entries.');
320
+ }
321
+ $fileIfd = new PelIfd($type);
322
+
323
+ for ($i=0; $i<$components; $i++) {
324
+ // check if tag is defined
325
+ if (in_array($i+1, $this->undefinedFileInfoTags)) {
326
+ continue;
327
+ }
328
+ $format = PelFormat::SSHORT;
329
+ if ($i + 1 == PelTag::CANON_FI_FILE_NUMBER) {
330
+ $format = PelFormat::LONG;
331
+ }
332
+ $fileIfd->loadSingleMakerNotesValue($type, $data, $offset, $size, $i, $format);
333
+ }
334
+ $parent->addSubIfd($fileIfd);
335
+ }
336
+ }
vendor/pel/src/PelConvert.php CHANGED
@@ -79,7 +79,7 @@ class PelConvert
79
  * the unsigned short that will be converted. The lower
80
  * two bytes will be extracted regardless of the actual size passed.
81
  *
82
- * @param integer $endian
83
  * one of {@link LITTLE_ENDIAN} and {@link
84
  * BIG_ENDIAN}.
85
  *
@@ -101,7 +101,7 @@ class PelConvert
101
  * the signed short that will be converted. The lower
102
  * two bytes will be extracted regardless of the actual size passed.
103
  *
104
- * @param integer $endian
105
  * one of {@link LITTLE_ENDIAN} and {@link
106
  * BIG_ENDIAN}.
107
  *
@@ -131,7 +131,7 @@ class PelConvert
131
  * unsigned integer means that the absolute value will be used. Use
132
  * {@link sLongToBytes} to convert signed integers.
133
  *
134
- * @param integer $endian
135
  * one of {@link LITTLE_ENDIAN} and {@link
136
  * BIG_ENDIAN}.
137
  *
@@ -164,7 +164,7 @@ class PelConvert
164
  * will be treated as a signed 32 bit integer, from which the lower
165
  * four bytes will be extracted.
166
  *
167
- * @param integer $endian
168
  * one of {@link LITTLE_ENDIAN} and {@link
169
  * BIG_ENDIAN}.
170
  *
@@ -238,7 +238,7 @@ class PelConvert
238
  * the offset. The short found at the offset will be
239
  * returned as an integer. There must be at least two bytes
240
  * available beginning at the offset given.
241
- * @param integer $endian
242
  * one of {@link LITTLE_ENDIAN} and {@link
243
  * BIG_ENDIAN}.
244
  * @return integer the unsigned short found at offset, e.g., an integer
@@ -263,7 +263,7 @@ class PelConvert
263
  * The short found at offset will be returned
264
  * as an integer. There must be at least two bytes available
265
  * beginning at the offset given.
266
- * @param integer $endian
267
  * one of {@link LITTLE_ENDIAN} and {@link
268
  * BIG_ENDIAN}.
269
  * @return integer the signed byte found at offset, e.g., an integer in
@@ -289,7 +289,7 @@ class PelConvert
289
  * The long found at offset will be returned
290
  * as an integer. There must be at least four bytes available
291
  * beginning at the offset given.
292
- * @param integer $endian
293
  * one of {@link LITTLE_ENDIAN} and {@link
294
  * BIG_ENDIAN}.
295
  * @return integer the unsigned long found at offset, e.g., an integer
@@ -316,7 +316,7 @@ class PelConvert
316
  * The long found at offset will be returned
317
  * as an integer. There must be at least four bytes available
318
  * beginning at the offset given.
319
- * @param integer $endian
320
  * one of {@link LITTLE_ENDIAN} and {@link
321
  * BIG_ENDIAN}. *
322
  * @return integer the signed long found at offset, e.g., an integer in
@@ -342,7 +342,7 @@ class PelConvert
342
  * The rational found at offset will be
343
  * returned as an array. There must be at least eight bytes
344
  * available beginning at the offset given.
345
- * @param integer $endian
346
  * one of {@link LITTLE_ENDIAN} and {@link
347
  * BIG_ENDIAN}. *
348
  * @return array the unsigned rational found at offset, e.g., an
@@ -366,7 +366,7 @@ class PelConvert
366
  * The rational found at offset will be
367
  * returned as an array. There must be at least eight bytes
368
  * available beginning at the offset given.
369
- * @param integer $endian
370
  * one of {@link LITTLE_ENDIAN} and {@link
371
  * BIG_ENDIAN}.
372
  * @return array the signed rational found at offset, e.g., an array
79
  * the unsigned short that will be converted. The lower
80
  * two bytes will be extracted regardless of the actual size passed.
81
  *
82
+ * @param boolean $endian
83
  * one of {@link LITTLE_ENDIAN} and {@link
84
  * BIG_ENDIAN}.
85
  *
101
  * the signed short that will be converted. The lower
102
  * two bytes will be extracted regardless of the actual size passed.
103
  *
104
+ * @param boolean $endian
105
  * one of {@link LITTLE_ENDIAN} and {@link
106
  * BIG_ENDIAN}.
107
  *
131
  * unsigned integer means that the absolute value will be used. Use
132
  * {@link sLongToBytes} to convert signed integers.
133
  *
134
+ * @param boolean $endian
135
  * one of {@link LITTLE_ENDIAN} and {@link
136
  * BIG_ENDIAN}.
137
  *
164
  * will be treated as a signed 32 bit integer, from which the lower
165
  * four bytes will be extracted.
166
  *
167
+ * @param boolean $endian
168
  * one of {@link LITTLE_ENDIAN} and {@link
169
  * BIG_ENDIAN}.
170
  *
238
  * the offset. The short found at the offset will be
239
  * returned as an integer. There must be at least two bytes
240
  * available beginning at the offset given.
241
+ * @param boolean $endian
242
  * one of {@link LITTLE_ENDIAN} and {@link
243
  * BIG_ENDIAN}.
244
  * @return integer the unsigned short found at offset, e.g., an integer
263
  * The short found at offset will be returned
264
  * as an integer. There must be at least two bytes available
265
  * beginning at the offset given.
266
+ * @param boolean $endian
267
  * one of {@link LITTLE_ENDIAN} and {@link
268
  * BIG_ENDIAN}.
269
  * @return integer the signed byte found at offset, e.g., an integer in
289
  * The long found at offset will be returned
290
  * as an integer. There must be at least four bytes available
291
  * beginning at the offset given.
292
+ * @param boolean $endian
293
  * one of {@link LITTLE_ENDIAN} and {@link
294
  * BIG_ENDIAN}.
295
  * @return integer the unsigned long found at offset, e.g., an integer
316
  * The long found at offset will be returned
317
  * as an integer. There must be at least four bytes available
318
  * beginning at the offset given.
319
+ * @param boolean $endian
320
  * one of {@link LITTLE_ENDIAN} and {@link
321
  * BIG_ENDIAN}. *
322
  * @return integer the signed long found at offset, e.g., an integer in
342
  * The rational found at offset will be
343
  * returned as an array. There must be at least eight bytes
344
  * available beginning at the offset given.
345
+ * @param boolean $endian
346
  * one of {@link LITTLE_ENDIAN} and {@link
347
  * BIG_ENDIAN}. *
348
  * @return array the unsigned rational found at offset, e.g., an
366
  * The rational found at offset will be
367
  * returned as an array. There must be at least eight bytes
368
  * available beginning at the offset given.
369
+ * @param boolean $endian
370
  * one of {@link LITTLE_ENDIAN} and {@link
371
  * BIG_ENDIAN}.
372
  * @return array the signed rational found at offset, e.g., an array
vendor/pel/src/PelDataWindow.php CHANGED
@@ -48,7 +48,7 @@ class PelDataWindow
48
  * example the {@link getShort} function. It must be one of {@link
49
  * PelConvert::LITTLE_ENDIAN} and {@link PelConvert::BIG_ENDIAN}.
50
  *
51
- * @var PelByteOrder
52
  * @see setByteOrder, getByteOrder
53
  */
54
  private $order;
@@ -130,7 +130,7 @@ class PelDataWindow
130
  /**
131
  * Change the byte order of the data.
132
  *
133
- * @param integer $order
134
  * the new byte order. This must be either
135
  * {@link PelConvert::LITTLE_ENDIAN} or {@link
136
  * PelConvert::BIG_ENDIAN}.
@@ -143,7 +143,7 @@ class PelDataWindow
143
  /**
144
  * Get the currently used byte order.
145
  *
146
- * @return integer this will be either {@link
147
  * PelConvert::LITTLE_ENDIAN} or {@link PelConvert::BIG_ENDIAN}.
148
  */
149
  public function getByteOrder()
48
  * example the {@link getShort} function. It must be one of {@link
49
  * PelConvert::LITTLE_ENDIAN} and {@link PelConvert::BIG_ENDIAN}.
50
  *
51
+ * @var boolean
52
  * @see setByteOrder, getByteOrder
53
  */
54
  private $order;
130
  /**
131
  * Change the byte order of the data.
132
  *
133
+ * @param boolean $order
134
  * the new byte order. This must be either
135
  * {@link PelConvert::LITTLE_ENDIAN} or {@link
136
  * PelConvert::BIG_ENDIAN}.
143
  /**
144
  * Get the currently used byte order.
145
  *
146
+ * @return boolean this will be either {@link
147
  * PelConvert::LITTLE_ENDIAN} or {@link PelConvert::BIG_ENDIAN}.
148
  */
149
  public function getByteOrder()
vendor/pel/src/PelEntry.php CHANGED
@@ -92,14 +92,14 @@ abstract class PelEntry
92
  /**
93
  * The {@link PelTag} of this entry.
94
  *
95
- * @var PelTag
96
  */
97
  protected $tag;
98
 
99
  /**
100
  * The {@link PelFormat} of this entry.
101
  *
102
- * @var PelFormat
103
  */
104
  protected $format;
105
 
@@ -113,7 +113,7 @@ abstract class PelEntry
113
  /**
114
  * Return the tag of this entry.
115
  *
116
- * @return PelTag the tag of this entry.
117
  */
118
  public function getTag()
119
  {
@@ -153,7 +153,7 @@ abstract class PelEntry
153
  /**
154
  * Return the format of this entry.
155
  *
156
- * @return PelFormat the format of this entry.
157
  */
158
  public function getFormat()
159
  {
92
  /**
93
  * The {@link PelTag} of this entry.
94
  *
95
+ * @var int
96
  */
97
  protected $tag;
98
 
99
  /**
100
  * The {@link PelFormat} of this entry.
101
  *
102
+ * @var int
103
  */
104
  protected $format;
105
 
113
  /**
114
  * Return the tag of this entry.
115
  *
116
+ * @return int the tag of this entry.
117
  */
118
  public function getTag()
119
  {
153
  /**
154
  * Return the format of this entry.
155
  *
156
+ * @return int the format of this entry.
157
  */
158
  public function getFormat()
159
  {
vendor/pel/src/PelEntryByte.php CHANGED
@@ -56,7 +56,7 @@ class PelEntryByte extends PelEntryNumber
56
  * getValue} method will always return an array except for when a
57
  * single integer argument is given here.
58
  *
59
- * @param PelTag $tag
60
  * the tag which this entry represents. This
61
  * should be one of the constants defined in {@link PelTag}
62
  * which has format {@link PelFormat::BYTE}.
56
  * getValue} method will always return an array except for when a
57
  * single integer argument is given here.
58
  *
59
+ * @param int $tag
60
  * the tag which this entry represents. This
61
  * should be one of the constants defined in {@link PelTag}
62
  * which has format {@link PelFormat::BYTE}.
vendor/pel/src/PelEntryException.php CHANGED
@@ -59,7 +59,7 @@ class PelEntryException extends PelException
59
  /**
60
  * The tag of the entry (if known).
61
  *
62
- * @var PelTag
63
  */
64
  protected $tag;
65
 
@@ -78,7 +78,7 @@ class PelEntryException extends PelException
78
  /**
79
  * Get the tag associated with the exception.
80
  *
81
- * @return PelTag the tag. If no tag is set, null is returned.
82
  */
83
  public function getTag()
84
  {
59
  /**
60
  * The tag of the entry (if known).
61
  *
62
+ * @var int
63
  */
64
  protected $tag;
65
 
78
  /**
79
  * Get the tag associated with the exception.
80
  *
81
+ * @return int the tag. If no tag is set, null is returned.
82
  */
83
  public function getTag()
84
  {
vendor/pel/src/PelEntryLong.php CHANGED
@@ -74,7 +74,7 @@ class PelEntryLong extends PelEntryNumber
74
  * extracted.
75
  *
76
  * @param
77
- * PelTag the tag which this entry represents. This
78
  * should be one of the constants defined in {@link PelTag},
79
  * e.g., {@link PelTag::IMAGE_WIDTH}, or any other tag which can
80
  * have format {@link PelFormat::LONG}.
74
  * extracted.
75
  *
76
  * @param
77
+ * int the tag which this entry represents. This
78
  * should be one of the constants defined in {@link PelTag},
79
  * e.g., {@link PelTag::IMAGE_WIDTH}, or any other tag which can
80
  * have format {@link PelFormat::LONG}.
vendor/pel/src/PelEntryRational.php CHANGED
@@ -65,7 +65,7 @@ class PelEntryRational extends PelEntryLong
65
  * Make a new entry that can hold an unsigned rational.
66
  *
67
  * @param
68
- * PelTag the tag which this entry represents. This should
69
  * be one of the constants defined in {@link PelTag}, e.g., {@link
70
  * PelTag::X_RESOLUTION}, or any other tag which can have format
71
  * {@link PelFormat::RATIONAL}.
65
  * Make a new entry that can hold an unsigned rational.
66
  *
67
  * @param
68
+ * int the tag which this entry represents. This should
69
  * be one of the constants defined in {@link PelTag}, e.g., {@link
70
  * PelTag::X_RESOLUTION}, or any other tag which can have format
71
  * {@link PelFormat::RATIONAL}.
vendor/pel/src/PelEntrySByte.php CHANGED
@@ -56,7 +56,7 @@ class PelEntrySByte extends PelEntryNumber
56
  * method will always return an array except for when a single
57
  * integer argument is given here.
58
  *
59
- * @param PelTag $tag
60
  * the tag which this entry represents. This
61
  * should be one of the constants defined in {@link PelTag}
62
  * which has format {@link PelFormat::BYTE}.
56
  * method will always return an array except for when a single
57
  * integer argument is given here.
58
  *
59
+ * @param int $tag
60
  * the tag which this entry represents. This
61
  * should be one of the constants defined in {@link PelTag}
62
  * which has format {@link PelFormat::BYTE}.
vendor/pel/src/PelEntrySLong.php CHANGED
@@ -56,7 +56,7 @@ class PelEntrySLong extends PelEntryNumber
56
  * single integer is given.
57
  *
58
  * @param
59
- * PelTag the tag which this entry represents. This
60
  * should be one of the constants defined in {@link PelTag}
61
  * which have format {@link PelFormat::SLONG}.
62
  *
56
  * single integer is given.
57
  *
58
  * @param
59
+ * int the tag which this entry represents. This
60
  * should be one of the constants defined in {@link PelTag}
61
  * which have format {@link PelFormat::SLONG}.
62
  *
vendor/pel/src/PelEntrySRational.php CHANGED
@@ -55,7 +55,7 @@ class PelEntrySRational extends PelEntrySLong
55
  * Make a new entry that can hold a signed rational.
56
  *
57
  * @param
58
- * PelTag the tag which this entry represents. This should
59
  * be one of the constants defined in {@link PelTag}, e.g., {@link
60
  * PelTag::SHUTTER_SPEED_VALUE}, or any other tag which can have
61
  * format {@link PelFormat::SRATIONAL}.
55
  * Make a new entry that can hold a signed rational.
56
  *
57
  * @param
58
+ * int the tag which this entry represents. This should
59
  * be one of the constants defined in {@link PelTag}, e.g., {@link
60
  * PelTag::SHUTTER_SPEED_VALUE}, or any other tag which can have
61
  * format {@link PelFormat::SRATIONAL}.
vendor/pel/src/PelEntrySShort.php CHANGED
@@ -53,7 +53,7 @@ class PelEntrySShort extends PelEntryNumber
53
  * getValue} method will always return an array except for when a
54
  * single integer argument is given here.
55
  *
56
- * @param PelTag $tag
57
  * the tag which this entry represents. This
58
  * should be one of the constants defined in {@link PelTag}
59
  * which has format {@link PelFormat::SSHORT}.
@@ -84,7 +84,7 @@ class PelEntrySShort extends PelEntryNumber
84
  * @param int $number
85
  * the number that should be converted.
86
  *
87
- * @param PelByteOrder $order
88
  * one of {@link PelConvert::LITTLE_ENDIAN} and
89
  * {@link PelConvert::BIG_ENDIAN}, specifying the target byte order.
90
  *
@@ -94,4 +94,1477 @@ class PelEntrySShort extends PelEntryNumber
94
  {
95
  return PelConvert::sShortToBytes($number, $order);
96
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  }
53
  * getValue} method will always return an array except for when a
54
  * single integer argument is given here.
55
  *
56
+ * @param int $tag
57
  * the tag which this entry represents. This
58
  * should be one of the constants defined in {@link PelTag}
59
  * which has format {@link PelFormat::SSHORT}.
84
  * @param int $number
85
  * the number that should be converted.
86
  *
87
+ * @param boolean $order
88
  * one of {@link PelConvert::LITTLE_ENDIAN} and
89
  * {@link PelConvert::BIG_ENDIAN}, specifying the target byte order.
90
  *
94
  {
95
  return PelConvert::sShortToBytes($number, $order);
96
  }
97
+
98
+ /**
99
+ * Get the value of an entry as text.
100
+ *
101
+ * The value will be returned in a format suitable for presentation,
102
+ * e.g., instead of returning '2' for a {@link
103
+ * PelTag::METERING_MODE} tag, 'Center-Weighted Average' is
104
+ * returned.
105
+ *
106
+ * @param
107
+ * boolean some values can be returned in a long or more
108
+ * brief form, and this parameter controls that.
109
+ *
110
+ * @return string the value as text.
111
+ */
112
+ public function getText($brief = false)
113
+ {
114
+ if ($this->ifd_type == PelIfd::CANON_FILE_INFO) {
115
+ switch ($this->tag) {
116
+ case PelTag::CANON_FI_BRACKET_MODE:
117
+ // CC (e->components, 1, v);
118
+ switch ($this->value[0]) {
119
+ case 0:
120
+ return Pel::tra('Off');
121
+ case 1:
122
+ return Pel::tra('AEB');
123
+ case 2:
124
+ return Pel::tra('FEB');
125
+ case 3:
126
+ return Pel::tra('ISO');
127
+ case 4:
128
+ return Pel::tra('WB');
129
+ default:
130
+ return $this->value[0];
131
+ }
132
+ break;
133
+ case PelTag::CANON_FI_RAW_JPG_QUALITY:
134
+ // CC (e->components, 1, v);
135
+ switch ($this->value[0]) {
136
+ case 1:
137
+ return Pel::tra('Economy');
138
+ case 2:
139
+ return Pel::tra('Normal');
140
+ case 3:
141
+ return Pel::tra('Fine');
142
+ case 4:
143
+ return Pel::tra('RAW');
144
+ case 5:
145
+ return Pel::tra('Superfine');
146
+ case 130:
147
+ return Pel::tra('Normal Movie');
148
+ case 131:
149
+ return Pel::tra('Movie (2)');
150
+ default:
151
+ return $this->value[0];
152
+ }
153
+ break;
154
+ case PelTag::CANON_FI_RAW_JPG_SIZE:
155
+ // CC (e->components, 1, v);
156
+ switch ($this->value[0]) {
157
+ case 0:
158
+ return Pel::tra('Large');
159
+ case 1:
160
+ return Pel::tra('Medium');
161
+ case 2:
162
+ return Pel::tra('Small');
163
+ case 5:
164
+ return Pel::tra('Medium 1');
165
+ case 6:
166
+ return Pel::tra('Medium 2');
167
+ case 7:
168
+ return Pel::tra('Medium 3');
169
+ case 8:
170
+ return Pel::tra('Postcard');
171
+ case 9:
172
+ return Pel::tra('Widescreen');
173
+ case 10:
174
+ return Pel::tra('Medium Widescreen');
175
+ case 14:
176
+ return Pel::tra('Small 1');
177
+ case 15:
178
+ return Pel::tra('Small 2');
179
+ case 16:
180
+ return Pel::tra('Small 3');
181
+ case 128:
182
+ return Pel::tra('640x480 Movie');
183
+ case 129:
184
+ return Pel::tra('Medium Movie');
185
+ case 130:
186
+ return Pel::tra('Small Movie');
187
+ case 137:
188
+ return Pel::tra('1280x720 Movie');
189
+ case 142:
190
+ return Pel::tra('1920x1080 Movie');
191
+ default:
192
+ return $this->value[0];
193
+ }
194
+ break;
195
+ case PelTag::CANON_FI_NOISE_REDUCTION:
196
+ // CC (e->components, 1, v);
197
+ switch ($this->value[0]) {
198
+ case 0:
199
+ return Pel::tra('Off');
200
+ case 1:
201
+ return Pel::tra('On (1D)');
202
+ case 3:
203
+ return Pel::tra('On');
204
+ case 4:
205
+ return Pel::tra('Auto');
206
+ default:
207
+ return $this->value[0];
208
+ }
209
+ break;
210
+ case PelTag::CANON_FI_WB_BRACKET_MODE:
211
+ // CC (e->components, 1, v);
212
+ switch ($this->value[0]) {
213
+ case 0:
214
+ return Pel::tra('Off');
215
+ case 1:
216
+ return Pel::tra('On (shift AB)');
217
+ case 2:
218
+ return Pel::tra('On (shift GM)');
219
+ default:
220
+ return $this->value[0];
221
+ }
222
+ break;
223
+ case PelTag::CANON_FI_FILTER_EFFECT:
224
+ // CC (e->components, 1, v);
225
+ switch ($this->value[0]) {
226
+ case 0:
227
+ return Pel::tra('None');
228
+ case 1:
229
+ return Pel::tra('Yellow');
230
+ case 2:
231
+ return Pel::tra('Orange');
232
+ case 3:
233
+ return Pel::tra('Red');
234
+ case 4:
235
+ return Pel::tra('Green');
236
+ default:
237
+ return $this->value[0];
238
+ }
239
+ break;
240
+ case PelTag::CANON_FI_TONING_EFFECT:
241
+ // CC (e->components, 1, v);
242
+ switch ($this->value[0]) {
243
+ case 0:
244
+ return Pel::tra('None');
245
+ case 1:
246
+ return Pel::tra('Sepia');
247
+ case 2:
248
+ return Pel::tra('Blue');
249
+ case 3:
250
+ return Pel::tra('Purple');
251
+ case 4:
252
+ return Pel::tra('Green');
253
+ default:
254
+ return $this->value[0];
255
+ }
256
+ break;
257
+ case PelTag::CANON_FI_LIVE_VIEW_SHOOTING:
258
+ // CC (e->components, 1, v);
259
+ switch ($this->value[0]) {
260
+ case 0:
261
+ return Pel::tra('Off');
262
+ case 1:
263
+ return Pel::tra('On');
264
+ default:
265
+ return $this->value[0];
266
+ }
267
+ break;
268
+ case PelTag::CANON_FI_FLASH_EXPOSURE_LOCK:
269
+ // CC (e->components, 1, v);
270
+ switch ($this->value[0]) {
271
+ case 0:
272
+ return Pel::tra('Off');
273
+ case 1:
274
+ return Pel::tra('On');
275
+ default:
276
+ return $this->value[0];
277
+ }
278
+ break;
279
+ default:
280
+ return $this->value[0];
281
+ }
282
+ }
283
+ switch ($this->tag) {
284
+ case PelTag::CANON_CS_MACRO:
285
+ // CC (e->components, 1, v);
286
+ switch ($this->value[0]) {
287
+ case 1:
288
+ return Pel::tra('Macro');
289
+ case 2:
290
+ return Pel::tra('Normal');
291
+ default:
292
+ return $this->value[0];
293
+ }
294
+ break;
295
+ case PelTag::CANON_CS_QUALITY:
296
+ // CC (e->components, 1, v);
297
+ switch ($this->value[0]) {
298
+ case 1:
299
+ return Pel::tra('Economy');
300
+ case 2:
301
+ return Pel::tra('Normal');
302
+ case 3:
303
+ return Pel::tra('Fine');
304
+ case 4:
305
+ return Pel::tra('RAW');
306
+ case 5:
307
+ return Pel::tra('Superfine');
308
+ case 130:
309
+ return Pel::tra('Normal Movie');
310
+ case 131:
311
+ return Pel::tra('Movie (2)');
312
+ default:
313
+ return $this->value[0];
314
+ }
315
+ break;
316
+ case PelTag::CANON_CS_FLASH_MODE:
317
+ // CC (e->components, 1, v);
318
+ switch ($this->value[0]) {
319
+ case 0:
320
+ return Pel::tra('Off');
321
+ case 1:
322
+ return Pel::tra('Auto');
323
+ case 2:
324
+ return Pel::tra('On');
325
+ case 3:
326
+ return Pel::tra('Red-eye reduction');
327
+ case 4:
328
+ return Pel::tra('Slow-sync');
329
+ case 5:
330
+ return Pel::tra('Red-eye reduction (Auto)');
331
+ case 6:
332
+ return Pel::tra('Red-eye reduction (On)');
333
+ case 16:
334
+ return Pel::tra('External flash');
335
+ default:
336
+ return $this->value[0];
337
+ }
338
+ break;
339
+ case PelTag::CANON_CS_DRIVE_MODE:
340
+ // CC (e->components, 1, v);
341
+ switch ($this->value[0]) {
342
+ case 0:
343
+ return Pel::tra('Single');
344
+ case 1:
345
+ return Pel::tra('Continuous');
346
+ case 2:
347
+ return Pel::tra('Movie');
348
+ case 3:
349
+ return Pel::tra('Continuous, Speed Priority');
350
+ case 4:
351
+ return Pel::tra('Continuous, Low');
352
+ case 5:
353
+ return Pel::tra('Continuous, High');
354
+ case 6:
355
+ return Pel::tra('Silent Single');
356
+ case 9:
357
+ return Pel::tra('Single, Silent');
358
+ case 10:
359
+ return Pel::tra('Continuous, Silent');
360
+ default:
361
+ return $this->value[0];
362
+ }
363
+ break;
364
+ case PelTag::CANON_CS_FOCUS_MODE:
365
+ // CC (e->components, 1, v);
366
+ switch ($this->value[0]) {
367
+ case 0:
368
+ return Pel::tra('One-shot AF');
369
+ case 1:
370
+ return Pel::tra('AI Servo AF');
371
+ case 2:
372
+ return Pel::tra('AI Focus AF');
373
+ case 3:
374
+ return Pel::tra('Manual Focus (3)');
375
+ case 4:
376
+ return Pel::tra('Single');
377
+ case 5:
378
+ return Pel::tra('Continuous');
379
+ case 6:
380
+ return Pel::tra('Manual Focus (6)');
381
+ case 16:
382
+ return Pel::tra('Pan Focus');
383
+ case 256:
384
+ return Pel::tra('AF + MF');
385
+ case 512:
386
+ return Pel::tra('Movie Snap Focus');
387
+ case 519:
388
+ return Pel::tra('Movie Servo AF');
389
+ default:
390
+ return $this->value[0];
391
+ }
392
+ break;
393
+ case PelTag::CANON_CS_RECORD_MODE:
394
+ // CC (e->components, 1, v);
395
+ switch ($this->value[0]) {
396
+ case 1:
397
+ return Pel::tra('JPEG');
398
+ case 2:
399
+ return Pel::tra('CRW+THM');
400
+ case 3:
401
+ return Pel::tra('AVI+THM');
402
+ case 4:
403
+ return Pel::tra('TIF');
404
+ case 5:
405
+ return Pel::tra('TIF+JPEG');
406
+ case 6:
407
+ return Pel::tra('CR2');
408
+ case 7:
409
+ return Pel::tra('CR2+JPEG');
410
+ case 9:
411
+ return Pel::tra('MOV');
412
+ case 10:
413
+ return Pel::tra('MP4');
414
+ default:
415
+ return $this->value[0];
416
+ }
417
+ break;
418
+ case PelTag::CANON_CS_IMAGE_SIZE:
419
+ // CC (e->components, 1, v);
420
+ switch ($this->value[0]) {
421
+ case 0:
422
+ return Pel::tra('Large');
423
+ case 1:
424
+ return Pel::tra('Medium');
425
+ case 2:
426
+ return Pel::tra('Small');
427
+ case 5:
428
+ return Pel::tra('Medium 1');
429
+ case 6:
430
+ return Pel::tra('Medium 2');
431
+ case 7:
432
+ return Pel::tra('Medium 3');
433
+ case 8:
434
+ return Pel::tra('Postcard');
435
+ case 9:
436
+ return Pel::tra('Widescreen');
437
+ case 10:
438
+ return Pel::tra('Medium Widescreen');
439
+ case 14:
440
+ return Pel::tra('Small 1');
441
+ case 15:
442
+ return Pel::tra('Small 2');
443
+ case 16:
444
+ return Pel::tra('Small 3');
445
+ case 128:
446
+ return Pel::tra('640x480 Movie');
447
+ case 129:
448
+ return Pel::tra('Medium Movie');
449
+ case 130:
450
+ return Pel::tra('Small Movie');
451
+ case 137:
452
+ return Pel::tra('1280x720 Movie');
453
+ case 142:
454
+ return Pel::tra('1920x1080 Movie');
455
+ default:
456
+ return $this->value[0];
457
+ }
458
+ break;
459
+ case PelTag::CANON_CS_EASY_MODE:
460
+ // CC (e->components, 1, v);
461
+ switch ($this->value[0]) {
462
+ case 0:
463
+ return Pel::tra('Full auto');
464
+ case 1:
465
+ return Pel::tra('Manual');
466
+ case 2:
467
+ return Pel::tra('Landscape');
468
+ case 3:
469
+ return Pel::tra('Fast shutter');
470
+ case 4:
471
+ return Pel::tra('Slow shutter');
472
+ case 5:
473
+ return Pel::tra('Night');
474
+ case 6:
475
+ return Pel::tra('Gray Scale');
476
+ case 7:
477
+ return Pel::tra('Sepia');
478
+ case 8:
479
+ return Pel::tra('Portrait');
480
+ case 9:
481
+ return Pel::tra('Sports');
482
+ case 10:
483
+ return Pel::tra('Macro');
484
+ case 11:
485
+ return Pel::tra('Black & White');
486
+ case 12:
487
+ return Pel::tra('Pan focus');
488
+ case 13:
489
+ return Pel::tra('Vivid');
490
+ case 14:
491
+ return Pel::tra('Neutral');
492
+ case 15:
493
+ return Pel::tra('Flash Off');
494
+ case 16:
495
+ return Pel::tra('Long Shutter');
496
+ case 17:
497
+ return Pel::tra('Super Macro');
498
+ case 18:
499
+ return Pel::tra('Foliage');
500
+ case 19:
501
+ return Pel::tra('Indoor');
502
+ case 20:
503
+ return Pel::tra('Fireworks');
504
+ case 21:
505
+ return Pel::tra('Beach');
506
+ case 22:
507
+ return Pel::tra('Underwater');
508
+ case 23:
509
+ return Pel::tra('Snow');
510
+ case 24:
511
+ return Pel::tra('Kids & Pets');
512
+ case 25:
513
+ return Pel::tra('Night Snapshot');
514
+ case 26:
515
+ return Pel::tra('Digital Macro');
516
+ case 27:
517
+ return Pel::tra('My Colors');
518
+ case 28:
519
+ return Pel::tra('Movie Snap');
520
+ case 29:
521
+ return Pel::tra('Super Macro 2');
522
+ case 30:
523
+ return Pel::tra('Color Accent');
524
+ case 31:
525
+ return Pel::tra('Color Swap');
526
+ case 32:
527
+ return Pel::tra('Aquarium');
528
+ case 33:
529
+ return Pel::tra('ISO 3200');
530
+ case 34:
531
+ return Pel::tra('ISO 6400');
532
+ case 35:
533
+ return Pel::tra('Creative Light Effect');
534
+ case 36:
535
+ return Pel::tra('Easy');
536
+ case 37:
537
+ return Pel::tra('Quick Shot');
538
+ case 38:
539
+ return Pel::tra('Creative Auto');
540
+ case 39:
541
+ return Pel::tra('Zoom Blur');
542
+ case 40:
543
+ return Pel::tra('Low Light');
544
+ case 41:
545
+ return Pel::tra('Nostalgic');
546
+ case 42:
547
+ return Pel::tra('Super Vivid');
548
+ case 43:
549
+ return Pel::tra('Poster Effect');
550
+ case 44:
551
+ return Pel::tra('Face Self-timer');
552
+ case 45:
553
+ return Pel::tra('Smile');
554
+ case 46:
555
+ return Pel::tra('Wink Self-timer');
556
+ case 47:
557
+ return Pel::tra('Fisheye Effect');
558
+ case 48:
559
+ return Pel::tra('Miniature Effect');
560
+ case 49:
561
+ return Pel::tra('High-speed Burst');
562
+ case 50:
563
+ return Pel::tra('Best Image Selection');
564
+ case 51:
565
+ return Pel::tra('High Dynamic Range');
566
+ case 52:
567
+ return Pel::tra('Handheld Night Scene');
568
+ case 53:
569
+ return Pel::tra('Movie Digest');
570
+ case 54:
571
+ return Pel::tra('Live View Control');
572
+ case 55:
573
+ return Pel::tra('Discreet');
574
+ case 56:
575
+ return Pel::tra('Blur Reduction');
576
+ case 57:
577
+ return Pel::tra('Monochrome');
578
+ case 58:
579
+ return Pel::tra('Toy Camera Effect');
580
+ case 59:
581
+ return Pel::tra('Scene Intelligent Auto');
582
+ case 60:
583
+ return Pel::tra('High-speed Burst HQ');
584
+ case 61:
585
+ return Pel::tra('Smooth Skin');
586
+ case 62:
587
+ return Pel::tra('Soft Focus');
588
+ case 257:
589
+ return Pel::tra('Spotlight');
590
+ case 258:
591
+ return Pel::tra('Night 2');
592
+ case 259:
593
+ return Pel::tra('Night+');
594
+ case 260:
595
+ return Pel::tra('Super Night');
596
+ case 261:
597
+ return Pel::tra('Sunset');
598
+ case 263:
599
+ return Pel::tra('Night Scene');
600
+ case 264:
601
+ return Pel::tra('Surface');
602
+ case 265:
603
+ return Pel::tra('Low Light 2');
604
+ default:
605
+ return $this->value[0];
606
+ }
607
+ break;
608
+ case PelTag::CANON_CS_DIGITAL_ZOOM:
609
+ // CC (e->components, 1, v);
610
+ switch ($this->value[0]) {
611
+ case 0:
612
+ return Pel::tra('None');
613
+ case 1:
614
+ return Pel::tra('2x');
615
+ case 2:
616
+ return Pel::tra('4x');
617
+ case 3:
618
+ return Pel::tra('Other');
619
+ default:
620
+ return $this->value[0];
621
+ }
622
+ break;
623
+ case PelTag::CANON_CS_CONTRAST:
624
+ // CC (e->components, 1, v);
625
+ switch ($this->value[0]) {
626
+ case 0:
627
+ return Pel::tra('Normal');
628
+ default:
629
+ return $this->value[0];
630
+ }
631
+ break;
632
+ case PelTag::CANON_CS_SATURATION:
633
+ // CC (e->components, 1, v);
634
+ switch ($this->value[0]) {
635
+ case 0:
636
+ return Pel::tra('Normal');
637
+ default:
638
+ return $this->value[0];
639
+ }
640
+ break;
641
+ case PelTag::CANON_CS_METERING_MODE:
642
+ // CC (e->components, 1, v);
643
+ switch ($this->value[0]) {
644
+ case 0:
645
+ return Pel::tra('Default');
646
+ case 1:
647
+ return Pel::tra('Spot');
648
+ case 2:
649
+ return Pel::tra('Average');
650
+ case 3:
651
+ return Pel::tra('Evaluative');
652
+ case 4:
653
+ return Pel::tra('Partial');
654
+ case 5:
655
+ return Pel::tra('Center-weighted average');
656
+ default:
657
+ return $this->value[0];
658
+ }
659
+ break;
660
+ case PelTag::CANON_CS_FOCUS_TYPE:
661
+ // CC (e->components, 1, v);
662
+ switch ($this->value[0]) {
663
+ case 0:
664
+ return Pel::tra('Manual');
665
+ case 1:
666
+ return Pel::tra('Auto');
667
+ case 2:
668
+ return Pel::tra('Not Known');
669
+ case 3:
670
+ return Pel::tra('Macro');
671
+ case 4:
672
+ return Pel::tra('Very Close');
673
+ case 5:
674
+ return Pel::tra('Close');
675
+ case 6:
676
+ return Pel::tra('Middle Range');
677
+ case 7:
678
+ return Pel::tra('Far Range');
679
+ case 8:
680
+ return Pel::tra('Pan Focus');
681
+ case 9:
682
+ return Pel::tra('Super Macro');
683
+ case 10:
684
+ return Pel::tra('Infinity');
685
+ default:
686
+ return $this->value[0];
687
+ }
688
+ break;
689
+ case PelTag::CANON_CS_AF_POINT:
690
+ // CC (e->components, 1, v);
691
+ switch ($this->value[0]) {
692
+ case 0x2005:
693
+ return Pel::tra('Manual AF point selection');
694
+ case 0x3000:
695
+ return Pel::tra('None (MF)');
696
+ case 0x3001:
697
+ return Pel::tra('Auto AF point selection');
698
+ case 0x3002:
699
+ return Pel::tra('Right');
700
+ case 0x3003:
701
+ return Pel::tra('Center');
702
+ case 0x3004:
703
+ return Pel::tra('Left');
704
+ case 0x4001:
705
+ return Pel::tra('Auto AF point selection');
706
+ case 0x4006:
707
+ return Pel::tra('Face Detect');
708
+ default:
709
+ return $this->value[0];
710
+ }
711
+ break;
712
+ case PelTag::CANON_CS_EXPOSURE_PROGRAM:
713
+ // CC (e->components, 1, v);
714
+ switch ($this->value[0]) {
715
+ case 0:
716
+ return Pel::tra('Easy');
717
+ case 1:
718
+ return Pel::tra('Program AE');
719
+ case 2:
720
+ return Pel::tra('Shutter speed priority AE');
721
+ case 3:
722
+ return Pel::tra('Aperture-priority AE');
723
+ case 4:
724
+ return Pel::tra('Manual');
725
+ case 5:
726
+ return Pel::tra('Depth-of-field AE');
727
+ case 6:
728
+ return Pel::tra('M-Dep');
729
+ case 7:
730
+ return Pel::tra('Bulb');
731
+ default:
732
+ return $this->value[0];
733
+ }
734
+ break;
735
+ case PelTag::CANON_CS_LENS_TYPE:
736
+ // CC (e->components, 1, v);
737
+ switch ($this->value[0]) {
738
+ case 1:
739
+ return Pel::tra('Canon EF 50mm f/1.8');
740
+ case 2:
741
+ return Pel::tra('Canon EF 28mm f/2.8');
742
+ case 3:
743
+ return Pel::tra('Canon EF 135mm f/2.8 Soft');
744
+ case 4:
745
+ return Pel::tra('Canon EF 35-105mm f/3.5-4.5 or Sigma Lens');
746
+ case 4.1:
747
+ return Pel::tra('Sigma UC Zoom 35-135mm f/4-5.6');
748
+ case 5:
749
+ return Pel::tra('Canon EF 35-70mm f/3.5-4.5');
750
+ case 6:
751
+ return Pel::tra('Canon EF 28-70mm f/3.5-4.5 or Sigma or Tokina Lens');
752
+ case 6.1:
753
+ return Pel::tra('Sigma 18-50mm f/3.5-5.6 DC');
754
+ case 6.2:
755
+ return Pel::tra('Sigma 18-125mm f/3.5-5.6 DC IF ASP');
756
+ case 6.3:
757
+ return Pel::tra('Tokina AF 193-2 19-35mm f/3.5-4.5');
758
+ case 6.4:
759
+ return Pel::tra('Sigma 28-80mm f/3.5-5.6 II Macro');
760
+ case 7:
761
+ return Pel::tra('Canon EF 100-300mm f/5.6L');
762
+ case 8:
763
+ return Pel::tra('Canon EF 100-300mm f/5.6 or Sigma or Tokina Lens');
764
+ case 8.1:
765
+ return Pel::tra('Sigma 70-300mm f/4-5.6 [APO] DG Macro');
766
+ case 8.2:
767
+ return Pel::tra('Tokina AT-X 242 AF 24-200mm f/3.5-5.6');
768
+ case 9:
769
+ return Pel::tra('Canon EF 70-210mm f/4');
770
+ case 9.1:
771
+ return Pel::tra('Sigma 55-200mm f/4-5.6 DC');
772
+ case 10:
773
+ return Pel::tra('Canon EF 50mm f/2.5 Macro or Sigma Lens');
774
+ case 10.1:
775
+ return Pel::tra('Sigma 50mm f/2.8 EX');
776
+ case 10.2:
777
+ return Pel::tra('Sigma 28mm f/1.8');
778
+ case 10.3:
779
+ return Pel::tra('Sigma 105mm f/2.8 Macro EX');
780
+ case 10.4:
781
+ return Pel::tra('Sigma 70mm f/2.8 EX DG Macro EF');
782
+ case 11:
783
+ return Pel::tra('Canon EF 35mm f/2');
784
+ case 13:
785
+ return Pel::tra('Canon EF 15mm f/2.8 Fisheye');
786
+ case 14:
787
+ return Pel::tra('Canon EF 50-200mm f/3.5-4.5L');
788
+ case 15:
789
+ return Pel::tra('Canon EF 50-200mm f/3.5-4.5');
790
+ case 16:
791
+ return Pel::tra('Canon EF 35-135mm f/3.5-4.5');
792
+ case 17:
793
+ return Pel::tra('Canon EF 35-70mm f/3.5-4.5A');
794
+ case 18:
795
+ return Pel::tra('Canon EF 28-70mm f/3.5-4.5');
796
+ case 20:
797
+ return Pel::tra('Canon EF 100-200mm f/4.5A');
798
+ case 21:
799
+ return Pel::tra('Canon EF 80-200mm f/2.8L');
800
+ case 22:
801
+ return Pel::tra('Canon EF 20-35mm f/2.8L or Tokina Lens');
802
+ case 22.1:
803
+ return Pel::tra('Tokina AT-X 280 AF Pro 28-80mm f/2.8 Aspherical');
804
+ case 23:
805
+ return Pel::tra('Canon EF 35-105mm f/3.5-4.5');
806
+ case 24:
807
+ return Pel::tra('Canon EF 35-80mm f/4-5.6 Power Zoom');
808
+ case 25:
809
+ return Pel::tra('Canon EF 35-80mm f/4-5.6 Power Zoom');
810
+ case 26:
811
+ return Pel::tra('Canon EF 100mm f/2.8 Macro or Other Lens');
812
+ case 26.1:
813
+ return Pel::tra('Cosina 100mm f/3.5 Macro AF');
814
+ case 26.2:
815
+ return Pel::tra('Tamron SP AF 90mm f/2.8 Di Macro');
816
+ case 26.3:
817
+ return Pel::tra('Tamron SP AF 180mm f/3.5 Di Macro');
818
+ case 26.4:
819
+ return Pel::tra('Carl Zeiss Planar T* 50mm f/1.4');
820
+ case 27:
821
+ return Pel::tra('Canon EF 35-80mm f/4-5.6');
822
+ case 28:
823
+ return Pel::tra('Canon EF 80-200mm f/4.5-5.6 or Tamron Lens');
824
+ case 28.1:
825
+ return Pel::tra('Tamron SP AF 28-105mm f/2.8 LD Aspherical IF');
826
+ case 28.2:
827
+ return Pel::tra('Tamron SP AF 28-75mm f/2.8 XR Di LD Aspherical [IF] Macro');
828
+ case 28.3:
829
+ return Pel::tra('Tamron AF 70-300mm f/4-5.6 Di LD 1:2 Macro');
830
+ case 28.4:
831
+ return Pel::tra('Tamron AF Aspherical 28-200mm f/3.8-5.6');
832
+ case 29:
833
+ return Pel::tra('Canon EF 50mm f/1.8 II');
834
+ case 30:
835
+ return Pel::tra('Canon EF 35-105mm f/4.5-5.6');
836
+ case 31:
837
+ return Pel::tra('Canon EF 75-300mm f/4-5.6 or Tamron Lens');
838
+ case 31.1:
839
+ return Pel::tra('Tamron SP AF 300mm f/2.8 LD IF');
840
+ case 32:
841
+ return Pel::tra('Canon EF 24mm f/2.8 or Sigma Lens');
842
+ case 32.1:
843
+ return Pel::tra('Sigma 15mm f/2.8 EX Fisheye');
844
+ case 33:
845
+ return Pel::tra('Voigtlander or Carl Zeiss Lens');
846
+ case 33.1:
847
+ return Pel::tra('Voigtlander Ultron 40mm f/2 SLII Aspherical');
848
+ case 33.2:
849
+ return Pel::tra('Voigtlander Color Skopar 20mm f/3.5 SLII Aspherical');
850
+ case 33.3:
851
+ return Pel::tra('Voigtlander APO-Lanthar 90mm f/3.5 SLII Close Focus');
852
+ case 33.4:
853
+ return Pel::tra('Carl Zeiss Distagon T* 15mm f/2.8 ZE');
854
+ case 33.5:
855
+ return Pel::tra('Carl Zeiss Distagon T* 18mm f/3.5 ZE');
856
+ case 33.6:
857
+ return Pel::tra('Carl Zeiss Distagon T* 21mm f/2.8 ZE');
858
+ case 33.7:
859
+ return Pel::tra('Carl Zeiss Distagon T* 25mm f/2 ZE');
860
+ case 33.8:
861
+ return Pel::tra('Carl Zeiss Distagon T* 28mm f/2 ZE');
862
+ case 33.9:
863
+ return Pel::tra('Carl Zeiss Distagon T* 35mm f/2 ZE');
864
+ case 33.10:
865
+ return Pel::tra('Carl Zeiss Distagon T* 35mm f/1.4 ZE');
866
+ case 33.11:
867
+ return Pel::tra('Carl Zeiss Planar T* 50mm f/1.4 ZE');
868
+ case 33.12:
869
+ return Pel::tra('Carl Zeiss Makro-Planar T* 50mm f/2 ZE');
870
+ case 33.13:
871
+ return Pel::tra('Carl Zeiss Makro-Planar T* 100mm f/2 ZE');
872
+ case 33.14:
873
+ return Pel::tra('Carl Zeiss Apo-Sonnar T* 135mm f/2 ZE');
874
+ case 35:
875
+ return Pel::tra('Canon EF 35-80mm f/4-5.6');
876
+ case 36:
877
+ return Pel::tra('Canon EF 38-76mm f/4.5-5.6');
878
+ case 37:
879
+ return Pel::tra('Canon EF 35-80mm f/4-5.6 or Tamron Lens');
880
+ case 37.1:
881
+ return Pel::tra('Tamron 70-200mm f/2.8 Di LD IF Macro');
882
+ case 37.2:
883
+ return Pel::tra('Tamron AF 28-300mm f/3.5-6.3 XR Di VC LD Aspherical [IF] Macro Model A20');
884
+ case 37.3:
885
+ return Pel::tra('Tamron SP AF 17-50mm f/2.8 XR Di II VC LD Aspherical [IF]');
886
+ case 37.4:
887
+ return Pel::tra('Tamron AF 18-270mm f/3.5-6.3 Di II VC LD Aspherical [IF] Macro');
888
+ case 38:
889
+ return Pel::tra('Canon EF 80-200mm f/4.5-5.6');
890
+ case 39:
891
+ return Pel::tra('Canon EF 75-300mm f/4-5.6');
892
+ case 40:
893
+ return Pel::tra('Canon EF 28-80mm f/3.5-5.6');
894
+ case 41:
895
+ return Pel::tra('Canon EF 28-90mm f/4-5.6');
896
+ case 42:
897
+ return Pel::tra('Canon EF 28-200mm f/3.5-5.6 or Tamron Lens');
898
+ case 42.1:
899
+ return Pel::tra('Tamron AF 28-300mm f/3.5-6.3 XR Di VC LD Aspherical [IF] Macro Model A20');
900
+ case 43:
901
+ return Pel::tra('Canon EF 28-105mm f/4-5.6');
902
+ case 44:
903
+ return Pel::tra('Canon EF 90-300mm f/4.5-5.6');
904
+ case 45:
905
+ return Pel::tra('Canon EF-S 18-55mm f/3.5-5.6 [II]');
906
+ case 46:
907
+ return Pel::tra('Canon EF 28-90mm f/4-5.6');
908
+ case 47:
909
+ return Pel::tra('Zeiss Milvus 35mm f/2 or 50mm f/2');
910
+ case 47.1:
911
+ return Pel::tra('Zeiss Milvus 50mm f/2 Makro');
912
+ case 48:
913
+ return Pel::tra('Canon EF-S 18-55mm f/3.5-5.6 IS');
914
+ case 49:
915
+ return Pel::tra('Canon EF-S 55-250mm f/4-5.6 IS');
916
+ case 50:
917
+ return Pel::tra('Canon EF-S 18-200mm f/3.5-5.6 IS');
918
+ case 51:
919
+ return Pel::tra('Canon EF-S 18-135mm f/3.5-5.6 IS');
920
+ case 52:
921
+ return Pel::tra('Canon EF-S 18-55mm f/3.5-5.6 IS II');
922
+ case 53:
923
+ return Pel::tra('Canon EF-S 18-55mm f/3.5-5.6 III');
924
+ case 54:
925
+ return Pel::tra('Canon EF-S 55-250mm f/4-5.6 IS II');
926
+ case 60:
927
+ return Pel::tra('Irix 11mm f/4');
928
+ case 94:
929
+ return Pel::tra('Canon TS-E 17mm f/4L');
930
+ case 95:
931
+ return Pel::tra('Canon TS-E 24.0mm f/3.5 L II');
932
+ case 124:
933
+ return Pel::tra('Canon MP-E 65mm f/2.8 1-5x Macro Photo');
934
+ case 125:
935
+ return Pel::tra('Canon TS-E 24mm f/3.5L');
936
+ case 126:
937
+ return Pel::tra('Canon TS-E 45mm f/2.8');
938
+ case 127:
939
+ return Pel::tra('Canon TS-E 90mm f/2.8');
940
+ case 129:
941
+ return Pel::tra('Canon EF 300mm f/2.8L');
942
+ case 130:
943
+ return Pel::tra('Canon EF 50mm f/1.0L');
944
+ case 131:
945
+ return Pel::tra('Canon EF 28-80mm f/2.8-4L or Sigma Lens');
946
+ case 131.1:
947
+ return Pel::tra('Sigma 8mm f/3.5 EX DG Circular Fisheye');
948
+ case 131.2:
949
+ return Pel::tra('Sigma 17-35mm f/2.8-4 EX DG Aspherical HSM');
950
+ case 131.3:
951
+ return Pel::tra('Sigma 17-70mm f/2.8-4.5 DC Macro');
952
+ case 131.4:
953
+ return Pel::tra('Sigma APO 50-150mm f/2.8 [II] EX DC HSM');
954
+ case 131.5:
955
+ return Pel::tra('Sigma APO 120-300mm f/2.8 EX DG HSM');
956
+ case 131.6:
957
+ return Pel::tra('Sigma 4.5mm f/2.8 EX DC HSM Circular Fisheye');
958
+ case 131.7:
959
+ return Pel::tra('Sigma 70-200mm f/2.8 APO EX HSM');
960
+ case 132:
961
+ return Pel::tra('Canon EF 1200mm f/5.6L');
962
+ case 134:
963
+ return Pel::tra('Canon EF 600mm f/4L IS');
964
+ case 135:
965
+ return Pel::tra('Canon EF 200mm f/1.8L');
966
+ case 136:
967
+ return Pel::tra('Canon EF 300mm f/2.8L');
968
+ case 137:
969
+ return Pel::tra('Canon EF 85mm f/1.2L or Sigma or Tamron Lens');
970
+ case 137.1:
971
+ return Pel::tra('Sigma 18-50mm f/2.8-4.5 DC OS HSM');
972
+ case 137.2:
973
+ return Pel::tra('Sigma 50-200mm f/4-5.6 DC OS HSM');
974
+ case 137.3:
975
+ return Pel::tra('Sigma 18-250mm f/3.5-6.3 DC OS HSM');
976
+ case 137.4:
977
+ return Pel::tra('Sigma 24-70mm f/2.8 IF EX DG HSM');
978
+ case 137.5:
979
+ return Pel::tra('Sigma 18-125mm f/3.8-5.6 DC OS HSM');
980
+ case 137.6:
981
+ return Pel::tra('Sigma 17-70mm f/2.8-4 DC Macro OS HSM | C');
982
+ case 137.7:
983
+ return Pel::tra('Sigma 17-50mm f/2.8 OS HSM');
984
+ case 137.8:
985
+ return Pel::tra('Sigma 18-200mm f/3.5-6.3 DC OS HSM [II]');
986
+ case 137.9:
987
+ return Pel::tra('Tamron AF 18-270mm f/3.5-6.3 Di II VC PZD');
988
+ case 137.10:
989
+ return Pel::tra('Sigma 8-16mm f/4.5-5.6 DC HSM');
990
+ case 137.11:
991
+ return Pel::tra('Tamron SP 17-50mm f/2.8 XR Di II VC');
992
+ case 137.12:
993
+ return Pel::tra('Tamron SP 60mm f/2 Macro Di II');
994
+ case 137.13:
995
+ return Pel::tra('Sigma 10-20mm f/3.5 EX DC HSM');
996
+ case 137.14:
997
+ return Pel::tra('Tamron SP 24-70mm f/2.8 Di VC USD');
998
+ case 137.15:
999
+ return Pel::tra('Sigma 18-35mm f/1.8 DC HSM');
1000
+ case 137.16:
1001
+ return Pel::tra('Sigma 12-24mm f/4.5-5.6 DG HSM II');
1002
+ case 138:
1003
+ return Pel::tra('Canon EF 28-80mm f/2.8-4L');
1004
+ case 139:
1005
+ return Pel::tra('Canon EF 400mm f/2.8L');
1006
+ case 140:
1007
+ return Pel::tra('Canon EF 500mm f/4.5L');
1008
+ case 141:
1009
+ return Pel::tra('Canon EF 500mm f/4.5L');
1010
+ case 142:
1011
+ return Pel::tra('Canon EF 300mm f/2.8L IS');
1012
+ case 143:
1013
+ return Pel::tra('Canon EF 500mm f/4L IS or Sigma Lens');
1014
+ case 143.1:
1015
+ return Pel::tra('Sigma 17-70mm f/2.8-4 DC Macro OS HSM');
1016
+ case 144:
1017
+ return Pel::tra('Canon EF 35-135mm f/4-5.6 USM');
1018
+ case 145:
1019
+ return Pel::tra('Canon EF 100-300mm f/4.5-5.6 USM');
1020
+ case 146:
1021
+ return Pel::tra('Canon EF 70-210mm f/3.5-4.5 USM');
1022
+ case 147:
1023
+ return Pel::tra('Canon EF 35-135mm f/4-5.6 USM');
1024
+ case 148:
1025
+ return Pel::tra('Canon EF 28-80mm f/3.5-5.6 USM');
1026
+ case 149:
1027
+ return Pel::tra('Canon EF 100mm f/2 USM');
1028
+ case 150:
1029
+ return Pel::tra('Canon EF 14mm f/2.8L or Sigma Lens');
1030
+ case 150.1:
1031
+ return Pel::tra('Sigma 20mm EX f/1.8');
1032
+ case 150.2:
1033
+ return Pel::tra('Sigma 30mm f/1.4 DC HSM');
1034
+ case 150.3:
1035
+ return Pel::tra('Sigma 24mm f/1.8 DG Macro EX');
1036
+ case 150.4:
1037
+ return Pel::tra('Sigma 28mm f/1.8 DG Macro EX');
1038
+ case 151:
1039
+ return Pel::tra('Canon EF 200mm f/2.8L');
1040
+ case 152:
1041
+ return Pel::tra('Canon EF 300mm f/4L IS or Sigma Lens');
1042
+ case 152.1:
1043
+ return Pel::tra('Sigma 12-24mm f/4.5-5.6 EX DG ASPHERICAL HSM');
1044
+ case 152.2:
1045
+ return Pel::tra('Sigma 14mm f/2.8 EX Aspherical HSM');
1046
+ case 152.3:
1047
+ return Pel::tra('Sigma 10-20mm f/4-5.6');
1048
+ case 152.4:
1049
+ return Pel::tra('Sigma 100-300mm f/4');
1050
+ case 153:
1051
+ return Pel::tra('Canon EF 35-350mm f/3.5-5.6L or Sigma or Tamron Lens');
1052
+ case 153.1:
1053
+ return Pel::tra('Sigma 50-500mm f/4-6.3 APO HSM EX');
1054
+ case 153.2:
1055
+ return Pel::tra('Tamron AF 28-300mm f/3.5-6.3 XR LD Aspherical [IF] Macro');
1056
+ case 153.3:
1057
+ return Pel::tra('Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical [IF] Macro Model A14');
1058
+ case 153.4:
1059
+ return Pel::tra('Tamron 18-250mm f/3.5-6.3 Di II LD Aspherical [IF] Macro');
1060
+ case 154:
1061
+ return Pel::tra('Canon EF 20mm f/2.8 USM or Zeiss Lens');
1062
+ case 154.1:
1063
+ return Pel::tra('Zeiss Milvus 21mm f/2.8');
1064
+ case 155:
1065
+ return Pel::tra('Canon EF 85mm f/1.8 USM');
1066
+ case 156:
1067
+ return Pel::tra('Canon EF 28-105mm f/3.5-4.5 USM or Tamron Lens');
1068
+ case 156.1:
1069
+ return Pel::tra('Tamron SP 70-300mm f/4.0-5.6 Di VC USD');
1070
+ case 156.2:
1071
+ return Pel::tra('Tamron SP AF 28-105mm f/2.8 LD Aspherical IF');
1072
+ case 160:
1073
+ return Pel::tra('Canon EF 20-35mm f/3.5-4.5 USM or Tamron or Tokina Lens');
1074
+ case 160.1:
1075
+ return Pel::tra('Tamron AF 19-35mm f/3.5-4.5');
1076
+ case 160.2:
1077
+ return Pel::tra('Tokina AT-X 124 AF Pro DX 12-24mm f/4');
1078
+ case 160.3:
1079
+ return Pel::tra('Tokina AT-X 107 AF DX 10-17mm f/3.5-4.5 Fisheye');
1080
+ case 160.4:
1081
+ return Pel::tra('Tokina AT-X 116 AF Pro DX 11-16mm f/2.8');
1082
+ case 160.5:
1083
+ return Pel::tra('Tokina AT-X 11-20 F2.8 PRO DX Aspherical 11-20mm f/2.8');
1084
+ case 161:
1085
+ return Pel::tra('Canon EF 28-70mm f/2.8L or Sigma or Tamron Lens');
1086
+ case 161.1:
1087
+ return Pel::tra('Sigma 24-70mm f/2.8 EX');
1088
+ case 161.2:
1089
+ return Pel::tra('Sigma 28-70mm f/2.8 EX');
1090
+ case 161.3:
1091
+ return Pel::tra('Sigma 24-60mm f/2.8 EX DG');
1092
+ case 161.4:
1093
+ return Pel::tra('Tamron AF 17-50mm f/2.8 Di-II LD Aspherical');
1094
+ case 161.5:
1095
+ return Pel::tra('Tamron 90mm f/2.8');
1096
+ case 161.6:
1097
+ return Pel::tra('Tamron SP AF 17-35mm f/2.8-4 Di LD Aspherical IF');
1098
+ case 161.7:
1099
+ return Pel::tra('Tamron SP AF 28-75mm f/2.8 XR Di LD Aspherical [IF] Macro');
1100
+ case 162:
1101
+ return Pel::tra('Canon EF 200mm f/2.8L');
1102
+ case 163:
1103
+ return Pel::tra('Canon EF 300mm f/4L');
1104
+ case 164:
1105
+ return Pel::tra('Canon EF 400mm f/5.6L');
1106
+ case 165:
1107
+ return Pel::tra('Canon EF 70-200mm f/2.8 L');
1108
+ case 166:
1109
+ return Pel::tra('Canon EF 70-200mm f/2.8 L + 1.4x');
1110
+ case 167:
1111
+ return Pel::tra('Canon EF 70-200mm f/2.8 L + 2x');
1112
+ case 168:
1113
+ return Pel::tra('Canon EF 28mm f/1.8 USM or Sigma Lens');
1114
+ case 168.1:
1115
+ return Pel::tra('Sigma 50-100mm f/1.8 DC HSM | A');
1116
+ case 169:
1117
+ return Pel::tra('Canon EF 17-35mm f/2.8L or Sigma Lens');
1118
+ case 169.1:
1119
+ return Pel::tra('Sigma 18-200mm f/3.5-6.3 DC OS');
1120
+ case 169.2:
1121
+ return Pel::tra('Sigma 15-30mm f/3.5-4.5 EX DG Aspherical');
1122
+ case 169.3:
1123
+ return Pel::tra('Sigma 18-50mm f/2.8 Macro');
1124
+ case 169.4:
1125
+ return Pel::tra('Sigma 50mm f/1.4 EX DG HSM');
1126
+ case 169.5:
1127
+ return Pel::tra('Sigma 85mm f/1.4 EX DG HSM');
1128
+ case 169.6:
1129
+ return Pel::tra('Sigma 30mm f/1.4 EX DC HSM');
1130
+ case 169.7:
1131
+ return Pel::tra('Sigma 35mm f/1.4 DG HSM');
1132
+ case 170:
1133
+ return Pel::tra('Canon EF 200mm f/2.8L II');
1134
+ case 171:
1135
+ return Pel::tra('Canon EF 300mm f/4L');
1136
+ case 172:
1137
+ return Pel::tra('Canon EF 400mm f/5.6L or Sigma Lens');
1138
+ case 172.1:
1139
+ return Pel::tra('Sigma 150-600mm f/5-6.3 DG OS HSM | S');
1140
+ case 173:
1141
+ return Pel::tra('Canon EF 180mm Macro f/3.5L or Sigma Lens');
1142
+ case 173.1:
1143
+ return Pel::tra('Sigma 180mm EX HSM Macro f/3.5');
1144
+ case 173.2:
1145
+ return Pel::tra('Sigma APO Macro 150mm f/2.8 EX DG HSM');
1146
+ case 174:
1147
+ return Pel::tra('Canon EF 135mm f/2L or Other Lens');
1148
+ case 174.1:
1149
+ return Pel::tra('Sigma 70-200mm f/2.8 EX DG APO OS HSM');
1150
+ case 174.2:
1151
+ return Pel::tra('Sigma 50-500mm f/4.5-6.3 APO DG OS HSM');
1152
+ case 174.3:
1153
+ return Pel::tra('Sigma 150-500mm f/5-6.3 APO DG OS HSM');
1154
+ case 174.4:
1155
+ return Pel::tra('Zeiss Milvus 100mm f/2 Makro');
1156
+ case 175:
1157
+ return Pel::tra('Canon EF 400mm f/2.8L');
1158
+ case 176:
1159
+ return Pel::tra('Canon EF 24-85mm f/3.5-4.5 USM');
1160
+ case 177:
1161
+ return Pel::tra('Canon EF 300mm f/4L IS');
1162
+ case 178:
1163
+ return Pel::tra('Canon EF 28-135mm f/3.5-5.6 IS');
1164
+ case 179:
1165
+ return Pel::tra('Canon EF 24mm f/1.4L');
1166
+ case 180:
1167
+ return Pel::tra('Canon EF 35mm f/1.4L or Other Lens');
1168
+ case 180.1:
1169
+ return Pel::tra('Sigma 50mm f/1.4 DG HSM | A');
1170
+ case 180.2:
1171
+ return Pel::tra('Sigma 24mm f/1.4 DG HSM | A');
1172
+ case 180.3:
1173
+ return Pel::tra('Zeiss Milvus 50mm f/1.4');
1174
+ case 180.4:
1175
+ return Pel::tra('Zeiss Milvus 85mm f/1.4');
1176
+ case 180.5:
1177
+ return Pel::tra('Zeiss Otus 28mm f/1.4 ZE');
1178
+ case 181:
1179
+ return Pel::tra('Canon EF 100-400mm f/4.5-5.6L IS + 1.4x or Sigma Lens');
1180
+ case 181.1:
1181
+ return Pel::tra('Sigma 150-600mm f/5-6.3 DG OS HSM | S + 1.4x');
1182
+ case 182:
1183
+ return Pel::tra('Canon EF 100-400mm f/4.5-5.6L IS + 2x or Sigma Lens');
1184
+ case 182.1:
1185
+ return Pel::tra('Sigma 150-600mm f/5-6.3 DG OS HSM | S + 2x');
1186
+ case 183:
1187
+ return Pel::tra('Canon EF 100-400mm f/4.5-5.6L IS or Sigma Lens');
1188
+ case 183.1:
1189
+ return Pel::tra('Sigma 150mm f/2.8 EX DG OS HSM APO Macro');
1190
+ case 183.2:
1191
+ return Pel::tra('Sigma 105mm f/2.8 EX DG OS HSM Macro');
1192
+ case 183.3:
1193
+ return Pel::tra('Sigma 180mm f/2.8 EX DG OS HSM APO Macro');
1194
+ case 183.4:
1195
+ return Pel::tra('Sigma 150-600mm f/5-6.3 DG OS HSM | C');
1196
+ case 183.5:
1197
+ return Pel::tra('Sigma 150-600mm f/5-6.3 DG OS HSM | S');
1198
+ case 183.6:
1199
+ return Pel::tra('Sigma 100-400mm f/5-6.3 DG OS HSM');
1200
+ case 184:
1201
+ return Pel::tra('Canon EF 400mm f/2.8L + 2x');
1202
+ case 185:
1203
+ return Pel::tra('Canon EF 600mm f/4L IS');
1204
+ case 186:
1205
+ return Pel::tra('Canon EF 70-200mm f/4L');
1206
+ case 187:
1207
+ return Pel::tra('Canon EF 70-200mm f/4L + 1.4x');
1208
+ case 188:
1209
+ return Pel::tra('Canon EF 70-200mm f/4L + 2x');
1210
+ case 189:
1211
+ return Pel::tra('Canon EF 70-200mm f/4L + 2.8x');
1212
+ case 190:
1213
+ return Pel::tra('Canon EF 100mm f/2.8 Macro USM');
1214
+ case 191:
1215
+ return Pel::tra('Canon EF 400mm f/4 DO IS');
1216
+ case 193:
1217
+ return Pel::tra('Canon EF 35-80mm f/4-5.6 USM');
1218
+ case 194:
1219
+ return Pel::tra('Canon EF 80-200mm f/4.5-5.6 USM');
1220
+ case 195:
1221
+ return Pel::tra('Canon EF 35-105mm f/4.5-5.6 USM');
1222
+ case 196:
1223
+ return Pel::tra('Canon EF 75-300mm f/4-5.6 USM');
1224
+ case 197:
1225
+ return Pel::tra('Canon EF 75-300mm f/4-5.6 IS USM or Sigma Lens');
1226
+ case 197.1:
1227
+ return Pel::tra('Sigma 18-300mm f/3.5-6.3 DC Macro OS HS');
1228
+ case 198:
1229
+ return Pel::tra('Canon EF 50mm f/1.4 USM or Zeiss Lens');
1230
+ case 198.1:
1231
+ return Pel::tra('Zeiss Otus 55mm f/1.4 ZE');
1232
+ case 198.2:
1233
+ return Pel::tra('Zeiss Otus 85mm f/1.4 ZE');
1234
+ case 199:
1235
+ return Pel::tra('Canon EF 28-80mm f/3.5-5.6 USM');
1236
+ case 200:
1237
+ return Pel::tra('Canon EF 75-300mm f/4-5.6 USM');
1238
+ case 201:
1239
+ return Pel::tra('Canon EF 28-80mm f/3.5-5.6 USM');
1240
+ case 202:
1241
+ return Pel::tra('Canon EF 28-80mm f/3.5-5.6 USM IV');
1242
+ case 208:
1243
+ return Pel::tra('Canon EF 22-55mm f/4-5.6 USM');
1244
+ case 209:
1245
+ return Pel::tra('Canon EF 55-200mm f/4.5-5.6');
1246
+ case 210:
1247
+ return Pel::tra('Canon EF 28-90mm f/4-5.6 USM');
1248
+ case 211:
1249
+ return Pel::tra('Canon EF 28-200mm f/3.5-5.6 USM');
1250
+ case 212:
1251
+ return Pel::tra('Canon EF 28-105mm f/4-5.6 USM');
1252
+ case 213:
1253
+ return Pel::tra('Canon EF 90-300mm f/4.5-5.6 USM or Tamron Lens');
1254
+ case 213.1:
1255
+ return Pel::tra('Tamron SP 150-600mm f/5-6.3 Di VC USD');
1256
+ case 213.2:
1257
+ return Pel::tra('Tamron 16-300mm f/3.5-6.3 Di II VC PZD Macro');
1258
+ case 213.3:
1259
+ return Pel::tra('Tamron SP 35mm f/1.8 Di VC USD');
1260
+ case 213.4:
1261
+ return Pel::tra('Tamron SP 45mm f/1.8 Di VC USD');
1262
+ case 214:
1263
+ return Pel::tra('Canon EF-S 18-55mm f/3.5-5.6 USM');
1264
+ case 215:
1265
+ return Pel::tra('Canon EF 55-200mm f/4.5-5.6 II USM');
1266
+ case 217:
1267
+ return Pel::tra('Tamron AF 18-270mm f/3.5-6.3 Di II VC PZD');
1268
+ case 224:
1269
+ return Pel::tra('Canon EF 70-200mm f/2.8L IS');
1270
+ case 225:
1271
+ return Pel::tra('Canon EF 70-200mm f/2.8L IS + 1.4x');
1272
+ case 226:
1273
+ return Pel::tra('Canon EF 70-200mm f/2.8L IS + 2x');
1274
+ case 227:
1275
+ return Pel::tra('Canon EF 70-200mm f/2.8L IS + 2.8x');
1276
+ case 228:
1277
+ return Pel::tra('Canon EF 28-105mm f/3.5-4.5 USM');
1278
+ case 229:
1279
+ return Pel::tra('Canon EF 16-35mm f/2.8L');
1280
+ case 230:
1281
+ return Pel::tra('Canon EF 24-70mm f/2.8L');
1282
+ case 231:
1283
+ return Pel::tra('Canon EF 17-40mm f/4L');
1284
+ case 232:
1285
+ return Pel::tra('Canon EF 70-300mm f/4.5-5.6 DO IS USM');
1286
+ case 233:
1287
+ return Pel::tra('Canon EF 28-300mm f/3.5-5.6L IS');
1288
+ case 234:
1289
+ return Pel::tra('Canon EF-S 17-85mm f/4-5.6 IS USM or Tokina Lens');
1290
+ case 234.1:
1291
+ return Pel::tra('Tokina AT-X 12-28 PRO DX 12-28mm f/4');
1292
+ case 235:
1293
+ return Pel::tra('Canon EF-S 10-22mm f/3.5-4.5 USM');
1294
+ case 236:
1295
+ return Pel::tra('Canon EF-S 60mm f/2.8 Macro USM');
1296
+ case 237:
1297
+ return Pel::tra('Canon EF 24-105mm f/4L IS');
1298
+ case 238:
1299
+ return Pel::tra('Canon EF 70-300mm f/4-5.6 IS USM');
1300
+ case 239:
1301
+ return Pel::tra('Canon EF 85mm f/1.2L II');
1302
+ case 240:
1303
+ return Pel::tra('Canon EF-S 17-55mm f/2.8 IS USM');
1304
+ case 241:
1305
+ return Pel::tra('Canon EF 50mm f/1.2L');
1306
+ case 242:
1307
+ return Pel::tra('Canon EF 70-200mm f/4L IS');
1308
+ case 243:
1309
+ return Pel::tra('Canon EF 70-200mm f/4L IS + 1.4x');
1310
+ case 244:
1311
+ return Pel::tra('Canon EF 70-200mm f/4L IS + 2x');
1312
+ case 245:
1313
+ return Pel::tra('Canon EF 70-200mm f/4L IS + 2.8x');
1314
+ case 246:
1315
+ return Pel::tra('Canon EF 16-35mm f/2.8L II');
1316
+ case 247:
1317
+ return Pel::tra('Canon EF 14mm f/2.8L II USM');
1318
+ case 248:
1319
+ return Pel::tra('Canon EF 200mm f/2L IS or Sigma Lens');
1320
+ case 248.1:
1321
+ return Pel::tra('Sigma 24-35mm f/2 DG HSM | A');
1322
+ case 249:
1323
+ return Pel::tra('Canon EF 800mm f/5.6L IS');
1324
+ case 250:
1325
+ return Pel::tra('Canon EF 24mm f/1.4L II or Sigma Lens');
1326
+ case 250.1:
1327
+ return Pel::tra('Sigma 20mm f/1.4 DG HSM | A');
1328
+ case 251:
1329
+ return Pel::tra('Canon EF 70-200mm f/2.8L IS II USM');
1330
+ case 252:
1331
+ return Pel::tra('Canon EF 70-200mm f/2.8L IS II USM + 1.4x');
1332
+ case 253:
1333
+ return Pel::tra('Canon EF 70-200mm f/2.8L IS II USM + 2x');
1334
+ case 254:
1335
+ return Pel::tra('Canon EF 100mm f/2.8L Macro IS USM');
1336
+ case 255:
1337
+ return Pel::tra('Sigma 24-105mm f/4 DG OS HSM | A or Other Sigma Lens');
1338
+ case 255.1:
1339
+ return Pel::tra('Sigma 180mm f/2.8 EX DG OS HSM APO Macro');
1340
+ case 488:
1341
+ return Pel::tra('Canon EF-S 15-85mm f/3.5-5.6 IS USM');
1342
+ case 489:
1343
+ return Pel::tra('Canon EF 70-300mm f/4-5.6L IS USM');
1344
+ case 490:
1345
+ return Pel::tra('Canon EF 8-15mm f/4L Fisheye USM');
1346
+ case 491:
1347
+ return Pel::tra('Canon EF 300mm f/2.8L IS II USM or Tamron Lens');
1348
+ case 491.1:
1349
+ return Pel::tra('Tamron SP 70-200mm F/2.8 Di VC USD G2 (A025)');
1350
+ case 491.2:
1351
+ return Pel::tra('Tamron 18-400mm F/3.5-6.3 Di II VC HLD (B028)');
1352
+ case 492:
1353
+ return Pel::tra('Canon EF 400mm f/2.8L IS II USM');
1354
+ case 493:
1355
+ return Pel::tra('Canon EF 500mm f/4L IS II USM or EF 24-105mm f4L IS USM');
1356
+ case 493.1:
1357
+ return Pel::tra('Canon EF 24-105mm f/4L IS USM');
1358
+ case 494:
1359
+ return Pel::tra('Canon EF 600mm f/4.0L IS II USM');
1360
+ case 495:
1361
+ return Pel::tra('Canon EF 24-70mm f/2.8L II USM or Sigma Lens');
1362
+ case 495.1:
1363
+ return Pel::tra('Sigma 24-70mm F2.8 DG OS HSM | A');
1364
+ case 496:
1365
+ return Pel::tra('Canon EF 200-400mm f/4L IS USM');
1366
+ case 499:
1367
+ return Pel::tra('Canon EF 200-400mm f/4L IS USM + 1.4x');
1368
+ case 502:
1369
+ return Pel::tra('Canon EF 28mm f/2.8 IS USM');
1370
+ case 503:
1371
+ return Pel::tra('Canon EF 24mm f/2.8 IS USM');
1372
+ case 504:
1373
+ return Pel::tra('Canon EF 24-70mm f/4L IS USM');
1374
+ case 505:
1375
+ return Pel::tra('Canon EF 35mm f/2 IS USM');
1376
+ case 506:
1377
+ return Pel::tra('Canon EF 400mm f/4 DO IS II USM');
1378
+ case 507:
1379
+ return Pel::tra('Canon EF 16-35mm f/4L IS USM');
1380
+ case 508:
1381
+ return Pel::tra('Canon EF 11-24mm f/4L USM or Tamron Lens');
1382
+ case 508.1:
1383
+ return Pel::tra('Tamron 10-24mm f/3.5-4.5 Di II VC HLD');
1384
+ case 747:
1385
+ return Pel::tra('Canon EF 100-400mm f/4.5-5.6L IS II USM or Tamron Lens');
1386
+ case 747.1:
1387
+ return Pel::tra('Tamron SP 150-600mm F5-6.3 Di VC USD G2');
1388
+ case 748:
1389
+ return Pel::tra('Canon EF 100-400mm f/4.5-5.6L IS II USM + 1.4x');
1390
+ case 750:
1391
+ return Pel::tra('Canon EF 35mm f/1.4L II USM');
1392
+ case 751:
1393
+ return Pel::tra('Canon EF 16-35mm f/2.8L III USM');
1394
+ case 752:
1395
+ return Pel::tra('Canon EF 24-105mm f/4L IS II USM');
1396
+ case 4142:
1397
+ return Pel::tra('Canon EF-S 18-135mm f/3.5-5.6 IS STM');
1398
+ case 4143:
1399
+ return Pel::tra('Canon EF-M 18-55mm f/3.5-5.6 IS STM or Tamron Lens');
1400
+ case 4143.1:
1401
+ return Pel::tra('Tamron 18-200mm F/3.5-6.3 Di III VC');
1402
+ case 4144:
1403
+ return Pel::tra('Canon EF 40mm f/2.8 STM');
1404
+ case 4145:
1405
+ return Pel::tra('Canon EF-M 22mm f/2 STM');
1406
+ case 4146:
1407
+ return Pel::tra('Canon EF-S 18-55mm f/3.5-5.6 IS STM');
1408
+ case 4147:
1409
+ return Pel::tra('Canon EF-M 11-22mm f/4-5.6 IS STM');
1410
+ case 4148:
1411
+ return Pel::tra('Canon EF-S 55-250mm f/4-5.6 IS STM');
1412
+ case 4149:
1413
+ return Pel::tra('Canon EF-M 55-200mm f/4.5-6.3 IS STM');
1414
+ case 4150:
1415
+ return Pel::tra('Canon EF-S 10-18mm f/4.5-5.6 IS STM');
1416
+ case 4152:
1417
+ return Pel::tra('Canon EF 24-105mm f/3.5-5.6 IS STM');
1418
+ case 4153:
1419
+ return Pel::tra('Canon EF-M 15-45mm f/3.5-6.3 IS STM');
1420
+ case 4154:
1421
+ return Pel::tra('Canon EF-S 24mm f/2.8 STM');
1422
+ case 4155:
1423
+ return Pel::tra('Canon EF-M 28mm f/3.5 Macro IS STM');
1424
+ case 4156:
1425
+ return Pel::tra('Canon EF 50mm f/1.8 STM');
1426
+ case 4157:
1427
+ return Pel::tra('Canon EF-M 18-150mm 1:3.5-6.3 IS STM');
1428
+ case 4158:
1429
+ return Pel::tra('Canon EF-S 18-55mm f/4-5.6 IS STM');
1430
+ case 4160:
1431
+ return Pel::tra('Canon EF-S 35mm f/2.8 Macro IS STM');
1432
+ case 36910:
1433
+ return Pel::tra('Canon EF 70-300mm f/4-5.6 IS II USM');
1434
+ case 36912:
1435
+ return Pel::tra('Canon EF-S 18-135mm f/3.5-5.6 IS USM');
1436
+ case 61494:
1437
+ return Pel::tra('Canon CN-E 85mm T1.3 L F');
1438
+ default:
1439
+ return $this->value[0];
1440
+ }
1441
+ break;
1442
+ case PelTag::CANON_CS_FOCUS_CONTINUOUS:
1443
+ // CC (e->components, 1, v);
1444
+ switch ($this->value[0]) {
1445
+ case 0:
1446
+ return Pel::tra('Single');
1447
+ case 1:
1448
+ return Pel::tra('Continuous');
1449
+ case 8:
1450
+ return Pel::tra('Manual');
1451
+ default:
1452
+ return $this->value[0];
1453
+ }
1454
+ break;
1455
+ case PelTag::CANON_CS_AE_SETTING:
1456
+ // CC (e->components, 1, v);
1457
+ switch ($this->value[0]) {
1458
+ case 0:
1459
+ return Pel::tra('Normal AE');
1460
+ case 1:
1461
+ return Pel::tra('Exposure Compensation');
1462
+ case 2:
1463
+ return Pel::tra('AE Lock');
1464
+ case 3:
1465
+ return Pel::tra('AE Lock + Exposure Comp.');
1466
+ case 4:
1467
+ return Pel::tra('No AE');
1468
+ default:
1469
+ return $this->value[0];
1470
+ }
1471
+ break;
1472
+ case PelTag::CANON_CS_IMAGE_STABILIZATION:
1473
+ // CC (e->components, 1, v);
1474
+ switch ($this->value[0]) {
1475
+ case 0:
1476
+ return Pel::tra('Off');
1477
+ case 1:
1478
+ return Pel::tra('On');
1479
+ case 2:
1480
+ return Pel::tra('Shoot Only');
1481
+ case 3:
1482
+ return Pel::tra('Panning');
1483
+ case 4:
1484
+ return Pel::tra('Dynamic');
1485
+ case 256:
1486
+ return Pel::tra('Off (2)');
1487
+ case 257:
1488
+ return Pel::tra('On (2)');
1489
+ case 258:
1490
+ return Pel::tra('Shoot Only (2)');
1491
+ case 259:
1492
+ return Pel::tra('Panning (2)');
1493
+ case 260:
1494
+ return Pel::tra('Dynamic (2)');
1495
+ default:
1496
+ return $this->value[0];
1497
+ }
1498
+ break;
1499
+ case PelTag::CANON_CS_SPOT_METERING_MODE:
1500
+ // CC (e->components, 1, v);
1501
+ switch ($this->value[0]) {
1502
+ case 0:
1503
+ return Pel::tra('Center');
1504
+ case 1:
1505
+ return Pel::tra('AF Point');
1506
+ default:
1507
+ return $this->value[0];
1508
+ }
1509
+ break;
1510
+ case PelTag::CANON_CS_PHOTO_EFFECT:
1511
+ // CC (e->components, 1, v);
1512
+ switch ($this->value[0]) {
1513
+ case 0:
1514
+ return Pel::tra('Off');
1515
+ case 1:
1516
+ return Pel::tra('Vivid');
1517
+ case 2:
1518
+ return Pel::tra('Neutral');
1519
+ case 3:
1520
+ return Pel::tra('Smooth');
1521
+ case 4:
1522
+ return Pel::tra('Sepia');
1523
+ case 5:
1524
+ return Pel::tra('B&W');
1525
+ case 6:
1526
+ return Pel::tra('Custom');
1527
+ case 100:
1528
+ return Pel::tra('My Color Data');
1529
+ default:
1530
+ return $this->value[0];
1531
+ }
1532
+ break;
1533
+ case PelTag::CANON_CS_MANUAL_FLASH_OUTPUT:
1534
+ // CC (e->components, 1, v);
1535
+ switch ($this->value[0]) {
1536
+ case 0x500:
1537
+ return Pel::tra('Full');
1538
+ case 0x502:
1539
+ return Pel::tra('Medium');
1540
+ case 0x504:
1541
+ return Pel::tra('Low');
1542
+ default:
1543
+ return $this->value[0];
1544
+ }
1545
+ break;
1546
+ case PelTag::CANON_CS_COLOR_TONE:
1547
+ // CC (e->components, 1, v);
1548
+ switch ($this->value[0]) {
1549
+ case 0:
1550
+ return Pel::tra('Normal');
1551
+ default:
1552
+ return $this->value[0];
1553
+ }
1554
+ break;
1555
+ case PelTag::CANON_CS_SRAW_QUALITY:
1556
+ // CC (e->components, 1, v);
1557
+ switch ($this->value[0]) {
1558
+ case 1:
1559
+ return Pel::tra('sRAW1 (mRAW)');
1560
+ case 2:
1561
+ return Pel::tra('sRAW2 (sRAW)');
1562
+ default:
1563
+ return $this->value[0];
1564
+ }
1565
+ break;
1566
+ default:
1567
+ return parent::getText($brief);
1568
+ }
1569
+ }
1570
  }
vendor/pel/src/PelEntryShort.php CHANGED
@@ -73,7 +73,7 @@ class PelEntryShort extends PelEntryNumber
73
  * instead of an array with one integer element, which would then
74
  * have to be extracted.
75
  *
76
- * @param PelTag $tag
77
  * the tag which this entry represents. This should be
78
  * one of the constants defined in {@link PelTag}, e.g., {@link
79
  * PelTag::IMAGE_WIDTH}, {@link PelTag::ISO_SPEED_RATINGS},
@@ -105,7 +105,7 @@ class PelEntryShort extends PelEntryNumber
105
  * @param int $number
106
  * the number that should be converted.
107
  *
108
- * @param PelByteOrder $order
109
  * one of {@link PelConvert::LITTLE_ENDIAN} and
110
  * {@link PelConvert::BIG_ENDIAN}, specifying the target byte order.
111
  *
@@ -132,6 +132,179 @@ class PelEntryShort extends PelEntryNumber
132
  */
133
  public function getText($brief = false)
134
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  switch ($this->tag) {
136
  case PelTag::METERING_MODE:
137
  // CC (e->components, 1, v);
73
  * instead of an array with one integer element, which would then
74
  * have to be extracted.
75
  *
76
+ * @param int $tag
77
  * the tag which this entry represents. This should be
78
  * one of the constants defined in {@link PelTag}, e.g., {@link
79
  * PelTag::IMAGE_WIDTH}, {@link PelTag::ISO_SPEED_RATINGS},
105
  * @param int $number
106
  * the number that should be converted.
107
  *
108
+ * @param boolean $order
109
  * one of {@link PelConvert::LITTLE_ENDIAN} and
110
  * {@link PelConvert::BIG_ENDIAN}, specifying the target byte order.
111
  *
132
  */
133
  public function getText($brief = false)
134
  {
135
+ if ($this->ifd_type == PelIfd::CANON_SHOT_INFO) {
136
+ switch ($this->tag) {
137
+ case PelTag::CANON_SI_WHITE_BALANCE:
138
+ // CC (e->components, 1, v);
139
+ switch ($this->value[0]) {
140
+ case 0:
141
+ return Pel::tra('Auto');
142
+ case 1:
143
+ return Pel::tra('Daylight');
144
+ case 2:
145
+ return Pel::tra('Cloudy');
146
+ case 3:
147
+ return Pel::tra('Tungsten');
148
+ case 4:
149
+ return Pel::tra('Fluorescent');
150
+ case 5:
151
+ return Pel::tra('Flash');
152
+ case 6:
153
+ return Pel::tra('Custom');
154
+ case 7:
155
+ return Pel::tra('Black & White');
156
+ case 8:
157
+ return Pel::tra('Shade');
158
+ case 9:
159
+ return Pel::tra('Manual Temperature (Kelvin)');
160
+ case 10:
161
+ return Pel::tra('PC Set1');
162
+ case 11:
163
+ return Pel::tra('PC Set2');
164
+ case 12:
165
+ return Pel::tra('PC Set3');
166
+ case 14:
167
+ return Pel::tra('Daylight Fluorescent');
168
+ case 15:
169
+ return Pel::tra('Custom 1');
170
+ case 16:
171
+ return Pel::tra('Custom 2');
172
+ case 17:
173
+ return Pel::tra('Underwater');
174
+ case 18:
175
+ return Pel::tra('Custom 3');
176
+ case 19:
177
+ return Pel::tra('Custom 4');
178
+ case 20:
179
+ return Pel::tra('PC Set4');
180
+ case 21:
181
+ return Pel::tra('PC Set5');
182
+ case 23:
183
+ return Pel::tra('Auto (ambience priority)');
184
+ default:
185
+ return $this->value[0];
186
+ }
187
+ break;
188
+ case PelTag::CANON_SI_SLOW_SHUTTER:
189
+ // CC (e->components, 1, v);
190
+ switch ($this->value[0]) {
191
+ case 0:
192
+ return Pel::tra('Off');
193
+ case 1:
194
+ return Pel::tra('Night Scene');
195
+ case 2:
196
+ return Pel::tra('On');
197
+ case 3:
198
+ return Pel::tra('None');
199
+ default:
200
+ return $this->value[0];
201
+ }
202
+ break;
203
+ case PelTag::CANON_SI_AF_POINT_USED:
204
+ // CC (e->components, 1, v);
205
+ switch ($this->value[0]) {
206
+ case 0x3000:
207
+ return Pel::tra('None (MF)');
208
+ case 0x3001:
209
+ return Pel::tra('Right');
210
+ case 0x3002:
211
+ return Pel::tra('Center');
212
+ case 0x3003:
213
+ return Pel::tra('Center+Right');
214
+ case 0x3004:
215
+ return Pel::tra('Left');
216
+ case 0x3005:
217
+ return Pel::tra('Left+Right');
218
+ case 0x3006:
219
+ return Pel::tra('Left+Center');
220
+ case 0x3007:
221
+ return Pel::tra('All');
222
+ default:
223
+ return $this->value[0];
224
+ }
225
+ break;
226
+ case PelTag::CANON_SI_AUTO_EXPOSURE_BRACKETING:
227
+ // CC (e->components, 1, v);
228
+ switch ($this->value[0]) {
229
+ case -1:
230
+ return Pel::tra('On');
231
+ case 0:
232
+ return Pel::tra('Off');
233
+ case 1:
234
+ return Pel::tra('On (shot 1)');
235
+ case 2:
236
+ return Pel::tra('On (shot 2)');
237
+ case 3:
238
+ return Pel::tra('On (shot 3)');
239
+ default:
240
+ return $this->value[0];
241
+ }
242
+ break;
243
+ case PelTag::CANON_SI_CAMERA_TYPE:
244
+ // CC (e->components, 1, v);
245
+ switch ($this->value[0]) {
246
+ case 248:
247
+ return Pel::tra('EOS High-end');
248
+ case 250:
249
+ return Pel::tra('Compact');
250
+ case 252:
251
+ return Pel::tra('EOS Mid-range');
252
+ case 255:
253
+ return Pel::tra('DV Camera');
254
+ default:
255
+ return $this->value[0];
256
+ }
257
+ break;
258
+ case PelTag::CANON_SI_AUTO_ROTATE:
259
+ // CC (e->components, 1, v);
260
+ switch ($this->value[0]) {
261
+ case 0:
262
+ return Pel::tra('None');
263
+ case 1:
264
+ return Pel::tra('Rotate 90 CW');
265
+ case 2:
266
+ return Pel::tra('Rotate 180');
267
+ case 3:
268
+ return Pel::tra('Rotate 270 CW');
269
+ default:
270
+ return $this->value[0];
271
+ }
272
+ break;
273
+ case PelTag::CANON_SI_ND_FILTER:
274
+ // CC (e->components, 1, v);
275
+ switch ($this->value[0]) {
276
+ case 0:
277
+ return Pel::tra('Off');
278
+ case 1:
279
+ return Pel::tra('On');
280
+ default:
281
+ return $this->value[0];
282
+ }
283
+ break;
284
+ default:
285
+ return $this->value[0];
286
+ }
287
+ }
288
+ if ($this->ifd_type == PelIfd::CANON_PANORAMA) {
289
+ switch ($this->tag) {
290
+ case PelTag::CANON_PA_PANORAMA_DIRECTION:
291
+ // CC (e->components, 1, v);
292
+ switch ($this->value[0]) {
293
+ case 0:
294
+ return Pel::tra('Left to Right');
295
+ case 1:
296
+ return Pel::tra('Right to Left');
297
+ case 2:
298
+ return Pel::tra('Bottom to Top');
299
+ case 3:
300
+ return Pel::tra('Top to Bottom');
301
+ case 4:
302
+ return Pel::tra('2x2 Matrix (Clockwise)');
303
+ default:
304
+ return $this->value[0];
305
+ }
306
+ }
307
+ }
308
  switch ($this->tag) {
309
  case PelTag::METERING_MODE:
310
  // CC (e->components, 1, v);
vendor/pel/src/PelIfd.php CHANGED
@@ -86,6 +86,87 @@ class PelIfd implements \IteratorAggregate, \ArrayAccess
86
  */
87
  const INTEROPERABILITY = 4;
88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  /**
90
  * The entries held by this directory.
91
  *
@@ -154,14 +235,49 @@ class PelIfd implements \IteratorAggregate, \ArrayAccess
154
  */
155
  public function __construct($type)
156
  {
157
- if ($type != PelIfd::IFD0 && $type != PelIfd::IFD1 && $type != PelIfd::EXIF && $type != PelIfd::GPS &&
158
- $type != PelIfd::INTEROPERABILITY) {
159
  throw new PelIfdException('Unknown IFD type: %d', $type);
160
  }
161
 
162
  $this->type = $type;
163
  }
164
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  /**
166
  * Load data into a Image File Directory (IFD).
167
  *
@@ -174,6 +290,8 @@ class PelIfd implements \IteratorAggregate, \ArrayAccess
174
  */
175
  public function load(PelDataWindow $d, $offset)
176
  {
 
 
177
  $thumb_offset = 0;
178
  $thumb_length = 0;
179
 
@@ -205,6 +323,8 @@ class PelIfd implements \IteratorAggregate, \ArrayAccess
205
  case PelTag::EXIF_IFD_POINTER:
206
  case PelTag::GPS_INFO_IFD_POINTER:
207
  case PelTag::INTEROPERABILITY_IFD_POINTER:
 
 
208
  $o = $d->getLong($offset + 12 * $i + 8);
209
  Pel::debug('Found sub IFD at offset %d', $o);
210
 
@@ -215,10 +335,25 @@ class PelIfd implements \IteratorAggregate, \ArrayAccess
215
  $type = PelIfd::GPS;
216
  } elseif ($tag == PelTag::INTEROPERABILITY_IFD_POINTER) {
217
  $type = PelIfd::INTEROPERABILITY;
 
 
 
 
 
 
218
  }
219
 
220
- $this->sub[$type] = new PelIfd($type);
221
- $this->sub[$type]->load($d, $o);
 
 
 
 
 
 
 
 
 
222
  break;
223
  case PelTag::JPEG_INTERCHANGE_FORMAT:
224
  $thumb_offset = $d->getLong($offset + 12 * $i + 8);
@@ -229,41 +364,7 @@ class PelIfd implements \IteratorAggregate, \ArrayAccess
229
  $this->safeSetThumbnail($d, $thumb_offset, $thumb_length);
230
  break;
231
  default:
232
- $format = $d->getShort($offset + 12 * $i + 2);
233
- $components = $d->getLong($offset + 12 * $i + 4);
234
-
235
- /*
236
- * The data size. If bigger than 4 bytes, the actual data is
237
- * not in the entry but somewhere else, with the offset stored
238
- * in the entry.
239
- */
240
- $s = PelFormat::getSize($format) * $components;
241
- if ($s > 0) {
242
- $doff = $offset + 12 * $i + 8;
243
- if ($s > 4) {
244
- $doff = $d->getLong($doff);
245
- }
246
- $data = $d->getClone($doff, $s);
247
- } else {
248
- $data = new PelDataWindow();
249
- }
250
-
251
- try {
252
- $entry = $this->newEntryFromData($tag, $format, $components, $data);
253
- $this->addEntry($entry);
254
- } catch (PelException $e) {
255
- /*
256
- * Throw the exception when running in strict mode, store
257
- * otherwise.
258
- */
259
- Pel::maybeThrow($e);
260
- }
261
-
262
- /* The format of the thumbnail is stored in this tag. */
263
- // TODO: handle TIFF thumbnail.
264
- // if ($tag == PelTag::COMPRESSION) {
265
- // $this->thumb_format = $data->getShort();
266
- // }
267
  break;
268
  }
269
  }
@@ -287,6 +388,145 @@ class PelIfd implements \IteratorAggregate, \ArrayAccess
287
  } else {
288
  Pel::debug('Last IFD.');
289
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
  }
291
 
292
  /**
@@ -424,7 +664,13 @@ class PelIfd implements \IteratorAggregate, \ArrayAccess
424
  return $v;
425
 
426
  case PelFormat::ASCII:
427
- return new PelEntryAscii($tag, rtrim($data->getBytes(0), "\0"));
 
 
 
 
 
 
428
 
429
  case PelFormat::SHORT:
430
  $v = new PelEntryShort($tag);
@@ -519,7 +765,11 @@ class PelIfd implements \IteratorAggregate, \ArrayAccess
519
  }
520
 
521
  /* Now set the thumbnail normally. */
522
- $this->setThumbnail($d->getClone($offset, $length));
 
 
 
 
523
  }
524
  }
525
 
@@ -572,7 +822,7 @@ class PelIfd implements \IteratorAggregate, \ArrayAccess
572
  * treated as private tags and will be allowed everywhere (use this
573
  * for testing or for implementing your own types of tags).
574
  *
575
- * @param PelTag $tag
576
  * the tag.
577
  *
578
  * @return boolean true if the tag is considered valid in this IFD,
@@ -636,7 +886,8 @@ class PelIfd implements \IteratorAggregate, \ArrayAccess
636
  PelTag::XP_AUTHOR,
637
  PelTag::XP_KEYWORDS,
638
  PelTag::XP_SUBJECT,
639
- PelTag::RATING
 
640
  );
641
 
642
  case PelIfd::EXIF:
@@ -650,6 +901,9 @@ class PelIfd implements \IteratorAggregate, \ArrayAccess
650
  PelTag::EXIF_VERSION,
651
  PelTag::DATE_TIME_ORIGINAL,
652
  PelTag::DATE_TIME_DIGITIZED,
 
 
 
653
  PelTag::COMPONENTS_CONFIGURATION,
654
  PelTag::COMPRESSED_BITS_PER_PIXEL,
655
  PelTag::SHUTTER_SPEED_VALUE,
@@ -743,6 +997,133 @@ class PelIfd implements \IteratorAggregate, \ArrayAccess
743
  PelTag::RELATED_IMAGE_WIDTH,
744
  PelTag::RELATED_IMAGE_LENGTH
745
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
746
 
747
  /*
748
  * TODO: Where do these tags belong?
@@ -780,6 +1161,14 @@ class PelIfd implements \IteratorAggregate, \ArrayAccess
780
  return 'GPS';
781
  case self::INTEROPERABILITY:
782
  return 'Interoperability';
 
 
 
 
 
 
 
 
783
  default:
784
  throw new PelIfdException('Unknown IFD type: %d', $type);
785
  }
@@ -829,7 +1218,7 @@ class PelIfd implements \IteratorAggregate, \ArrayAccess
829
  * // ... do something with the F-number.
830
  * </code>
831
  *
832
- * @param PelTag $tag
833
  * the offset to check.
834
  *
835
  * @return boolean whether the tag exists.
@@ -850,7 +1239,7 @@ class PelIfd implements \IteratorAggregate, \ArrayAccess
850
  * $entry = $ifd[PelTag::FNUMBER];
851
  * </code>
852
  *
853
- * @param PelTag $tag
854
  * the tag to return. It is an error to ask for a tag
855
  * which is not in the IFD, just like asking for a non-existant
856
  * array entry.
@@ -876,8 +1265,8 @@ class PelIfd implements \IteratorAggregate, \ArrayAccess
876
  * Note that the actual array index passed is ignored! Instead the
877
  * {@link PelTag} from the entry is used.
878
  *
879
- * @param PelTag $tag
880
- * the offset to update.
881
  *
882
  * @param PelEntry $e
883
  * the new value.
@@ -903,7 +1292,7 @@ class PelIfd implements \IteratorAggregate, \ArrayAccess
903
  * unset($ifd[PelTag::EXPOSURE_BIAS_VALUE])
904
  * </code>
905
  *
906
- * @param PelTag $tag
907
  * the offset to delete.
908
  */
909
  public function offsetUnset($tag)
@@ -914,7 +1303,7 @@ class PelIfd implements \IteratorAggregate, \ArrayAccess
914
  /**
915
  * Retrieve an entry.
916
  *
917
- * @param PelTag $tag
918
  * the tag identifying the entry.
919
  *
920
  * @return PelEntry the entry associated with the tag, or null if no
@@ -1072,7 +1461,7 @@ class PelIfd implements \IteratorAggregate, \ArrayAccess
1072
  * @param int $offset
1073
  * the offset of the first byte of this directory.
1074
  *
1075
- * @param PelByteOrder $order
1076
  * the byte order that should be used when
1077
  * turning integers into bytes. This should be one of {@link
1078
  * PelConvert::LITTLE_ENDIAN} and {@link PelConvert::BIG_ENDIAN}.
86
  */
87
  const INTEROPERABILITY = 4;
88
 
89
+ /**
90
+ * Canon Maker Notes IFD.
91
+ *
92
+ * Pass this to the constructor when creating an IFD which will be
93
+ * the canon maker notes sub-IFD.
94
+ */
95
+ const CANON_MAKER_NOTES = 5;
96
+
97
+ /**
98
+ * Canon Camera Settings IFD.
99
+ *
100
+ * Pass this to the constructor when creating an IFD which will be
101
+ * the canon maker notes sub-IFD.
102
+ */
103
+ const CANON_CAMERA_SETTINGS = 6;
104
+
105
+ /**
106
+ * Canon Shot Info IFD.
107
+ *
108
+ * Pass this to the constructor when creating an IFD which will be
109
+ * the canon maker notes sub-IFD.
110
+ */
111
+ const CANON_SHOT_INFO = 7;
112
+
113
+ /**
114
+ * Canon Shot Info IFD.
115
+ *
116
+ * Pass this to the constructor when creating an IFD which will be
117
+ * the canon maker notes sub-IFD.
118
+ */
119
+ const CANON_PANORAMA = 8;
120
+
121
+ /**
122
+ * Canon Shot Info IFD.
123
+ *
124
+ * Pass this to the constructor when creating an IFD which will be
125
+ * the canon maker notes sub-IFD.
126
+ */
127
+ const CANON_PICTURE_INFO = 9;
128
+
129
+ /**
130
+ * Canon Shot Info IFD.
131
+ *
132
+ * Pass this to the constructor when creating an IFD which will be
133
+ * the canon maker notes sub-IFD.
134
+ */
135
+ const CANON_FILE_INFO = 10;
136
+
137
+ /**
138
+ * Canon Shot Info IFD.
139
+ *
140
+ * Pass this to the constructor when creating an IFD which will be
141
+ * the canon maker notes sub-IFD.
142
+ */
143
+ const CANON_CUSTOM_FUNCTIONS = 11;
144
+
145
+ private $ifdTypes = array(
146
+ self::IFD0,
147
+ self::IFD1,
148
+ self::EXIF,
149
+ self::GPS,
150
+ self::INTEROPERABILITY,
151
+ self::CANON_MAKER_NOTES,
152
+ self::CANON_CAMERA_SETTINGS,
153
+ self::CANON_SHOT_INFO,
154
+ self::CANON_PANORAMA,
155
+ self::CANON_PICTURE_INFO,
156
+ self::CANON_FILE_INFO,
157
+ self::CANON_CUSTOM_FUNCTIONS
158
+ );
159
+
160
+ /**
161
+ * The maker notes held by this directory.
162
+ *
163
+ * Stores information of the MakerNotes IFD.
164
+ * Available and required keys are: parent, data, components and offset
165
+ *
166
+ * @var array
167
+ */
168
+ private $maker_notes = array();
169
+
170
  /**
171
  * The entries held by this directory.
172
  *
235
  */
236
  public function __construct($type)
237
  {
238
+ if (!in_array($type, $this->ifdTypes)) {
 
239
  throw new PelIfdException('Unknown IFD type: %d', $type);
240
  }
241
 
242
  $this->type = $type;
243
  }
244
 
245
+ /**
246
+ * Stores Maker Notes data for an IFD (Probably PelIfd::EXIF only).
247
+ *
248
+ * @param PelIfd $parent
249
+ * the parent PelIfd of the current PelIfd
250
+ *
251
+ * @param PelDataWindow $data
252
+ * the data window that will provide the data.
253
+ *
254
+ * @param PelIfd $parent
255
+ * the components in the entry.
256
+ *
257
+ * @param int $offset
258
+ * the offset within the window where the directory will
259
+ * be found.
260
+ */
261
+ public function setMakerNotes($parent, $data, $components, $offset)
262
+ {
263
+ $this->maker_notes = array(
264
+ 'parent' => $parent,
265
+ 'data' => $data,
266
+ 'components' => $components,
267
+ 'offset' => $offset
268
+ );
269
+ }
270
+
271
+ /**
272
+ * Returns the Maker Notes data for an IFD (Probably PelIfd::EXIF only).
273
+ *
274
+ * @return array The maker_notes of IDF
275
+ */
276
+ public function getMakerNotes()
277
+ {
278
+ return $this->maker_notes;
279
+ }
280
+
281
  /**
282
  * Load data into a Image File Directory (IFD).
283
  *
290
  */
291
  public function load(PelDataWindow $d, $offset)
292
  {
293
+ $starting_offset = $offset;
294
+
295
  $thumb_offset = 0;
296
  $thumb_length = 0;
297
 
323
  case PelTag::EXIF_IFD_POINTER:
324
  case PelTag::GPS_INFO_IFD_POINTER:
325
  case PelTag::INTEROPERABILITY_IFD_POINTER:
326
+ case PelTag::MAKER_NOTE:
327
+ $components = $d->getLong($offset + 12 * $i + 4);
328
  $o = $d->getLong($offset + 12 * $i + 8);
329
  Pel::debug('Found sub IFD at offset %d', $o);
330
 
335
  $type = PelIfd::GPS;
336
  } elseif ($tag == PelTag::INTEROPERABILITY_IFD_POINTER) {
337
  $type = PelIfd::INTEROPERABILITY;
338
+ } elseif ($tag == PelTag::MAKER_NOTE) {
339
+ // Store maker notes infos, because we need PelTag::MAKE of PelIfd::IFD0 for MakerNotes
340
+ // Thus MakerNotes will be loaded at the end of loading PelIfd::IFD0
341
+ $this->setMakerNotes($this, $d, $components, $o);
342
+ $this->loadSingleValue($d, $offset, $i, $tag);
343
+ break;
344
  }
345
 
346
+ if ($starting_offset != $o) {
347
+ $ifd = new PelIfd($type);
348
+ try {
349
+ $ifd->load($d, $o);
350
+ $this->sub[$type] = $ifd;
351
+ } catch (PelDataWindowOffsetException $e) {
352
+ Pel::maybeThrow(new PelIfdException($e->getMessage()));
353
+ }
354
+ } else {
355
+ Pel::maybeThrow(new PelIfdException('Bogus offset to next IFD: %d, same as offset being loaded from.', $o));
356
+ }
357
  break;
358
  case PelTag::JPEG_INTERCHANGE_FORMAT:
359
  $thumb_offset = $d->getLong($offset + 12 * $i + 8);
364
  $this->safeSetThumbnail($d, $thumb_offset, $thumb_length);
365
  break;
366
  default:
367
+ $this->loadSingleValue($d, $offset, $i, $tag);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
368
  break;
369
  }
370
  }
388
  } else {
389
  Pel::debug('Last IFD.');
390
  }
391
+
392
+ // Check if we finished loading IFD0 and EXIF IFD is set (EXIF IFD holds the MakerNotes)
393
+ if ($this->type == PelIfd::IFD0 && isset($this->sub[PelIfd::EXIF])) {
394
+ // Get MakerNotes from EXIF IFD and check if they are set
395
+ $mk = $this->sub[PelIfd::EXIF]->getMakerNotes();
396
+ if (!empty($mk) && count($mk) > 0) {
397
+ // get Make tag and load maker notes if tag is valid
398
+ $manufacturer = $this->getEntry(PelTag::MAKE);
399
+ if ($manufacturer !== null) {
400
+ $manufacturer = $manufacturer->getValue();
401
+ $mkNotes = PelMakerNotes::createMakerNotesFromManufacturer($manufacturer, $mk['parent'], $mk['data'], $mk['components'], $mk['offset']);
402
+ if ($mkNotes !== null) {
403
+ // remove pre-loaded undefined MakerNotes
404
+ $mk['parent']->offsetUnset(PelTag::MAKER_NOTE);
405
+ $mkNotes->load();
406
+ }
407
+ }
408
+ }
409
+ }
410
+ }
411
+
412
+ /**
413
+ * Load a single value which didn't match any special {@link PelTag}.
414
+ *
415
+ * This method will add a single value given by the {@link PelDataWindow} and it's offset ($offset) and element counter ($i).
416
+ *
417
+ * Please note that the data you pass to this method should come
418
+ * from an image, that is, it should be raw bytes. If instead you
419
+ * want to create an entry for holding, say, an short integer, then
420
+ * create a {@link PelEntryShort} object directly and load the data
421
+ * into it.
422
+ *
423
+ * @param PelDataWindow $d
424
+ * the data window that will provide the data.
425
+ *
426
+ * @param integer $offset
427
+ * the offset within the window where the directory will
428
+ * be found.
429
+ *
430
+ * @param int $i
431
+ * the element's position in the {@link PelDataWindow} $d.
432
+ *
433
+ * @param int $tag
434
+ * the tag of the entry as defined in {@link PelTag}.
435
+ */
436
+ public function loadSingleValue($d, $offset, $i, $tag)
437
+ {
438
+ $format = $d->getShort($offset + 12 * $i + 2);
439
+ $components = $d->getLong($offset + 12 * $i + 4);
440
+
441
+ /*
442
+ * The data size. If bigger than 4 bytes, the actual data is
443
+ * not in the entry but somewhere else, with the offset stored
444
+ * in the entry.
445
+ */
446
+ $s = PelFormat::getSize($format) * $components;
447
+ if ($s > 0) {
448
+ $doff = $offset + 12 * $i + 8;
449
+ if ($s > 4) {
450
+ $doff = $d->getLong($doff);
451
+ }
452
+ $data = $d->getClone($doff, $s);
453
+ } else {
454
+ $data = new PelDataWindow();
455
+ }
456
+
457
+ try {
458
+ $entry = $this->newEntryFromData($tag, $format, $components, $data);
459
+ $this->addEntry($entry);
460
+ } catch (PelException $e) {
461
+ /*
462
+ * Throw the exception when running in strict mode, store
463
+ * otherwise.
464
+ */
465
+ Pel::maybeThrow($e);
466
+ }
467
+
468
+ /* The format of the thumbnail is stored in this tag. */
469
+ // TODO: handle TIFF thumbnail.
470
+ // if ($tag == PelTag::COMPRESSION) {
471
+ // $this->thumb_format = $data->getShort();
472
+ // }
473
+ }
474
+
475
+ /**
476
+ * Load a single value which didn't match any special {@link PelTag}.
477
+ *
478
+ * This method will add a single value given by the {@link PelDataWindow} and it's offset ($offset) and element counter ($i).
479
+ *
480
+ * Please note that the data you pass to this method should come
481
+ * from an image, that is, it should be raw bytes. If instead you
482
+ * want to create an entry for holding, say, an short integer, then
483
+ * create a {@link PelEntryShort} object directly and load the data
484
+ * into it.
485
+ *
486
+ * @param int $type
487
+ * the type of the ifd
488
+ *
489
+ * @param PelDataWindow $data
490
+ * the data window that will provide the data.
491
+ *
492
+ * @param integer $offset
493
+ * the offset within the window where the directory will
494
+ * be found.
495
+ *
496
+ * @param int $size
497
+ * the size in bytes of the maker notes section
498
+ *
499
+ * @param int $i
500
+ * the element's position in the {@link PelDataWindow} $data.
501
+ *
502
+ * @param int $format
503
+ * the format {@link PelFormat} of the entry.
504
+ */
505
+ public function loadSingleMakerNotesValue($type, $data, $offset, $size, $i, $format)
506
+ {
507
+ $elemSize = PelFormat::getSize($format);
508
+ if ($size > 0) {
509
+ $subdata = $data->getClone($offset + $i * $elemSize, $elemSize);
510
+ } else {
511
+ $subdata = new PelDataWindow();
512
+ }
513
+
514
+ try {
515
+ $entry = $this->newEntryFromData($i + 1, $format, 1, $subdata);
516
+ $this->addEntry($entry);
517
+ } catch (PelException $e) {
518
+ /*
519
+ * Throw the exception when running in strict mode, store
520
+ * otherwise.
521
+ */
522
+ Pel::maybeThrow($e);
523
+ }
524
+
525
+ /* The format of the thumbnail is stored in this tag. */
526
+ // TODO: handle TIFF thumbnail.
527
+ // if ($tag == PelTag::COMPRESSION) {
528
+ // $this->thumb_format = $data->getShort();
529
+ // }
530
  }
531
 
532
  /**
664
  return $v;
665
 
666
  case PelFormat::ASCII:
667
+ // cut off string after the first nul byte
668
+ $canonicalString = strstr($data->getBytes(0), "\0", true);
669
+ if ($canonicalString !== false) {
670
+ return new PelEntryAscii($tag, $canonicalString);
671
+ }
672
+ // TODO throw exception if string isn't nul-terminated
673
+ return new PelEntryAscii($tag, $data->getBytes(0));
674
 
675
  case PelFormat::SHORT:
676
  $v = new PelEntryShort($tag);
765
  }
766
 
767
  /* Now set the thumbnail normally. */
768
+ try {
769
+ $this->setThumbnail($d->getClone($offset, $length));
770
+ } catch (PelDataWindowWindowException $e) {
771
+ Pel::maybeThrow(new PelIfdException($e->getMessage()));
772
+ }
773
  }
774
  }
775
 
822
  * treated as private tags and will be allowed everywhere (use this
823
  * for testing or for implementing your own types of tags).
824
  *
825
+ * @param int $tag
826
  * the tag.
827
  *
828
  * @return boolean true if the tag is considered valid in this IFD,
886
  PelTag::XP_AUTHOR,
887
  PelTag::XP_KEYWORDS,
888
  PelTag::XP_SUBJECT,
889
+ PelTag::RATING,
890
+ PelTag::RATING_PERCENT
891
  );
892
 
893
  case PelIfd::EXIF:
901
  PelTag::EXIF_VERSION,
902
  PelTag::DATE_TIME_ORIGINAL,
903
  PelTag::DATE_TIME_DIGITIZED,
904
+ PelTag::OFFSET_TIME,
905
+ PelTag::OFFSET_TIME_ORIGINAL,
906
+ PelTag::OFFSET_TIME_DIGITIZED,
907
  PelTag::COMPONENTS_CONFIGURATION,
908
  PelTag::COMPRESSED_BITS_PER_PIXEL,
909
  PelTag::SHUTTER_SPEED_VALUE,
997
  PelTag::RELATED_IMAGE_WIDTH,
998
  PelTag::RELATED_IMAGE_LENGTH
999
  );
1000
+ case PelIfd::CANON_MAKER_NOTES:
1001
+ return array(
1002
+ PelTag::CANON_CAMERA_SETTINGS,
1003
+ PelTag::CANON_FOCAL_LENGTH,
1004
+ PelTag::CANON_SHOT_INFO,
1005
+ PelTag::CANON_PANORAMA,
1006
+ PelTag::CANON_IMAGE_TYPE,
1007
+ PelTag::CANON_FIRMWARE_VERSION,
1008
+ PelTag::CANON_FILE_NUMBER,
1009
+ PelTag::CANON_OWNER_NAME,
1010
+ PelTag::CANON_SERIAL_NUMBER,
1011
+ PelTag::CANON_CAMERA_INFO,
1012
+ PelTag::CANON_CUSTOM_FUNCTIONS,
1013
+ PelTag::CANON_MODEL_ID,
1014
+ PelTag::CANON_PICTURE_INFO,
1015
+ PelTag::CANON_THUMBNAIL_IMAGE_VALID_AREA,
1016
+ PelTag::CANON_SERIAL_NUMBER_FORMAT,
1017
+ PelTag::CANON_SUPER_MACRO,
1018
+ PelTag::CANON_FIRMWARE_REVISION,
1019
+ PelTag::CANON_AF_INFO,
1020
+ PelTag::CANON_ORIGINAL_DECISION_DATA_OFFSET,
1021
+ PelTag::CANON_WHITE_BALANCE_TABLE,
1022
+ PelTag::CANON_LENS_MODEL,
1023
+ PelTag::CANON_INTERNAL_SERIAL_NUMBER,
1024
+ PelTag::CANON_DUST_REMOVAL_DATA,
1025
+ PelTag::CANON_CUSTOM_FUNCTIONS_2,
1026
+ PelTag::CANON_PROCESSING_INFO,
1027
+ PelTag::CANON_MEASURED_COLOR,
1028
+ PelTag::CANON_COLOR_SPACE,
1029
+ PelTag::CANON_VRD_OFFSET,
1030
+ PelTag::CANON_SENSOR_INFO,
1031
+ PelTag::CANON_COLOR_DATA
1032
+ );
1033
+ case PelIfd::CANON_CAMERA_SETTINGS:
1034
+ return array(
1035
+ PelTag::CANON_CS_MACRO,
1036
+ PelTag::CANON_CS_SELF_TIMER,
1037
+ PelTag::CANON_CS_QUALITY,
1038
+ PelTag::CANON_CS_FLASH_MODE,
1039
+ PelTag::CANON_CS_DRIVE_MODE,
1040
+ PelTag::CANON_CS_FOCUS_MODE,
1041
+ PelTag::CANON_CS_RECORD_MODE,
1042
+ PelTag::CANON_CS_IMAGE_SIZE,
1043
+ PelTag::CANON_CS_EASY_MODE,
1044
+ PelTag::CANON_CS_DIGITAL_ZOOM,
1045
+ PelTag::CANON_CS_CONTRAST,
1046
+ PelTag::CANON_CS_SATURATION,
1047
+ PelTag::CANON_CS_SHARPNESS,
1048
+ PelTag::CANON_CS_ISO_SPEED,
1049
+ PelTag::CANON_CS_METERING_MODE,
1050
+ PelTag::CANON_CS_FOCUS_TYPE,
1051
+ PelTag::CANON_CS_AF_POINT,
1052
+ PelTag::CANON_CS_EXPOSURE_PROGRAM,
1053
+ PelTag::CANON_CS_LENS_TYPE,
1054
+ PelTag::CANON_CS_LENS,
1055
+ PelTag::CANON_CS_SHORT_FOCAL,
1056
+ PelTag::CANON_CS_FOCAL_UNITS,
1057
+ PelTag::CANON_CS_MAX_APERTURE,
1058
+ PelTag::CANON_CS_MIN_APERTURE,
1059
+ PelTag::CANON_CS_FLASH_ACTIVITY,
1060
+ PelTag::CANON_CS_FLASH_DETAILS,
1061
+ PelTag::CANON_CS_FOCUS_CONTINUOUS,
1062
+ PelTag::CANON_CS_AE_SETTING,
1063
+ PelTag::CANON_CS_IMAGE_STABILIZATION,
1064
+ PelTag::CANON_CS_DISPLAY_APERTURE,
1065
+ PelTag::CANON_CS_ZOOM_SOURCE_WIDTH,
1066
+ PelTag::CANON_CS_ZOOM_TARGET_WIDTH,
1067
+ PelTag::CANON_CS_SPOT_METERING_MODE,
1068
+ PelTag::CANON_CS_PHOTO_EFFECT,
1069
+ PelTag::CANON_CS_MANUAL_FLASH_OUTPUT,
1070
+ PelTag::CANON_CS_COLOR_TONE,
1071
+ PelTag::CANON_CS_SRAW_QUALITY
1072
+ );
1073
+ case PelIfd::CANON_SHOT_INFO:
1074
+ return array(
1075
+ PelTag::CANON_SI_ISO_SPEED,
1076
+ PelTag::CANON_SI_MEASURED_EV,
1077
+ PelTag::CANON_SI_TARGET_APERTURE,
1078
+ PelTag::CANON_SI_TARGET_SHUTTER_SPEED,
1079
+ PelTag::CANON_SI_WHITE_BALANCE,
1080
+ PelTag::CANON_SI_SLOW_SHUTTER,
1081
+ PelTag::CANON_SI_SEQUENCE,
1082
+ PelTag::CANON_SI_AF_POINT_USED,
1083
+ PelTag::CANON_SI_FLASH_BIAS,
1084
+ PelTag::CANON_SI_AUTO_EXPOSURE_BRACKETING,
1085
+ PelTag::CANON_SI_SUBJECT_DISTANCE,
1086
+ PelTag::CANON_SI_APERTURE_VALUE,
1087
+ PelTag::CANON_SI_SHUTTER_SPEED_VALUE,
1088
+ PelTag::CANON_SI_MEASURED_EV2,
1089
+ PelTag::CANON_SI_CAMERA_TYPE,
1090
+ PelTag::CANON_SI_AUTO_ROTATE,
1091
+ PelTag::CANON_SI_ND_FILTER
1092
+ );
1093
+ case PelIfd::CANON_PANORAMA:
1094
+ return array(
1095
+ PelTag::CANON_PA_PANORAMA_FRAME,
1096
+ PelTag::CANON_PA_PANORAMA_DIRECTION
1097
+ );
1098
+ case PelIfd::CANON_PICTURE_INFO:
1099
+ return array(
1100
+ PelTag::CANON_PI_IMAGE_WIDTH,
1101
+ PelTag::CANON_PI_IMAGE_HEIGHT,
1102
+ PelTag::CANON_PI_IMAGE_WIDTH_AS_SHOT,
1103
+ PelTag::CANON_PI_IMAGE_HEIGHT_AS_SHOT,
1104
+ PelTag::CANON_PI_AF_POINTS_USED,
1105
+ PelTag::CANON_PI_AF_POINTS_USED_20D
1106
+ );
1107
+ case PelIfd::CANON_FILE_INFO:
1108
+ return array(
1109
+ PelTag::CANON_FI_FILE_NUMBER,
1110
+ PelTag::CANON_FI_BRACKET_MODE,
1111
+ PelTag::CANON_FI_BRACKET_VALUE,
1112
+ PelTag::CANON_FI_BRACKET_SHOT_NUMBER,
1113
+ PelTag::CANON_FI_RAW_JPG_QUALITY,
1114
+ PelTag::CANON_FI_RAW_JPG_SIZE,
1115
+ PelTag::CANON_FI_NOISE_REDUCTION,
1116
+ PelTag::CANON_FI_WB_BRACKET_MODE,
1117
+ PelTag::CANON_FI_WB_BRACKET_VALUE_AB,
1118
+ PelTag::CANON_FI_WB_BRACKET_VALUE_GM,
1119
+ PelTag::CANON_FI_FILTER_EFFECT,
1120
+ PelTag::CANON_FI_TONING_EFFECT,
1121
+ PelTag::CANON_FI_MACRO_MAGNIFICATION,
1122
+ PelTag::CANON_FI_LIVE_VIEW_SHOOTING,
1123
+ PelTag::CANON_FI_FOCUS_DISTANCE_UPPER,
1124
+ PelTag::CANON_FI_FOCUS_DISTANCE_LOWER,
1125
+ PelTag::CANON_FI_FLASH_EXPOSURE_LOCK
1126
+ );
1127
 
1128
  /*
1129
  * TODO: Where do these tags belong?
1161
  return 'GPS';
1162
  case self::INTEROPERABILITY:
1163
  return 'Interoperability';
1164
+ case self::CANON_MAKER_NOTES:
1165
+ case self::CANON_CAMERA_SETTINGS:
1166
+ case self::CANON_SHOT_INFO:
1167
+ case self::CANON_PANORAMA:
1168
+ case self::CANON_PICTURE_INFO:
1169
+ case self::CANON_FILE_INFO:
1170
+ case self::CANON_CUSTOM_FUNCTIONS:
1171
+ return 'MakerNotes';
1172
  default:
1173
  throw new PelIfdException('Unknown IFD type: %d', $type);
1174
  }
1218
  * // ... do something with the F-number.
1219
  * </code>
1220
  *
1221
+ * @param int $tag
1222
  * the offset to check.
1223
  *
1224
  * @return boolean whether the tag exists.
1239
  * $entry = $ifd[PelTag::FNUMBER];
1240
  * </code>
1241
  *
1242
+ * @param int $tag
1243
  * the tag to return. It is an error to ask for a tag
1244
  * which is not in the IFD, just like asking for a non-existant
1245
  * array entry.
1265
  * Note that the actual array index passed is ignored! Instead the
1266
  * {@link PelTag} from the entry is used.
1267
  *
1268
+ * @param int $tag
1269
+ * unused.
1270
  *
1271
  * @param PelEntry $e
1272
  * the new value.
1292
  * unset($ifd[PelTag::EXPOSURE_BIAS_VALUE])
1293
  * </code>
1294
  *
1295
+ * @param int $tag
1296
  * the offset to delete.
1297
  */
1298
  public function offsetUnset($tag)
1303
  /**
1304
  * Retrieve an entry.
1305
  *
1306
+ * @param int $tag
1307
  * the tag identifying the entry.
1308
  *
1309
  * @return PelEntry the entry associated with the tag, or null if no
1461
  * @param int $offset
1462
  * the offset of the first byte of this directory.
1463
  *
1464
+ * @param boolean $order
1465
  * the byte order that should be used when
1466
  * turning integers into bytes. This should be one of {@link
1467
  * PelConvert::LITTLE_ENDIAN} and {@link PelConvert::BIG_ENDIAN}.
vendor/pel/src/PelJpeg.php CHANGED
@@ -78,7 +78,7 @@ class PelJpeg
78
  *
79
  * @var array
80
  */
81
- private $sections = array();
82
 
83
  /**
84
  * The JPEG image data.
@@ -120,11 +120,7 @@ class PelJpeg
120
 
121
  if (is_string($data)) {
122
  Pel::debug('Initializing PelJpeg object from %s', $data);
123
- try {
124
- $this->loadFile($data);
125
- } catch ( PelDataWindowOffsetException $e ) {
126
- return;
127
- }
128
  } elseif ($data instanceof PelDataWindow) {
129
  Pel::debug('Initializing PelJpeg object from PelDataWindow.');
130
  $this->load($data);
@@ -308,9 +304,10 @@ class PelJpeg
308
  $sections_count = count($this->sections);
309
  for ($i = 0; $i < $sections_count; $i ++) {
310
  if (! empty($this->sections[$i][0])) {
311
- if ($this->sections[$i][0] == PelJpegMarker::APP0) {
 
312
  $app0_offset = $i;
313
- } elseif ($this->sections[$i][0] == PelJpegMarker::APP1) {
314
  $app1_offset = $i;
315
  break;
316
  }
@@ -369,7 +366,7 @@ class PelJpeg
369
  }
370
 
371
  /**
372
- * Get Exif data.
373
  *
374
  * Use this to get the @{link PelExif Exif data} stored.
375
  *
@@ -378,9 +375,12 @@ class PelJpeg
378
  */
379
  public function getExif()
380
  {
381
- $exif = $this->getSection(PelJpegMarker::APP1);
382
- if ($exif instanceof PelExif) {
383
- return $exif;
 
 
 
384
  }
385
  return null;
386
  }
@@ -405,16 +405,18 @@ class PelJpeg
405
  /**
406
  * Clear any Exif data.
407
  *
408
- * This method will only clear the first @{link PelJpegMarker::APP1}
409
- * section found (there should normally be just one).
410
  */
411
  public function clearExif()
412
  {
413
- $sections_count = count($this->sections);
414
- for ($i = 0; $i < $sections_count; $i ++) {
415
- if ($this->sections[$i][0] == PelJpegMarker::APP1) {
416
- unset($this->sections[$i]);
417
- return;
 
 
 
418
  }
419
  }
420
  }
78
  *
79
  * @var array
80
  */
81
+ protected $sections = array();
82
 
83
  /**
84
  * The JPEG image data.
120
 
121
  if (is_string($data)) {
122
  Pel::debug('Initializing PelJpeg object from %s', $data);
123
+ $this->loadFile($data);
 
 
 
 
124
  } elseif ($data instanceof PelDataWindow) {
125
  Pel::debug('Initializing PelJpeg object from PelDataWindow.');
126
  $this->load($data);
304
  $sections_count = count($this->sections);
305
  for ($i = 0; $i < $sections_count; $i ++) {
306
  if (! empty($this->sections[$i][0])) {
307
+ $section = $this->sections[$i];
308
+ if ($section[0] == PelJpegMarker::APP0) {
309
  $app0_offset = $i;
310
+ } elseif (($section[0] == PelJpegMarker::APP1) && ($section[1] instanceof PelExif)) {
311
  $app1_offset = $i;
312
  break;
313
  }
366
  }
367
 
368
  /**
369
+ * Get first valid APP1 Exif section data.
370
  *
371
  * Use this to get the @{link PelExif Exif data} stored.
372
  *
375
  */
376
  public function getExif()
377
  {
378
+ $sections_count = count($this->sections);
379
+ for ($i = 0; $i < $sections_count; $i ++) {
380
+ $section = $this->getSection(PelJpegMarker::APP1, $i);
381
+ if ($section instanceof PelExif) {
382
+ return $section;
383
+ }
384
  }
385
  return null;
386
  }
405
  /**
406
  * Clear any Exif data.
407
  *
408
+ * This method will only clear @{link PelJpegMarker::APP1} EXIF sections found.
 
409
  */
410
  public function clearExif()
411
  {
412
+ $idx = 0;
413
+ while ($idx < count($this->sections)) {
414
+ $s = $this->sections[$idx];
415
+ if (($s[0] == PelJpegMarker::APP1) && ($s[1] instanceof PelExif)) {
416
+ array_splice($this->sections, $idx, 1);
417
+ $idx--;
418
+ } else {
419
+ ++ $idx;
420
  }
421
  }
422
  }
vendor/pel/src/PelMakerNotes.php ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * PEL: PHP Exif Library.
4
+ * A library with support for reading and
5
+ * writing all Exif headers in JPEG and TIFF images using PHP.
6
+ *
7
+ * Copyright (C) 2004, 2005 Martin Geisler.
8
+ * Copyright (C) 2017 Johannes Weberhofer.
9
+ *
10
+ * This program is free software; you can redistribute it and/or modify
11
+ * it under the terms of the GNU General Public License as published by
12
+ * the Free Software Foundation; either version 2 of the License, or
13
+ * (at your option) any later version.
14
+ *
15
+ * This program is distributed in the hope that it will be useful,
16
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
+ * GNU General Public License for more details.
19
+ *
20
+ * You should have received a copy of the GNU General Public License
21
+ * along with this program in the file COPYING; if not, write to the
22
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
23
+ * Boston, MA 02110-1301 USA
24
+ */
25
+ namespace lsolesen\pel;
26
+
27
+ /**
28
+ * Namespace for functions operating on Exif formats.
29
+ *
30
+ * This class defines the constants that are to be used whenever one
31
+ * has to refer to the format of an Exif tag. They will be
32
+ * collectively denoted by the pseudo-type PelFormat throughout the
33
+ * documentation.
34
+ *
35
+ * All the methods defined here are static, and they all operate on a
36
+ * single argument which should be one of the class constants.
37
+ *
38
+ * @author Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com>
39
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
40
+ * License (GPL)
41
+ * @package
42
+ *
43
+ */
44
+ abstract class PelMakerNotes
45
+ {
46
+ protected $type;
47
+ protected $parent;
48
+ protected $data;
49
+ protected $components;
50
+ protected $offset;
51
+
52
+ public static function createMakerNotesFromManufacturer($man, $parent, $data, $size, $offset)
53
+ {
54
+ switch ($man) {
55
+ case 'Canon':
56
+ return new PelCanonMakerNotes($parent, $data, $size, $offset);
57
+ default:
58
+ return null;
59
+ }
60
+ }
61
+
62
+ public function __construct($parent, $data, $size, $offset)
63
+ {
64
+ $this->parent = $parent;
65
+ $this->data = $data;
66
+ $this->size = $size;
67
+ $this->offset = $offset;
68
+ $this->components = 0;
69
+ Pel::debug('Creating MakerNotes with %d bytes at offset %d.', $size, $offset);
70
+ }
71
+
72
+ abstract public function load();
73
+ }
vendor/pel/src/PelMakerNotesMalformedException.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * PEL: PHP Exif Library.
5
+ * A library with support for reading and
6
+ * writing all Exif headers in JPEG and TIFF images using PHP.
7
+ *
8
+ * Copyright (C) 2004, 2005, 2006 Martin Geisler.
9
+ *
10
+ * This program is free software; you can redistribute it and/or modify
11
+ * it under the terms of the GNU General Public License as published by
12
+ * the Free Software Foundation; either version 2 of the License, or
13
+ * (at your option) any later version.
14
+ *
15
+ * This program is distributed in the hope that it will be useful,
16
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
+ * GNU General Public License for more details.
19
+ *
20
+ * You should have received a copy of the GNU General Public License
21
+ * along with this program in the file COPYING; if not, write to the
22
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
23
+ * Boston, MA 02110-1301 USA
24
+ */
25
+ namespace lsolesen\pel;
26
+
27
+ /**
28
+ * Classes for dealing with Exif entries.
29
+ *
30
+ * This file defines two exception classes and the abstract class
31
+ * {@link PelEntry} which provides the basic methods that all Exif
32
+ * entries will have. All Exif entries will be represented by
33
+ * descendants of the {@link PelEntry} class --- the class itself is
34
+ * abstract and so it cannot be instantiated.
35
+ *
36
+ * @author Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com>
37
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
38
+ * License (GPL)
39
+ * @package PEL
40
+ */
41
+
42
+ /**
43
+ * An exception thrown when the makernotes IFD is malformed.
44
+ *
45
+ * @package PEL
46
+ * @subpackage Exception
47
+ */
48
+ class PelMakerNotesMalformedException extends PelException
49
+ {
50
+ }
vendor/pel/src/PelTag.php CHANGED
@@ -409,6 +409,15 @@ class PelTag
409
  */
410
  const RATING = 0x4746;
411
 
 
 
 
 
 
 
 
 
 
412
  /**
413
  * CFA Repeat Pattern Dim.
414
  *
@@ -557,6 +566,33 @@ class PelTag
557
  */
558
  const DATE_TIME_DIGITIZED = 0x9004;
559
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
560
  /**
561
  * Meaning of each component.
562
  *
@@ -1338,6 +1374,369 @@ class PelTag
1338
  */
1339
  const GPS_DIFFERENTIAL = 0x001E;
1340
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1341
  /**
1342
  * Values for tags short names.
1343
  */
@@ -1381,6 +1780,7 @@ class PelTag
1381
  self::RELATED_IMAGE_WIDTH => 'RelatedImageWidth',
1382
  self::RELATED_IMAGE_LENGTH => 'RelatedImageLength',
1383
  self::RATING => 'Rating',
 
1384
  self::CFA_REPEAT_PATTERN_DIM => 'CFARepeatPatternDim',
1385
  self::CFA_PATTERN => 'CFAPattern',
1386
  self::BATTERY_LEVEL => 'BatteryLevel',
@@ -1398,6 +1798,9 @@ class PelTag
1398
  self::EXIF_VERSION => 'ExifVersion',
1399
  self::DATE_TIME_ORIGINAL => 'DateTimeOriginal',
1400
  self::DATE_TIME_DIGITIZED => 'DateTimeDigitized',
 
 
 
1401
  self::COMPONENTS_CONFIGURATION => 'ComponentsConfiguration',
1402
  self::COMPRESSED_BITS_PER_PIXEL => 'CompressedBitsPerPixel',
1403
  self::SHUTTER_SPEED_VALUE => 'ShutterSpeedValue',
@@ -1496,6 +1899,8 @@ class PelTag
1496
  self::RELATED_IMAGE_FILE_FORMAT => 'Related Image File Format',
1497
  self::RELATED_IMAGE_WIDTH => 'Related Image Width',
1498
  self::RELATED_IMAGE_LENGTH => 'Related Image Length',
 
 
1499
  self::CFA_REPEAT_PATTERN_DIM => 'CFA Repeat Pattern Dim',
1500
  self::CFA_PATTERN => 'CFA Pattern',
1501
  self::BATTERY_LEVEL => 'Battery Level',
@@ -1513,6 +1918,9 @@ class PelTag
1513
  self::EXIF_VERSION => 'Exif Version',
1514
  self::DATE_TIME_ORIGINAL => 'Date and Time (original)',
1515
  self::DATE_TIME_DIGITIZED => 'Date and Time (digitized)',
 
 
 
1516
  self::COMPONENTS_CONFIGURATION => 'Components Configuration',
1517
  self::COMPRESSED_BITS_PER_PIXEL => 'Compressed Bits per Pixel',
1518
  self::SHUTTER_SPEED_VALUE => 'Shutter speed',
@@ -1606,13 +2014,303 @@ class PelTag
1606
  self::GPS_DIFFERENTIAL => 'GPSDifferential',
1607
  );
1608
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1609
  /**
1610
  * Returns a string from container with key $tag and subcontainer index of $idx
1611
  *
1612
  * @param array $container
1613
  * {@link PelTag::EXIF_TAGS_SHORT}, {@link PelTag::EXIF_TAGS_TITLE},
1614
  * {@link PelTag::GPS_TAGS_SHORT} or {@link PelTag::GPS_TAGS_TITLE} container.
1615
- * @param PelTag $tag
1616
  * the tag.
1617
  *
1618
  * @return string short name or long name of the tag.
@@ -1629,6 +2327,8 @@ class PelTag
1629
  /**
1630
  * Reverse lookup of a tag id by its short name. Return false for the unknown tag name.
1631
  *
 
 
1632
  * @param string $name
1633
  * tag short name.
1634
  *
@@ -1642,6 +2342,39 @@ class PelTag
1642
  return $k;
1643
  }
1644
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1645
  return array_search($name, static::$gpsTagsShort);
1646
  }
1647
 
@@ -1667,7 +2400,7 @@ class PelTag
1667
  * {@link PelIfd::IFD1}, {@link PelIfd::EXIF}, {@link PelIfd::GPS},
1668
  * or {@link PelIfd::INTEROPERABILITY}.
1669
  *
1670
- * @param PelTag $tag
1671
  * the tag.
1672
  *
1673
  * @return string the short name of the tag, e.g., 'ImageWidth' for
@@ -1685,6 +2418,18 @@ class PelTag
1685
  return self::getValue(self::$exifTagsShort, $tag);
1686
  case PelIfd::GPS:
1687
  return self::getValue(self::$gpsTagsShort, $tag);
 
 
 
 
 
 
 
 
 
 
 
 
1688
  }
1689
 
1690
  return self::unknownTag($tag);
@@ -1698,7 +2443,7 @@ class PelTag
1698
  * {@link PelIfd::IFD1}, {@link PelIfd::EXIF}, {@link PelIfd::GPS},
1699
  * or {@link PelIfd::INTEROPERABILITY}.
1700
  *
1701
- * @param PelTag $tag
1702
  * the tag.
1703
  *
1704
  * @return string the title of the tag, e.g., 'Image Width' for the
@@ -1716,6 +2461,18 @@ class PelTag
1716
  return Pel::tra(self::getValue(self::$exifTagsTitle, $tag));
1717
  case PelIfd::GPS:
1718
  return Pel::tra(self::getValue(self::$gpsTagsShort, $tag));
 
 
 
 
 
 
 
 
 
 
 
 
1719
  }
1720
 
1721
  return self::unknownTag($tag);
409
  */
410
  const RATING = 0x4746;
411
 
412
+ /**
413
+ * Rating percent
414
+ *
415
+ * Format: {@link PelFormat::SHORT}
416
+ *
417
+ * Components: 1.
418
+ */
419
+ const RATING_PERCENT = 0x4749;
420
+
421
  /**
422
  * CFA Repeat Pattern Dim.
423
  *
566
  */
567
  const DATE_TIME_DIGITIZED = 0x9004;
568
 
569
+ /**
570
+ * Offset time (timezone) of file change time.
571
+ *
572
+ * Format: {@link PelFormat::ASCII}
573
+ *
574
+ * Components: 7.
575
+ */
576
+ const OFFSET_TIME = 0x9010;
577
+
578
+ /**
579
+ * Offset time (timezone) of original data generation.
580
+ *
581
+ * Format: {@link PelFormat::ASCII}
582
+ *
583
+ * Components: 7.
584
+ */
585
+ const OFFSET_TIME_ORIGINAL = 0x9011;
586
+
587
+ /**
588
+ * Offset time (timezone) of digital data generation.
589
+ *
590
+ * Format: {@link PelFormat::ASCII}
591
+ *
592
+ * Components: 7.
593
+ */
594
+ const OFFSET_TIME_DIGITIZED = 0x9012;
595
+
596
  /**
597
  * Meaning of each component.
598
  *
1374
  */
1375
  const GPS_DIFFERENTIAL = 0x001E;
1376
 
1377
+ /**
1378
+ * Canon camera settings.
1379
+ *
1380
+ * Format: {@link PelFormat::SHORT}.
1381
+ *
1382
+ * Components: Any.
1383
+ */
1384
+ const CANON_CAMERA_SETTINGS = 0x0001;
1385
+
1386
+ /**
1387
+ * Canon focal length.
1388
+ *
1389
+ * Format: {@link PelFormat::SHORT}.
1390
+ *
1391
+ * Components: Any.
1392
+ */
1393
+ const CANON_FOCAL_LENGTH = 0x0002;
1394
+
1395
+ /**
1396
+ * Canon shot info.
1397
+ *
1398
+ * Format: {@link PelFormat::SHORT}.
1399
+ *
1400
+ * Components: Any.
1401
+ */
1402
+ const CANON_SHOT_INFO = 0x0004;
1403
+
1404
+ /**
1405
+ * Canon panorama.
1406
+ *
1407
+ * Format: {@link PelFormat::SHORT}.
1408
+ *
1409
+ * Components: Any.
1410
+ */
1411
+ const CANON_PANORAMA = 0x0005;
1412
+
1413
+ /**
1414
+ * Canon image type.
1415
+ *
1416
+ * Format: {@link PelFormat::ASCII}.
1417
+ *
1418
+ * Components: Any.
1419
+ */
1420
+ const CANON_IMAGE_TYPE = 0x0006;
1421
+
1422
+ /**
1423
+ * Canon firmware version.
1424
+ *
1425
+ * Format: {@link PelFormat::ASCII}.
1426
+ *
1427
+ * Components: Any.
1428
+ */
1429
+ const CANON_FIRMWARE_VERSION = 0x0007;
1430
+
1431
+ /**
1432
+ * Canon file number.
1433
+ *
1434
+ * Format: {@link PelFormat::LONG}.
1435
+ *
1436
+ * Components: Any.
1437
+ */
1438
+ const CANON_FILE_NUMBER = 0x0008;
1439
+
1440
+ /**
1441
+ * Canon owner name.
1442
+ *
1443
+ * Format: {@link PelFormat::ASCII}.
1444
+ *
1445
+ * Components: Any.
1446
+ */
1447
+ const CANON_OWNER_NAME = 0x0009;
1448
+
1449
+ /**
1450
+ * Canon serial number.
1451
+ *
1452
+ * Format: {@link PelFormat::LONG}.
1453
+ *
1454
+ * Components: Any.
1455
+ */
1456
+ const CANON_SERIAL_NUMBER = 0x000c;
1457
+
1458
+ /**
1459
+ * Canon camera info.
1460
+ *
1461
+ * Format: {@link PelFormat::SHORT}.
1462
+ *
1463
+ * Components: Any.
1464
+ */
1465
+ const CANON_CAMERA_INFO = 0x000d;
1466
+
1467
+ /**
1468
+ * Canon custom functions.
1469
+ *
1470
+ * Format: {@link PelFormat::SHORT}.
1471
+ *
1472
+ * Components: Any.
1473
+ */
1474
+ const CANON_CUSTOM_FUNCTIONS = 0x000f;
1475
+
1476
+ /**
1477
+ * Canon model id.
1478
+ *
1479
+ * Format: {@link PelFormat::LONG}.
1480
+ *
1481
+ * Components: Any.
1482
+ */
1483
+ const CANON_MODEL_ID = 0x0010;
1484
+
1485
+ /**
1486
+ * Canon picture info.
1487
+ *
1488
+ * Format: {@link PelFormat::SHORT}.
1489
+ *
1490
+ * Components: Any.
1491
+ */
1492
+ const CANON_PICTURE_INFO = 0x0012;
1493
+
1494
+ /**
1495
+ * Canon thumbnail image valid area.
1496
+ *
1497
+ * Format: {@link PelFormat::SSHORT}.
1498
+ *
1499
+ * Components: Any.
1500
+ */
1501
+ const CANON_THUMBNAIL_IMAGE_VALID_AREA = 0x0013;
1502
+
1503
+ /**
1504
+ * Canon serial number format.
1505
+ *
1506
+ * Format: {@link PelFormat::LONG}.
1507
+ *
1508
+ * Components: Any.
1509
+ */
1510
+ const CANON_SERIAL_NUMBER_FORMAT = 0x0015;
1511
+
1512
+ /**
1513
+ * Canon super macro.
1514
+ *
1515
+ * Format: {@link PelFormat::SSHORT}.
1516
+ *
1517
+ * Components: Any.
1518
+ */
1519
+ const CANON_SUPER_MACRO = 0x001a;
1520
+
1521
+ /**
1522
+ * Canon firmware revision.
1523
+ *
1524
+ * Format: {@link PelFormat::LONG}.
1525
+ *
1526
+ * Components: Any.
1527
+ */
1528
+ const CANON_FIRMWARE_REVISION = 0x001e;
1529
+
1530
+ /**
1531
+ * Canon af info.
1532
+ *
1533
+ * Format: {@link PelFormat::SHORT}.
1534
+ *
1535
+ * Components: Any.
1536
+ */
1537
+ const CANON_AF_INFO = 0x0026;
1538
+
1539
+ /**
1540
+ * Canon original decision data offset.
1541
+ *
1542
+ * Format: {@link PelFormat::SLONG}.
1543
+ *
1544
+ * Components: Any.
1545
+ */
1546
+ const CANON_ORIGINAL_DECISION_DATA_OFFSET = 0x0083;
1547
+
1548
+ /**
1549
+ * Canon white balance table.
1550
+ *
1551
+ * Format: {@link PelFormat::SHORT}.
1552
+ *
1553
+ * Components: Any.
1554
+ */
1555
+ const CANON_WHITE_BALANCE_TABLE = 0x00a4;
1556
+
1557
+ /**
1558
+ * Canon file info.
1559
+ *
1560
+ * Format: {@link PelFormat::UNDEFINED}.
1561
+ *
1562
+ * Components: Any.
1563
+ */
1564
+ const CANON_FILE_INFO = 0x0093;
1565
+
1566
+ /**
1567
+ * Canon lens model.
1568
+ *
1569
+ * Format: {@link PelFormat::ASCII}.
1570
+ *
1571
+ * Components: Any.
1572
+ */
1573
+ const CANON_LENS_MODEL = 0x0095;
1574
+
1575
+ /**
1576
+ * Canon internal serial number.
1577
+ *
1578
+ * Format: {@link PelFormat::ASCII}.
1579
+ *
1580
+ * Components: Any.
1581
+ */
1582
+ const CANON_INTERNAL_SERIAL_NUMBER = 0x0096;
1583
+
1584
+ /**
1585
+ * Canon dust removal data.
1586
+ *
1587
+ * Format: {@link PelFormat::ASCII}.
1588
+ *
1589
+ * Components: Any.
1590
+ */
1591
+ const CANON_DUST_REMOVAL_DATA = 0x0097;
1592
+
1593
+ /**
1594
+ * Canon custom functions (2).
1595
+ *
1596
+ * Format: {@link PelFormat::SHORT}.
1597
+ *
1598
+ * Components: Any.
1599
+ */
1600
+ const CANON_CUSTOM_FUNCTIONS_2 = 0x0099;
1601
+
1602
+ /**
1603
+ * Canon processing info.
1604
+ *
1605
+ * Format: {@link PelFormat::SHORT}.
1606
+ *
1607
+ * Components: Any.
1608
+ */
1609
+ const CANON_PROCESSING_INFO = 0x00a0;
1610
+
1611
+ /**
1612
+ * Canon measured color.
1613
+ *
1614
+ * Format: {@link PelFormat::SHORT}.
1615
+ *
1616
+ * Components: Any.
1617
+ */
1618
+ const CANON_MEASURED_COLOR = 0x00aa;
1619
+
1620
+ /**
1621
+ * Canon color space.
1622
+ *
1623
+ * Format: {@link PelFormat::SSHORT}.
1624
+ *
1625
+ * Components: Any.
1626
+ */
1627
+ const CANON_COLOR_SPACE = 0x00b4;
1628
+
1629
+ /**
1630
+ * Canon vrd offset.
1631
+ *
1632
+ * Format: {@link PelFormat::LONG}.
1633
+ *
1634
+ * Components: Any.
1635
+ */
1636
+ const CANON_VRD_OFFSET = 0x00d0;
1637
+
1638
+ /**
1639
+ * Canon sensor info.
1640
+ *
1641
+ * Format: {@link PelFormat::SHORT}.
1642
+ *
1643
+ * Components: Any.
1644
+ */
1645
+ const CANON_SENSOR_INFO = 0x00e0;
1646
+
1647
+ /**
1648
+ * Canon color data.
1649
+ *
1650
+ * Format: {@link PelFormat::SHORT}.
1651
+ *
1652
+ * Components: Any.
1653
+ */
1654
+ const CANON_COLOR_DATA = 0x4001;
1655
+
1656
+ const CANON_CS_MACRO = 0x0001;
1657
+ const CANON_CS_SELF_TIMER = 0x0002;
1658
+ const CANON_CS_QUALITY = 0x0003;
1659
+ const CANON_CS_FLASH_MODE = 0x0004;
1660
+ const CANON_CS_DRIVE_MODE = 0x0005;
1661
+ const CANON_CS_FOCUS_MODE = 0x0007;
1662
+ const CANON_CS_RECORD_MODE = 0x0009;
1663
+ const CANON_CS_IMAGE_SIZE = 0x000a;
1664
+ const CANON_CS_EASY_MODE = 0x000b;
1665
+ const CANON_CS_DIGITAL_ZOOM = 0x000c;
1666
+ const CANON_CS_CONTRAST = 0x000d;
1667
+ const CANON_CS_SATURATION = 0x000e;
1668
+ const CANON_CS_SHARPNESS = 0x000f;
1669
+ const CANON_CS_ISO_SPEED = 0x0010;
1670
+ const CANON_CS_METERING_MODE = 0x0011;
1671
+ const CANON_CS_FOCUS_TYPE = 0x0012;
1672
+ const CANON_CS_AF_POINT = 0x0013;
1673
+ const CANON_CS_EXPOSURE_PROGRAM = 0x0014;
1674
+ const CANON_CS_LENS_TYPE = 0x0016;
1675
+ const CANON_CS_LENS = 0x0017;
1676
+ const CANON_CS_SHORT_FOCAL = 0x0018;
1677
+ const CANON_CS_FOCAL_UNITS = 0x0019;
1678
+ const CANON_CS_MAX_APERTURE = 0x001a;
1679
+ const CANON_CS_MIN_APERTURE = 0x001b;
1680
+ const CANON_CS_FLASH_ACTIVITY = 0x001c;
1681
+ const CANON_CS_FLASH_DETAILS = 0x001d;
1682
+ const CANON_CS_FOCUS_CONTINUOUS = 0x0020;
1683
+ const CANON_CS_AE_SETTING = 0x0021;
1684
+ const CANON_CS_IMAGE_STABILIZATION = 0x0022;
1685
+ const CANON_CS_DISPLAY_APERTURE = 0x0023;
1686
+ const CANON_CS_ZOOM_SOURCE_WIDTH = 0x0024;
1687
+ const CANON_CS_ZOOM_TARGET_WIDTH = 0x0025;
1688
+ const CANON_CS_SPOT_METERING_MODE = 0x0027;
1689
+ const CANON_CS_PHOTO_EFFECT = 0x0028;
1690
+ const CANON_CS_MANUAL_FLASH_OUTPUT = 0x0029;
1691
+ const CANON_CS_COLOR_TONE = 0x002a;
1692
+ const CANON_CS_SRAW_QUALITY = 0x002e;
1693
+
1694
+ const CANON_SI_ISO_SPEED = 0x0002;
1695
+ const CANON_SI_MEASURED_EV = 0x0003;
1696
+ const CANON_SI_TARGET_APERTURE = 0x0004;
1697
+ const CANON_SI_TARGET_SHUTTER_SPEED = 0x0005;
1698
+ const CANON_SI_WHITE_BALANCE = 0x0007;
1699
+ const CANON_SI_SLOW_SHUTTER = 0x0008;
1700
+ const CANON_SI_SEQUENCE = 0x0009;
1701
+ const CANON_SI_AF_POINT_USED = 0x000e;
1702
+ const CANON_SI_FLASH_BIAS = 0x000f;
1703
+ const CANON_SI_AUTO_EXPOSURE_BRACKETING = 0x0010;
1704
+ const CANON_SI_SUBJECT_DISTANCE = 0x0013;
1705
+ const CANON_SI_APERTURE_VALUE = 0x0015;
1706
+ const CANON_SI_SHUTTER_SPEED_VALUE = 0x0016;
1707
+ const CANON_SI_MEASURED_EV2 = 0x0017;
1708
+ const CANON_SI_CAMERA_TYPE = 0x001a;
1709
+ const CANON_SI_AUTO_ROTATE = 0x001b;
1710
+ const CANON_SI_ND_FILTER = 0x001c;
1711
+
1712
+ const CANON_PA_PANORAMA_FRAME = 0x0002;
1713
+ const CANON_PA_PANORAMA_DIRECTION = 0x0005;
1714
+
1715
+ const CANON_PI_IMAGE_WIDTH = 0x0002;
1716
+ const CANON_PI_IMAGE_HEIGHT = 0x0003;
1717
+ const CANON_PI_IMAGE_WIDTH_AS_SHOT = 0x0004;
1718
+ const CANON_PI_IMAGE_HEIGHT_AS_SHOT = 0x0005;
1719
+ const CANON_PI_AF_POINTS_USED = 0x0016;
1720
+ const CANON_PI_AF_POINTS_USED_20D = 0x001a;
1721
+
1722
+ const CANON_FI_FILE_NUMBER = 0x0001;
1723
+ const CANON_FI_BRACKET_MODE = 0x0003;
1724
+ const CANON_FI_BRACKET_VALUE = 0x0004;
1725
+ const CANON_FI_BRACKET_SHOT_NUMBER = 0x0005;
1726
+ const CANON_FI_RAW_JPG_QUALITY = 0x0006;
1727
+ const CANON_FI_RAW_JPG_SIZE = 0x0007;
1728
+ const CANON_FI_NOISE_REDUCTION = 0x0008;
1729
+ const CANON_FI_WB_BRACKET_MODE = 0x0009;
1730
+ const CANON_FI_WB_BRACKET_VALUE_AB = 0x000c;
1731
+ const CANON_FI_WB_BRACKET_VALUE_GM = 0x000d;
1732
+ const CANON_FI_FILTER_EFFECT = 0x000e;
1733
+ const CANON_FI_TONING_EFFECT = 0x000f;
1734
+ const CANON_FI_MACRO_MAGNIFICATION = 0x0010;
1735
+ const CANON_FI_LIVE_VIEW_SHOOTING = 0x0013;
1736
+ const CANON_FI_FOCUS_DISTANCE_UPPER = 0x0014;
1737
+ const CANON_FI_FOCUS_DISTANCE_LOWER = 0x0015;
1738
+ const CANON_FI_FLASH_EXPOSURE_LOCK = 0x0019;
1739
+
1740
  /**
1741
  * Values for tags short names.
1742
  */
1780
  self::RELATED_IMAGE_WIDTH => 'RelatedImageWidth',
1781
  self::RELATED_IMAGE_LENGTH => 'RelatedImageLength',
1782
  self::RATING => 'Rating',
1783
+ self::RATING_PERCENT => 'RatingPercent',
1784
  self::CFA_REPEAT_PATTERN_DIM => 'CFARepeatPatternDim',
1785
  self::CFA_PATTERN => 'CFAPattern',
1786
  self::BATTERY_LEVEL => 'BatteryLevel',
1798
  self::EXIF_VERSION => 'ExifVersion',
1799
  self::DATE_TIME_ORIGINAL => 'DateTimeOriginal',
1800
  self::DATE_TIME_DIGITIZED => 'DateTimeDigitized',
1801
+ self::OFFSET_TIME => 'OffsetTime',
1802
+ self::OFFSET_TIME_ORIGINAL => 'OffsetTimeOriginal',
1803
+ self::OFFSET_TIME_DIGITIZED => 'OffsetTimeDigitized',
1804
  self::COMPONENTS_CONFIGURATION => 'ComponentsConfiguration',
1805
  self::COMPRESSED_BITS_PER_PIXEL => 'CompressedBitsPerPixel',
1806
  self::SHUTTER_SPEED_VALUE => 'ShutterSpeedValue',
1899
  self::RELATED_IMAGE_FILE_FORMAT => 'Related Image File Format',
1900
  self::RELATED_IMAGE_WIDTH => 'Related Image Width',
1901
  self::RELATED_IMAGE_LENGTH => 'Related Image Length',
1902
+ self::RATING => 'Star Rating',
1903
+ self::RATING_PERCENT => 'Percent Rating',
1904
  self::CFA_REPEAT_PATTERN_DIM => 'CFA Repeat Pattern Dim',
1905
  self::CFA_PATTERN => 'CFA Pattern',
1906
  self::BATTERY_LEVEL => 'Battery Level',
1918
  self::EXIF_VERSION => 'Exif Version',
1919
  self::DATE_TIME_ORIGINAL => 'Date and Time (original)',
1920
  self::DATE_TIME_DIGITIZED => 'Date and Time (digitized)',
1921
+ self::OFFSET_TIME => 'Timezone',
1922
+ self::OFFSET_TIME_ORIGINAL => 'Timezone (original)',
1923
+ self::OFFSET_TIME_DIGITIZED => 'Timezone (digitized)',
1924
  self::COMPONENTS_CONFIGURATION => 'Components Configuration',
1925
  self::COMPRESSED_BITS_PER_PIXEL => 'Compressed Bits per Pixel',
1926
  self::SHUTTER_SPEED_VALUE => 'Shutter speed',
2014
  self::GPS_DIFFERENTIAL => 'GPSDifferential',
2015
  );
2016
 
2017
+ /**
2018
+ * Values for canon maker notes tags titles
2019
+ */
2020
+ protected static $canonTagsTitle = array(
2021
+ self::CANON_CAMERA_SETTINGS => 'Camera Settings',
2022
+ self::CANON_FOCAL_LENGTH => 'Focal Length',
2023
+ self::CANON_SHOT_INFO => 'Shot Info',
2024
+ self::CANON_PANORAMA => 'Panorama',
2025
+ self::CANON_IMAGE_TYPE => 'Image Type',
2026
+ self::CANON_FIRMWARE_VERSION => 'Firmware Version',
2027
+ self::CANON_FILE_NUMBER => 'File Number',
2028
+ self::CANON_OWNER_NAME => 'Owner Name',
2029
+ self::CANON_SERIAL_NUMBER => 'Serial Number',
2030
+ self::CANON_CAMERA_INFO => 'Camera Info',
2031
+ self::CANON_CUSTOM_FUNCTIONS => 'Custom Functions',
2032
+ self::CANON_MODEL_ID => 'Model ID',
2033
+ self::CANON_PICTURE_INFO => 'Picture Info',
2034
+ self::CANON_THUMBNAIL_IMAGE_VALID_AREA => 'Thumbnail Image Valid Area',
2035
+ self::CANON_SERIAL_NUMBER_FORMAT => 'Serial number format',
2036
+ self::CANON_SUPER_MACRO => 'Super macro',
2037
+ self::CANON_FIRMWARE_REVISION => 'Firmware Revision',
2038
+ self::CANON_AF_INFO => 'AF info',
2039
+ self::CANON_ORIGINAL_DECISION_DATA_OFFSET => 'Original decision data offset',
2040
+ self::CANON_WHITE_BALANCE_TABLE => 'White balance table',
2041
+ self::CANON_LENS_MODEL => 'Lens model',
2042
+ self::CANON_INTERNAL_SERIAL_NUMBER => 'Internal serial number',
2043
+ self::CANON_DUST_REMOVAL_DATA => 'Dust removal data',
2044
+ self::CANON_CUSTOM_FUNCTIONS_2 => 'Custom functions',
2045
+ self::CANON_PROCESSING_INFO => 'Processing info',
2046
+ self::CANON_MEASURED_COLOR => 'Measured color',
2047
+ self::CANON_COLOR_SPACE => 'Color Space',
2048
+ self::CANON_VRD_OFFSET => 'VRD offset',
2049
+ self::CANON_SENSOR_INFO => 'Sensor info',
2050
+ self::CANON_COLOR_DATA => 'Color data'
2051
+ );
2052
+
2053
+ /**
2054
+ * Values for canon maker notes tags short names
2055
+ */
2056
+ protected static $canonTagsShort = array(
2057
+ self::CANON_CAMERA_SETTINGS => 'CameraSettings',
2058
+ self::CANON_FOCAL_LENGTH => 'FocalLength',
2059
+ self::CANON_SHOT_INFO => 'ShotInfo',
2060
+ self::CANON_PANORAMA => 'Panorama',
2061
+ self::CANON_IMAGE_TYPE => 'ImageType',
2062
+ self::CANON_FIRMWARE_VERSION => 'FirmwareVersion',
2063
+ self::CANON_FILE_NUMBER => 'FileNumber',
2064
+ self::CANON_OWNER_NAME => 'OwnerName',
2065
+ self::CANON_SERIAL_NUMBER => 'SerialNumber',
2066
+ self::CANON_CAMERA_INFO => 'CameraInfo',
2067
+ self::CANON_CUSTOM_FUNCTIONS => 'CustomFunctions',
2068
+ self::CANON_MODEL_ID => 'ModelID',
2069
+ self::CANON_PICTURE_INFO => 'PictureInfo',
2070
+ self::CANON_THUMBNAIL_IMAGE_VALID_AREA => 'ThumbnailImageValidArea',
2071
+ self::CANON_SERIAL_NUMBER_FORMAT => 'Serial Number Format',
2072
+ self::CANON_SUPER_MACRO => 'SuperMacro',
2073
+ self::CANON_FIRMWARE_REVISION => 'FirmwareRevision',
2074
+ self::CANON_AF_INFO => 'AFinfo',
2075
+ self::CANON_ORIGINAL_DECISION_DATA_OFFSET => 'OriginalDecision Data Offset',
2076
+ self::CANON_WHITE_BALANCE_TABLE => 'WhiteBalanceTable',
2077
+ self::CANON_LENS_MODEL => 'LensModel',
2078
+ self::CANON_INTERNAL_SERIAL_NUMBER => 'InternalSerialNumber',
2079
+ self::CANON_DUST_REMOVAL_DATA => 'DustRemovalData',
2080
+ self::CANON_CUSTOM_FUNCTIONS_2 => 'CustomFunctions',
2081
+ self::CANON_PROCESSING_INFO => 'ProcessingInfo',
2082
+ self::CANON_MEASURED_COLOR => 'MeasuredColor',
2083
+ self::CANON_COLOR_SPACE => 'ColorSpace',
2084
+ self::CANON_VRD_OFFSET => 'VRDOffset',
2085
+ self::CANON_SENSOR_INFO => 'SensorInfo',
2086
+ self::CANON_COLOR_DATA => 'ColorData'
2087
+ );
2088
+
2089
+ /**
2090
+ * Values for canon camera settings tags titles
2091
+ */
2092
+ protected static $canonCsTagsTitle = array(
2093
+ self::CANON_CS_MACRO => 'Macro Mode',
2094
+ self::CANON_CS_SELF_TIMER => 'Self Timer',
2095
+ self::CANON_CS_QUALITY => 'Quality',
2096
+ self::CANON_CS_FLASH_MODE => 'Flash Mode',
2097
+ self::CANON_CS_DRIVE_MODE => 'Drive Mode',
2098
+ self::CANON_CS_FOCUS_MODE => 'Focus Mode',
2099
+ self::CANON_CS_RECORD_MODE => 'Record Mode',
2100
+ self::CANON_CS_IMAGE_SIZE => 'Image Size',
2101
+ self::CANON_CS_EASY_MODE => 'Easy Shooting Mode',
2102
+ self::CANON_CS_DIGITAL_ZOOM => 'Digital Zoom',
2103
+ self::CANON_CS_CONTRAST => 'Contrast',
2104
+ self::CANON_CS_SATURATION => 'Saturation',
2105
+ self::CANON_CS_SHARPNESS => 'Sharpness',
2106
+ self::CANON_CS_ISO_SPEED => 'ISO Speed',
2107
+ self::CANON_CS_METERING_MODE => 'Metering Mode',
2108
+ self::CANON_CS_FOCUS_TYPE => 'Focus Type',
2109
+ self::CANON_CS_AF_POINT => 'AF Point Selected',
2110
+ self::CANON_CS_EXPOSURE_PROGRAM => 'Exposure Mode',
2111
+ self::CANON_CS_LENS_TYPE => 'Lens Type',
2112
+ self::CANON_CS_LENS => 'Long Focal Length',
2113
+ self::CANON_CS_SHORT_FOCAL => 'Short Focal Length',
2114
+ self::CANON_CS_FOCAL_UNITS => 'Focal Units',
2115
+ self::CANON_CS_MAX_APERTURE => 'Max Aperture',
2116
+ self::CANON_CS_MIN_APERTURE => 'Min Aperture',
2117
+ self::CANON_CS_FLASH_ACTIVITY => 'Flash Activity',
2118
+ self::CANON_CS_FLASH_DETAILS => 'Flash Details',
2119
+ self::CANON_CS_FOCUS_CONTINUOUS => 'Focus Continuous',
2120
+ self::CANON_CS_AE_SETTING => 'AE Setting',
2121
+ self::CANON_CS_IMAGE_STABILIZATION => 'Image Stabilization',
2122
+ self::CANON_CS_DISPLAY_APERTURE => 'Display Aperture',
2123
+ self::CANON_CS_ZOOM_SOURCE_WIDTH => 'Zoom Source Width',
2124
+ self::CANON_CS_ZOOM_TARGET_WIDTH => 'Zoom Target Width',
2125
+ self::CANON_CS_SPOT_METERING_MODE => 'Spot Metering Mode',
2126
+ self::CANON_CS_PHOTO_EFFECT => 'Photo Effect',
2127
+ self::CANON_CS_MANUAL_FLASH_OUTPUT => 'Manual Flash Output',
2128
+ self::CANON_CS_COLOR_TONE => 'Color Tone',
2129
+ self::CANON_CS_SRAW_QUALITY => 'SRAW Quality'
2130
+ );
2131
+
2132
+ /**
2133
+ * Values for canon camera settings tags short names
2134
+ */
2135
+ protected static $canonCsTagsShort = array(
2136
+ self::CANON_CS_MACRO => 'MacroMode',
2137
+ self::CANON_CS_SELF_TIMER => 'SelfTimer',
2138
+ self::CANON_CS_QUALITY => 'Quality',
2139
+ self::CANON_CS_FLASH_MODE => 'FlashMode',
2140
+ self::CANON_CS_DRIVE_MODE => 'DriveMode',
2141
+ self::CANON_CS_FOCUS_MODE => 'FocusMode',
2142
+ self::CANON_CS_RECORD_MODE => 'RecordMode',
2143
+ self::CANON_CS_IMAGE_SIZE => 'ImageSize',
2144
+ self::CANON_CS_EASY_MODE => 'EasyShootingMode',
2145
+ self::CANON_CS_DIGITAL_ZOOM => 'DigitalZoom',
2146
+ self::CANON_CS_CONTRAST => 'Contrast',
2147
+ self::CANON_CS_SATURATION => 'Saturation',
2148
+ self::CANON_CS_SHARPNESS => 'Sharpness',
2149
+ self::CANON_CS_ISO_SPEED => 'ISOSpeed',
2150
+ self::CANON_CS_METERING_MODE => 'MeteringMode',
2151
+ self::CANON_CS_FOCUS_TYPE => 'FocusType',
2152
+ self::CANON_CS_AF_POINT => 'AFPointSelected',
2153
+ self::CANON_CS_EXPOSURE_PROGRAM => 'ExposureMode',
2154
+ self::CANON_CS_LENS_TYPE => 'LensType',
2155
+ self::CANON_CS_LENS => 'LongFocalLength',
2156
+ self::CANON_CS_SHORT_FOCAL => 'ShortFocalLength',
2157
+ self::CANON_CS_FOCAL_UNITS => 'FocalUnits',
2158
+ self::CANON_CS_MAX_APERTURE => 'MaxAperture',
2159
+ self::CANON_CS_MIN_APERTURE => 'MinAperture',
2160
+ self::CANON_CS_FLASH_ACTIVITY => 'FlashActivity',
2161
+ self::CANON_CS_FLASH_DETAILS => 'FlashDetails',
2162
+ self::CANON_CS_FOCUS_CONTINUOUS => 'FocusContinuous',
2163
+ self::CANON_CS_AE_SETTING => 'AESetting',
2164
+ self::CANON_CS_IMAGE_STABILIZATION => 'ImageStabilization',
2165
+ self::CANON_CS_DISPLAY_APERTURE => 'DisplayAperture',
2166
+ self::CANON_CS_ZOOM_SOURCE_WIDTH => 'ZoomSourceWidth',
2167
+ self::CANON_CS_ZOOM_TARGET_WIDTH => 'ZoomTargetWidth',
2168
+ self::CANON_CS_SPOT_METERING_MODE => 'SpotMeteringMode',
2169
+ self::CANON_CS_PHOTO_EFFECT => 'PhotoEffect',
2170
+ self::CANON_CS_MANUAL_FLASH_OUTPUT => 'ManualFlashOutput',
2171
+ self::CANON_CS_COLOR_TONE => 'ColorTone',
2172
+ self::CANON_CS_SRAW_QUALITY => 'SRAWQuality'
2173
+ );
2174
+
2175
+ /**
2176
+ * Values for canon shot info tags titles
2177
+ */
2178
+ protected static $canonSiTagsTitle = array(
2179
+ self::CANON_SI_ISO_SPEED => 'ISO Speed Used',
2180
+ self::CANON_SI_MEASURED_EV => 'Measured EV',
2181
+ self::CANON_SI_TARGET_APERTURE => 'Target Aperture',
2182
+ self::CANON_SI_TARGET_SHUTTER_SPEED => 'Target Shutter Speed',
2183
+ self::CANON_SI_WHITE_BALANCE => 'White Balance Setting',
2184
+ self::CANON_SI_SLOW_SHUTTER => 'Slow Shutter',
2185
+ self::CANON_SI_SEQUENCE => 'Sequence Number',
2186
+ self::CANON_SI_AF_POINT_USED => 'AF Point Used',
2187
+ self::CANON_SI_FLASH_BIAS => 'Flash Bias',
2188
+ self::CANON_SI_AUTO_EXPOSURE_BRACKETING => 'Auto Exposure Bracketing',
2189
+ self::CANON_SI_SUBJECT_DISTANCE => 'Subject Distance',
2190
+ self::CANON_SI_APERTURE_VALUE => 'Aperture',
2191
+ self::CANON_SI_SHUTTER_SPEED_VALUE => 'Shutter Speed',
2192
+ self::CANON_SI_MEASURED_EV2 => 'Measured EV 2',
2193
+ self::CANON_SI_CAMERA_TYPE => 'Camera Type',
2194
+ self::CANON_SI_AUTO_ROTATE => 'Auto Rotate',
2195
+ self::CANON_SI_ND_FILTER => 'ND Filter'
2196
+ );
2197
+
2198
+ /**
2199
+ * Values for canon shot info tags short names
2200
+ */
2201
+ protected static $canonSiTagsShort = array(
2202
+ self::CANON_SI_ISO_SPEED => 'ISOSpeedUsed',
2203
+ self::CANON_SI_MEASURED_EV => 'MeasuredEV',
2204
+ self::CANON_SI_TARGET_APERTURE => 'TargetAperture',
2205
+ self::CANON_SI_TARGET_SHUTTER_SPEED => 'TargetShutterSpeed',
2206
+ self::CANON_SI_WHITE_BALANCE => 'WhiteBalanceSetting',
2207
+ self::CANON_SI_SLOW_SHUTTER => 'SlowShutter',
2208
+ self::CANON_SI_SEQUENCE => 'SequenceNumber',
2209
+ self::CANON_SI_AF_POINT_USED => 'AFPointUsed',
2210
+ self::CANON_SI_FLASH_BIAS => 'FlashBias',
2211
+ self::CANON_SI_AUTO_EXPOSURE_BRACKETING => 'AutoExposureBracketing',
2212
+ self::CANON_SI_SUBJECT_DISTANCE => 'SubjectDistance',
2213
+ self::CANON_SI_APERTURE_VALUE => 'Aperture',
2214
+ self::CANON_SI_SHUTTER_SPEED_VALUE => 'ShutterSpeed',
2215
+ self::CANON_SI_MEASURED_EV2 => 'MeasuredEV2',
2216
+ self::CANON_SI_CAMERA_TYPE => 'CameraType',
2217
+ self::CANON_SI_AUTO_ROTATE => 'AutoRotate',
2218
+ self::CANON_SI_ND_FILTER => 'NDFilter'
2219
+ );
2220
+
2221
+ /**
2222
+ * Values for canon panorama tags titles
2223
+ */
2224
+ protected static $canonPaTagsTitle = array(
2225
+ self::CANON_PA_PANORAMA_FRAME => 'Panorama Frame',
2226
+ self::CANON_PA_PANORAMA_DIRECTION => 'Panorama Direction'
2227
+ );
2228
+
2229
+ /**
2230
+ * Values for canon panorama tags short names
2231
+ */
2232
+ protected static $canonPaTagsShort = array(
2233
+ self::CANON_PA_PANORAMA_FRAME => 'PanoramaFrame',
2234
+ self::CANON_PA_PANORAMA_DIRECTION => 'PanoramaDirection'
2235
+ );
2236
+
2237
+ /**
2238
+ * Values for canon picture info tags titles
2239
+ */
2240
+ protected static $canonPiTagsTitle = array(
2241
+ self::CANON_PI_IMAGE_WIDTH => 'Image Width',
2242
+ self::CANON_PI_IMAGE_HEIGHT => 'Image Height',
2243
+ self::CANON_PI_IMAGE_WIDTH_AS_SHOT => 'Image Width As Shot',
2244
+ self::CANON_PI_IMAGE_HEIGHT_AS_SHOT => 'Image Height As Shot',
2245
+ self::CANON_PI_AF_POINTS_USED => 'AF Points Used',
2246
+ self::CANON_PI_AF_POINTS_USED_20D => 'AF Points Used (20D)'
2247
+ );
2248
+
2249
+ /**
2250
+ * Values for canon picture info tags short names
2251
+ */
2252
+ protected static $canonPiTagsShort = array(
2253
+ self::CANON_PI_IMAGE_WIDTH => 'ImageWidth',
2254
+ self::CANON_PI_IMAGE_HEIGHT => 'ImageHeight',
2255
+ self::CANON_PI_IMAGE_WIDTH_AS_SHOT => 'ImageWidthAsShot',
2256
+ self::CANON_PI_IMAGE_HEIGHT_AS_SHOT => 'ImageHeightAsShot',
2257
+ self::CANON_PI_AF_POINTS_USED => 'AFPointsUsed',
2258
+ self::CANON_PI_AF_POINTS_USED_20D => 'AFPointsUsed(20D)'
2259
+ );
2260
+
2261
+ /**
2262
+ * Values for canon file info tags titles
2263
+ */
2264
+ protected static $canonFiTagsTitle = array(
2265
+ self::CANON_FI_FILE_NUMBER => 'File Number',
2266
+ self::CANON_FI_BRACKET_MODE => 'Bracket Mode',
2267
+ self::CANON_FI_BRACKET_VALUE => 'Bracket Value',
2268
+ self::CANON_FI_BRACKET_SHOT_NUMBER => 'Bracket Shot Number',
2269
+ self::CANON_FI_RAW_JPG_QUALITY => 'Raw Jpg Quality',
2270
+ self::CANON_FI_RAW_JPG_SIZE => 'Raw Jpg Size',
2271
+ self::CANON_FI_NOISE_REDUCTION => 'Noise Reduction',
2272
+ self::CANON_FI_WB_BRACKET_MODE => 'WB Bracket Mode',
2273
+ self::CANON_FI_WB_BRACKET_VALUE_AB => 'WB Bracket Value AB',
2274
+ self::CANON_FI_WB_BRACKET_VALUE_GM => 'WB Bracket Value GM',
2275
+ self::CANON_FI_FILTER_EFFECT => 'Filter Effect',
2276
+ self::CANON_FI_TONING_EFFECT => 'Toning Effect',
2277
+ self::CANON_FI_MACRO_MAGNIFICATION => 'Macro Magnification',
2278
+ self::CANON_FI_LIVE_VIEW_SHOOTING => 'Live View Shooting',
2279
+ self::CANON_FI_FOCUS_DISTANCE_UPPER => 'Focus Distance Upper',
2280
+ self::CANON_FI_FOCUS_DISTANCE_LOWER => 'Focus Distance Lower',
2281
+ self::CANON_FI_FLASH_EXPOSURE_LOCK => 'Flash Exposure Lock'
2282
+ );
2283
+
2284
+ /**
2285
+ * Values for canon file info tags short names
2286
+ */
2287
+ protected static $canonFiTagsShort = array(
2288
+ self::CANON_FI_FILE_NUMBER => 'FileNumber',
2289
+ self::CANON_FI_BRACKET_MODE => 'BracketMode',
2290
+ self::CANON_FI_BRACKET_VALUE => 'BracketValue',
2291
+ self::CANON_FI_BRACKET_SHOT_NUMBER => 'BracketShotNumber',
2292
+ self::CANON_FI_RAW_JPG_QUALITY => 'RawJpgQuality',
2293
+ self::CANON_FI_RAW_JPG_SIZE => 'RawJpgSize',
2294
+ self::CANON_FI_NOISE_REDUCTION => 'NoiseReduction',
2295
+ self::CANON_FI_WB_BRACKET_MODE => 'WBBracketMode',
2296
+ self::CANON_FI_WB_BRACKET_VALUE_AB => 'WBBracketValueAB',
2297
+ self::CANON_FI_WB_BRACKET_VALUE_GM => 'WBBracketValueGM',
2298
+ self::CANON_FI_FILTER_EFFECT => 'FilterEffect',
2299
+ self::CANON_FI_TONING_EFFECT => 'ToningEffect',
2300
+ self::CANON_FI_MACRO_MAGNIFICATION => 'MacroMagnification',
2301
+ self::CANON_FI_LIVE_VIEW_SHOOTING => 'LiveViewShooting',
2302
+ self::CANON_FI_FOCUS_DISTANCE_UPPER => 'FocusDistanceUpper',
2303
+ self::CANON_FI_FOCUS_DISTANCE_LOWER => 'FocusDistanceLower',
2304
+ self::CANON_FI_FLASH_EXPOSURE_LOCK => 'FlashExposureLock'
2305
+ );
2306
+
2307
  /**
2308
  * Returns a string from container with key $tag and subcontainer index of $idx
2309
  *
2310
  * @param array $container
2311
  * {@link PelTag::EXIF_TAGS_SHORT}, {@link PelTag::EXIF_TAGS_TITLE},
2312
  * {@link PelTag::GPS_TAGS_SHORT} or {@link PelTag::GPS_TAGS_TITLE} container.
2313
+ * @param int $tag
2314
  * the tag.
2315
  *
2316
  * @return string short name or long name of the tag.
2327
  /**
2328
  * Reverse lookup of a tag id by its short name. Return false for the unknown tag name.
2329
  *
2330
+ * @deprecated Use getExifTagByName() and getGpsTagByName() to distinct the type of tag.
2331
+ *
2332
  * @param string $name
2333
  * tag short name.
2334
  *
2342
  return $k;
2343
  }
2344
 
2345
+ $k = array_search($name, static::$gpsTagsShort);
2346
+ if ($k !== false) {
2347
+ return $k;
2348
+ }
2349
+
2350
+ return array_search($name, self::$canonTagsShort);
2351
+ }
2352
+
2353
+ /**
2354
+ * Reverse lookup of a EXIF related tag id by its short name. Return false for the unknown tag name.
2355
+ *
2356
+ * @param string $name
2357
+ * tag short name.
2358
+ *
2359
+ * @return mixed (bool|int)
2360
+ * the tag.
2361
+ */
2362
+ public static function getExifTagByName($name)
2363
+ {
2364
+ return array_search($name, static::$exifTagsShort);
2365
+ }
2366
+
2367
+ /**
2368
+ * Reverse lookup of a GPS related tag id by its short name. Return false for the unknown tag name.
2369
+ *
2370
+ * @param string $name
2371
+ * tag short name.
2372
+ *
2373
+ * @return mixed (bool|int)
2374
+ * the tag.
2375
+ */
2376
+ public static function getGpsTagByName($name)
2377
+ {
2378
  return array_search($name, static::$gpsTagsShort);
2379
  }
2380
 
2400
  * {@link PelIfd::IFD1}, {@link PelIfd::EXIF}, {@link PelIfd::GPS},
2401
  * or {@link PelIfd::INTEROPERABILITY}.
2402
  *
2403
+ * @param int $tag
2404
  * the tag.
2405
  *
2406
  * @return string the short name of the tag, e.g., 'ImageWidth' for
2418
  return self::getValue(self::$exifTagsShort, $tag);
2419
  case PelIfd::GPS:
2420
  return self::getValue(self::$gpsTagsShort, $tag);
2421
+ case PelIfd::CANON_MAKER_NOTES:
2422
+ return self::getValue(self::$canonTagsShort, $tag);
2423
+ case PelIfd::CANON_CAMERA_SETTINGS:
2424
+ return self::getValue(self::$canonCsTagsShort, $tag);
2425
+ case PelIfd::CANON_SHOT_INFO:
2426
+ return self::getValue(self::$canonSiTagsShort, $tag);
2427
+ case PelIfd::CANON_PANORAMA:
2428
+ return self::getValue(self::$canonPaTagsShort, $tag);
2429
+ case PelIfd::CANON_PICTURE_INFO:
2430
+ return self::getValue(self::$canonPiTagsShort, $tag);
2431
+ case PelIfd::CANON_FILE_INFO:
2432
+ return self::getValue(self::$canonFiTagsShort, $tag);
2433
  }
2434
 
2435
  return self::unknownTag($tag);
2443
  * {@link PelIfd::IFD1}, {@link PelIfd::EXIF}, {@link PelIfd::GPS},
2444
  * or {@link PelIfd::INTEROPERABILITY}.
2445
  *
2446
+ * @param int $tag
2447
  * the tag.
2448
  *
2449
  * @return string the title of the tag, e.g., 'Image Width' for the
2461
  return Pel::tra(self::getValue(self::$exifTagsTitle, $tag));
2462
  case PelIfd::GPS:
2463
  return Pel::tra(self::getValue(self::$gpsTagsShort, $tag));
2464
+ case PelIfd::CANON_MAKER_NOTES:
2465
+ return Pel::tra(self::getValue(self::$canonTagsTitle, $tag));
2466
+ case PelIfd::CANON_CAMERA_SETTINGS:
2467
+ return self::getValue(self::$canonCsTagsTitle, $tag);
2468
+ case PelIfd::CANON_SHOT_INFO:
2469
+ return self::getValue(self::$canonSiTagsTitle, $tag);
2470
+ case PelIfd::CANON_PANORAMA:
2471
+ return self::getValue(self::$canonPaTagsTitle, $tag);
2472
+ case PelIfd::CANON_PICTURE_INFO:
2473
+ return self::getValue(self::$canonPiTagsTitle, $tag);
2474
+ case PelIfd::CANON_FILE_INFO:
2475
+ return self::getValue(self::$canonFiTagsTitle, $tag);
2476
  }
2477
 
2478
  return self::unknownTag($tag);
vendor/pel/src/PelTiff.php CHANGED
@@ -204,7 +204,7 @@ class PelTiff
204
  * little-endian} or {@link PelConvert::BIG_ENDIAN big-endian} byte
205
  * order, and so this method takes an argument specifying that.
206
  *
207
- * @param PelByteOrder $order
208
  * the desired byte order of the TIFF data.
209
  * This should be one of {@link PelConvert::LITTLE_ENDIAN} or {@link
210
  * PelConvert::BIG_ENDIAN}.
204
  * little-endian} or {@link PelConvert::BIG_ENDIAN big-endian} byte
205
  * order, and so this method takes an argument specifying that.
206
  *
207
+ * @param boolean $order
208
  * the desired byte order of the TIFF data.
209
  * This should be one of {@link PelConvert::LITTLE_ENDIAN} or {@link
210
  * PelConvert::BIG_ENDIAN}.
vendor/pel/src/PelWrongComponentCountException.php CHANGED
@@ -63,7 +63,7 @@ class PelWrongComponentCountException extends \lsolesen\pel\PelEntryException
63
  * @param int $type
64
  * the type of IFD.
65
  *
66
- * @param PelTag $tag
67
  * the tag for which the violation was found.
68
  *
69
  * @param int $found
63
  * @param int $type
64
  * the type of IFD.
65
  *
66
+ * @param int $tag
67
  * the tag for which the violation was found.
68
  *
69
  * @param int $found
vendor/wp-async-request.php CHANGED
@@ -141,7 +141,9 @@ if ( ! class_exists( 'WP_Async_Request' ) ) {
141
  * Check for correct nonce and pass to handler.
142
  */
143
  public function maybe_handle() {
 
144
  session_write_close();
 
145
  check_ajax_referer( $this->identifier, 'nonce' );
146
 
147
  $this->handle();
141
  * Check for correct nonce and pass to handler.
142
  */
143
  public function maybe_handle() {
144
+ // Don't lock up other requests while processing
145
  session_write_close();
146
+
147
  check_ajax_referer( $this->identifier, 'nonce' );
148
 
149
  $this->handle();