Imagify Image Optimizer - Version 1.9.8

Version Description

  • 2019/11/11 =
  • Improvement: compatibility with WordPress 5.3!
  • New: among other things, WordPress 5.3 automatically resizes large images on upload, using a predefined threshold value that can be changed only by filter (no setting fields are provided). Imagifys "Resize larger images" setting field is now used to tweak this threshold.
  • Caution: to be able to work on WordPress 5.3, some adjustments have been made to our compatibility with Enable Media Replace and Regenerate Thumbnails. However, these plugins must be updated to work with WordPress 5.3: do not use them until then.
  • Improvement: moved the width and height attributes from the <picture> tag to the <img> tag to be valid HTML markup.
  • Fix: added a missing descriptor in srcset attribute when using <picture> tags to display webp images. This should also fix an issue with LasyLoad.
  • Fix: fixed an issue with the user capacity used for "Other Media" menu item.
  • Fix: a php notice stripos(): Non-string needles will be interpreted as strings in the future..
Download this release

Release Info

Developer wp_media
Plugin Icon 128x128 Imagify Image Optimizer
Version 1.9.8
Comparing to
See all releases

Code changes from version 1.9.7 to 1.9.8

Files changed (56) hide show
  1. classes/CDN/PushCDNInterface.php +1 -1
  2. classes/Context/AbstractContext.php +1 -11
  3. classes/Context/ContextInterface.php +12 -0
  4. classes/Context/CustomFolders.php +9 -5
  5. classes/Context/Noop.php +6 -5
  6. classes/Context/WP.php +23 -8
  7. classes/Media/AbstractMedia.php +35 -7
  8. classes/Media/CustomFolders.php +43 -10
  9. classes/Media/MediaInterface.php +35 -8
  10. classes/Media/Noop.php +40 -8
  11. classes/Media/WP.php +112 -15
  12. classes/Optimization/Data/AbstractData.php +2 -2
  13. classes/Optimization/Data/CustomFolders.php +44 -2
  14. classes/Optimization/Data/DataInterface.php +13 -0
  15. classes/Optimization/Data/Noop.php +13 -0
  16. classes/Optimization/Data/WP.php +59 -0
  17. classes/Optimization/File.php +52 -19
  18. classes/Optimization/Process/AbstractProcess.php +57 -19
  19. classes/Optimization/Process/ProcessInterface.php +14 -3
  20. classes/Optimization/Process/WP.php +3 -3
  21. classes/Webp/Picture/Display.php +4 -9
  22. composer.json +1 -0
  23. imagify.php +2 -2
  24. inc/3rd-party/amazon-s3-and-cloudfront/classes/CDN/WP/AS3.php +52 -5
  25. inc/3rd-party/enable-media-replace/classes/Main.php +46 -5
  26. inc/3rd-party/enable-media-replace/enable-media-replace.php +1 -1
  27. inc/3rd-party/nextgen-gallery/classes/Context/NGG.php +13 -9
  28. inc/3rd-party/nextgen-gallery/classes/DynamicThumbnails.php +1 -1
  29. inc/3rd-party/nextgen-gallery/classes/Media/NGG.php +39 -12
  30. inc/3rd-party/nextgen-gallery/classes/Optimization/Data/NGG.php +47 -1
  31. inc/3rd-party/nextgen-gallery/inc/common/attachments.php +2 -2
  32. inc/3rd-party/regenerate-thumbnails/classes/Main.php +106 -20
  33. inc/3rd-party/wp-rocket/classes/Main.php +15 -3
  34. inc/admin/media.php +1 -1
  35. inc/classes/class-imagify-auto-optimization.php +250 -45
  36. inc/classes/class-imagify-custom-folders.php +2 -2
  37. inc/classes/class-imagify-db.php +1 -1
  38. inc/classes/class-imagify-files-list-table.php +4 -4
  39. inc/classes/class-imagify-options.php +20 -1
  40. inc/classes/class-imagify-views.php +4 -4
  41. inc/common/attachments.php +9 -0
  42. inc/deprecated/Traits/Media/CustomFoldersDeprecatedTrait.php +44 -0
  43. inc/deprecated/Traits/Media/NGGDeprecatedTrait.php +38 -0
  44. inc/deprecated/Traits/Media/NoopDeprecatedTrait.php +30 -0
  45. inc/deprecated/Traits/Media/WPDeprecatedTrait.php +40 -0
  46. inc/deprecated/Traits/Optimization/Process/AbstractProcessDeprecatedTrait.php +44 -0
  47. inc/functions/admin-ui.php +1 -1
  48. inc/functions/i18n.php +1 -1
  49. package.json +1 -1
  50. readme.txt +11 -2
  51. vendor/autoload.php +1 -1
  52. vendor/composer/autoload_classmap.php +5 -0
  53. vendor/composer/autoload_psr4.php +1 -0
  54. vendor/composer/autoload_real.php +4 -4
  55. vendor/composer/autoload_static.php +14 -4
  56. views/part-settings-library.php +32 -20
classes/CDN/PushCDNInterface.php CHANGED
@@ -89,7 +89,7 @@ interface PushCDNInterface {
89
  * @access public
90
  * @author Grégory Viguier
91
  *
92
- * @param string $file_name Name of the file. Leave empty for the full size file.
93
  * @return string Path to the file.
94
  */
95
  public function get_file_path( $file_name = false );
89
  * @access public
90
  * @author Grégory Viguier
91
  *
92
+ * @param string $file_name Name of the file. Leave empty for the full size file. Use 'original' to get the path to the original file.
93
  * @return string Path to the file.
94
  */
95
  public function get_file_path( $file_name = false );
classes/Context/AbstractContext.php CHANGED
@@ -63,16 +63,6 @@ abstract class AbstractContext implements ContextInterface {
63
  */
64
  protected $thumbnail_sizes;
65
 
66
- /**
67
- * Tell if the optimization process is allowed resize in this context.
68
- *
69
- * @var bool
70
- * @since 1.9
71
- * @access protected
72
- * @author Grégory Viguier
73
- */
74
- protected $can_resize;
75
-
76
  /**
77
  * Tell if the optimization process is allowed to backup in this context.
78
  *
@@ -167,7 +157,7 @@ abstract class AbstractContext implements ContextInterface {
167
  * @return bool
168
  */
169
  public function can_resize() {
170
- return $this->can_resize;
171
  }
172
 
173
  /**
63
  */
64
  protected $thumbnail_sizes;
65
 
 
 
 
 
 
 
 
 
 
 
66
  /**
67
  * Tell if the optimization process is allowed to backup in this context.
68
  *
157
  * @return bool
158
  */
159
  public function can_resize() {
160
+ return $this->get_resizing_threshold() > 0;
161
  }
162
 
163
  /**
classes/Context/ContextInterface.php CHANGED
@@ -78,6 +78,18 @@ interface ContextInterface {
78
  */
79
  public function get_thumbnail_sizes();
80
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  /**
82
  * Tell if the optimization process is allowed resize in this context.
83
  *
78
  */
79
  public function get_thumbnail_sizes();
80
 
81
+ /**
82
+ * Get images max width for this context. This is used when resizing.
83
+ * 0 means to not resize.
84
+ *
85
+ * @since 1.9.8
86
+ * @access public
87
+ * @author Grégory Viguier
88
+ *
89
+ * @return int
90
+ */
91
+ public function get_resizing_threshold();
92
+
93
  /**
94
  * Tell if the optimization process is allowed resize in this context.
95
  *
classes/Context/CustomFolders.php CHANGED
@@ -41,14 +41,18 @@ class CustomFolders extends AbstractContext {
41
  protected $thumbnail_sizes = [];
42
 
43
  /**
44
- * Tell if the optimization process is allowed resize in this context.
 
45
  *
46
- * @var bool
47
- * @since 1.9
48
- * @access protected
49
  * @author Grégory Viguier
 
 
50
  */
51
- protected $can_resize = false;
 
 
52
 
53
  /**
54
  * Tell if the optimization process is allowed to backup in this context.
41
  protected $thumbnail_sizes = [];
42
 
43
  /**
44
+ * Get images max width for this context. This is used when resizing.
45
+ * 0 means to not resize.
46
  *
47
+ * @since 1.9.8
48
+ * @access public
 
49
  * @author Grégory Viguier
50
+ *
51
+ * @return int
52
  */
53
+ public function get_resizing_threshold() {
54
+ return 0;
55
+ }
56
 
57
  /**
58
  * Tell if the optimization process is allowed to backup in this context.
classes/Context/Noop.php CHANGED
@@ -77,16 +77,17 @@ class Noop implements ContextInterface {
77
  }
78
 
79
  /**
80
- * Tell if the optimization process is allowed resize in this context.
 
81
  *
82
- * @since 1.9
83
  * @access public
84
  * @author Grégory Viguier
85
  *
86
- * @return bool
87
  */
88
- public function can_resize() {
89
- return false;
90
  }
91
 
92
  /**
77
  }
78
 
79
  /**
80
+ * Get images max width for this context. This is used when resizing.
81
+ * 0 means to not resize.
82
  *
83
+ * @since 1.9.8
84
  * @access public
85
  * @author Grégory Viguier
86
  *
87
+ * @return int
88
  */
89
+ public function get_resizing_threshold() {
90
+ return 0;
91
  }
92
 
93
  /**
classes/Context/WP.php CHANGED
@@ -22,6 +22,16 @@ class WP extends AbstractContext {
22
  */
23
  protected $context = 'wp';
24
 
 
 
 
 
 
 
 
 
 
 
25
  /**
26
  * Get the thumbnail sizes for this context, except the full size.
27
  *
@@ -50,22 +60,27 @@ class WP extends AbstractContext {
50
  }
51
 
52
  /**
53
- * Tell if the optimization process is allowed resize in this context.
 
54
  *
55
- * @since 1.9
56
  * @access public
57
  * @author Grégory Viguier
58
  *
59
- * @return bool
60
  */
61
- public function can_resize() {
62
- if ( isset( $this->can_resize ) ) {
63
- return $this->can_resize;
64
  }
65
 
66
- $this->can_resize = get_imagify_option( 'resize_larger' ) && get_imagify_option( 'resize_larger_w' ) > 0;
 
 
 
 
67
 
68
- return $this->can_resize;
69
  }
70
 
71
  /**
22
  */
23
  protected $context = 'wp';
24
 
25
+ /**
26
+ * Images max width for this context. This is used when resizing.
27
+ *
28
+ * @var int
29
+ * @since 1.9.8
30
+ * @access protected
31
+ * @author Grégory Viguier
32
+ */
33
+ protected $resizing_threshold;
34
+
35
  /**
36
  * Get the thumbnail sizes for this context, except the full size.
37
  *
60
  }
61
 
62
  /**
63
+ * Get images max width for this context. This is used when resizing.
64
+ * 0 means to not resize.
65
  *
66
+ * @since 1.9.8
67
  * @access public
68
  * @author Grégory Viguier
69
  *
70
+ * @return int
71
  */
72
+ public function get_resizing_threshold() {
73
+ if ( isset( $this->resizing_threshold ) ) {
74
+ return $this->resizing_threshold;
75
  }
76
 
77
+ if ( ! get_imagify_option( 'resize_larger' ) ) {
78
+ $this->resizing_threshold = 0;
79
+ } else {
80
+ $this->resizing_threshold = max( 0, get_imagify_option( 'resize_larger_w' ) );
81
+ }
82
 
83
+ return $this->resizing_threshold;
84
  }
85
 
86
  /**
classes/Media/AbstractMedia.php CHANGED
@@ -237,13 +237,41 @@ abstract class AbstractMedia implements MediaInterface {
237
  return false;
238
  }
239
 
240
- $backup_path = $this->get_raw_original_path();
241
 
242
- if ( ! $backup_path || ! $this->filesystem->exists( $backup_path ) ) {
243
  return false;
244
  }
245
 
246
- return $backup_path;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
  }
248
 
249
 
@@ -398,7 +426,7 @@ abstract class AbstractMedia implements MediaInterface {
398
  return false;
399
  }
400
 
401
- $dimensions = $this->filesystem->get_image_size( $this->get_raw_original_path() );
402
 
403
  if ( ! $dimensions ) {
404
  // Could not get the new dimensions.
@@ -487,7 +515,7 @@ abstract class AbstractMedia implements MediaInterface {
487
  return $this->file_type;
488
  }
489
 
490
- $path = $this->get_raw_original_path();
491
 
492
  if ( ! $path ) {
493
  return $this->file_type;
@@ -506,7 +534,7 @@ abstract class AbstractMedia implements MediaInterface {
506
  * @see $this->get_media_files()
507
  * @author Grégory Viguier
508
  *
509
- * @param array $files An array with the size names as keys ('full' is used for the original file), and arrays of data as values.
510
  * @return array
511
  */
512
  protected function filter_media_files( $files ) {
@@ -516,7 +544,7 @@ abstract class AbstractMedia implements MediaInterface {
516
  * @since 1.9
517
  * @author Grégory Viguier
518
  *
519
- * @param array $files An array with the size names as keys ('full' is used for the original file), and arrays of data as values.
520
  * @param MediaInterface $media This instance.
521
  */
522
  return (array) apply_filters( 'imagify_media_files', $files, $this );
237
  return false;
238
  }
239
 
240
+ $original_path = $this->get_raw_original_path();
241
 
242
+ if ( ! $original_path || ! $this->filesystem->exists( $original_path ) ) {
243
  return false;
244
  }
245
 
246
+ return $original_path;
247
+ }
248
+
249
+
250
+ /** ----------------------------------------------------------------------------------------- */
251
+ /** FULL SIZE FILE ========================================================================== */
252
+ /** ----------------------------------------------------------------------------------------- */
253
+
254
+ /**
255
+ * Get the path to the media’s full size file if the file exists.
256
+ *
257
+ * @since 1.9.8
258
+ * @access public
259
+ * @author Grégory Viguier
260
+ *
261
+ * @return string|bool The file path. False if it doesn't exist.
262
+ */
263
+ public function get_fullsize_path() {
264
+ if ( ! $this->is_valid() ) {
265
+ return false;
266
+ }
267
+
268
+ $original_path = $this->get_raw_fullsize_path();
269
+
270
+ if ( ! $original_path || ! $this->filesystem->exists( $original_path ) ) {
271
+ return false;
272
+ }
273
+
274
+ return $original_path;
275
  }
276
 
277
 
426
  return false;
427
  }
428
 
429
+ $dimensions = $this->filesystem->get_image_size( $this->get_raw_fullsize_path() );
430
 
431
  if ( ! $dimensions ) {
432
  // Could not get the new dimensions.
515
  return $this->file_type;
516
  }
517
 
518
+ $path = $this->get_raw_fullsize_path();
519
 
520
  if ( ! $path ) {
521
  return $this->file_type;
534
  * @see $this->get_media_files()
535
  * @author Grégory Viguier
536
  *
537
+ * @param array $files An array with the size names as keys ('full' is used for the full size file), and arrays of data as values.
538
  * @return array
539
  */
540
  protected function filter_media_files( $files ) {
544
  * @since 1.9
545
  * @author Grégory Viguier
546
  *
547
+ * @param array $files An array with the size names as keys ('full' is used for the full size file), and arrays of data as values.
548
  * @param MediaInterface $media This instance.
549
  */
550
  return (array) apply_filters( 'imagify_media_files', $files, $this );
classes/Media/CustomFolders.php CHANGED
@@ -11,6 +11,7 @@ defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
11
  */
12
  class CustomFolders extends AbstractMedia {
13
  use \Imagify\Traits\MediaRowTrait;
 
14
 
15
  /**
16
  * Context (where the media "comes from").
@@ -90,15 +91,47 @@ class CustomFolders extends AbstractMedia {
90
  /** ----------------------------------------------------------------------------------------- */
91
 
92
  /**
93
- * Get the original media's URL.
94
  *
95
  * @since 1.9
96
  * @access public
97
  * @author Grégory Viguier
98
  *
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  * @return string|bool The file URL. False on failure.
100
  */
101
- public function get_original_url() {
102
  if ( ! $this->is_valid() ) {
103
  return false;
104
  }
@@ -117,15 +150,15 @@ class CustomFolders extends AbstractMedia {
117
  }
118
 
119
  /**
120
- * Get the original media's path.
121
  *
122
- * @since 1.9
123
  * @access public
124
  * @author Grégory Viguier
125
  *
126
  * @return string|bool The file path. False on failure.
127
  */
128
- public function get_raw_original_path() {
129
  if ( ! $this->is_valid() ) {
130
  return false;
131
  }
@@ -224,14 +257,14 @@ class CustomFolders extends AbstractMedia {
224
  }
225
 
226
  /**
227
- * Get the list of the files of this media, including the original file.
228
  *
229
  * @since 1.9
230
  * @access public
231
  * @author Grégory Viguier
232
  *
233
  * @return array {
234
- * An array with the size names as keys ('full' is used for the original file), and arrays of data as values:
235
  *
236
  * @type string $size The size name.
237
  * @type string $path Absolute path to the file.
@@ -246,9 +279,9 @@ class CustomFolders extends AbstractMedia {
246
  return [];
247
  }
248
 
249
- $original_path = $this->get_raw_original_path();
250
 
251
- if ( ! $original_path ) {
252
  return [];
253
  }
254
 
@@ -256,7 +289,7 @@ class CustomFolders extends AbstractMedia {
256
  $sizes = [
257
  'full' => [
258
  'size' => 'full',
259
- 'path' => $original_path,
260
  'width' => $dimensions['width'],
261
  'height' => $dimensions['height'],
262
  'mime-type' => $this->get_mime_type(),
11
  */
12
  class CustomFolders extends AbstractMedia {
13
  use \Imagify\Traits\MediaRowTrait;
14
+ use \Imagify\Deprecated\Traits\Media\CustomFoldersDeprecatedTrait;
15
 
16
  /**
17
  * Context (where the media "comes from").
91
  /** ----------------------------------------------------------------------------------------- */
92
 
93
  /**
94
+ * Get the original media's path.
95
  *
96
  * @since 1.9
97
  * @access public
98
  * @author Grégory Viguier
99
  *
100
+ * @return string|bool The file path. False on failure.
101
+ */
102
+ public function get_raw_original_path() {
103
+ if ( ! $this->is_valid() ) {
104
+ return false;
105
+ }
106
+
107
+ if ( $this->get_cdn() ) {
108
+ return $this->get_cdn()->get_file_path( 'original' );
109
+ }
110
+
111
+ $row = $this->get_row();
112
+
113
+ if ( ! $row || empty( $row['path'] ) ) {
114
+ return false;
115
+ }
116
+
117
+ return \Imagify_Files_Scan::remove_placeholder( $row['path'] );
118
+ }
119
+
120
+
121
+ /** ----------------------------------------------------------------------------------------- */
122
+ /** FULL SIZE FILE ========================================================================== */
123
+ /** ----------------------------------------------------------------------------------------- */
124
+
125
+ /**
126
+ * Get the URL of the media’s full size file.
127
+ *
128
+ * @since 1.9.8
129
+ * @access public
130
+ * @author Grégory Viguier
131
+ *
132
  * @return string|bool The file URL. False on failure.
133
  */
134
+ public function get_fullsize_url() {
135
  if ( ! $this->is_valid() ) {
136
  return false;
137
  }
150
  }
151
 
152
  /**
153
+ * Get the path to the medias full size file, even if the file doesn't exist.
154
  *
155
+ * @since 1.9.8
156
  * @access public
157
  * @author Grégory Viguier
158
  *
159
  * @return string|bool The file path. False on failure.
160
  */
161
+ public function get_raw_fullsize_path() {
162
  if ( ! $this->is_valid() ) {
163
  return false;
164
  }
257
  }
258
 
259
  /**
260
+ * Get the list of the files of this media, including the full size file.
261
  *
262
  * @since 1.9
263
  * @access public
264
  * @author Grégory Viguier
265
  *
266
  * @return array {
267
+ * An array with the size names as keys ('full' is used for the full size file), and arrays of data as values:
268
  *
269
  * @type string $size The size name.
270
  * @type string $path Absolute path to the file.
279
  return [];
280
  }
281
 
282
+ $fullsize_path = $this->get_raw_fullsize_path();
283
 
284
+ if ( ! $fullsize_path ) {
285
  return [];
286
  }
287
 
289
  $sizes = [
290
  'full' => [
291
  'size' => 'full',
292
+ 'path' => $fullsize_path,
293
  'width' => $dimensions['width'],
294
  'height' => $dimensions['height'],
295
  'mime-type' => $this->get_mime_type(),
classes/Media/MediaInterface.php CHANGED
@@ -88,37 +88,64 @@ interface MediaInterface {
88
  /** ----------------------------------------------------------------------------------------- */
89
 
90
  /**
91
- * Get the original media's URL.
92
  *
93
  * @since 1.9
94
  * @access public
95
  * @author Grégory Viguier
96
  *
97
- * @return string|bool The file URL. False on failure.
98
  */
99
- public function get_original_url();
100
 
101
  /**
102
- * Get the original file path, even if the file doesn't exist.
103
  *
104
  * @since 1.9
105
  * @access public
106
  * @author Grégory Viguier
107
  *
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  * @return string|bool The file path. False on failure.
109
  */
110
- public function get_raw_original_path();
111
 
112
  /**
113
- * Get the original media's path if the file exists.
114
  *
115
- * @since 1.9
116
  * @access public
117
  * @author Grégory Viguier
118
  *
119
  * @return string|bool The file path. False if it doesn't exist.
120
  */
121
- public function get_original_path();
122
 
123
 
124
  /** ----------------------------------------------------------------------------------------- */
88
  /** ----------------------------------------------------------------------------------------- */
89
 
90
  /**
91
+ * Get the original file path, even if the file doesn't exist.
92
  *
93
  * @since 1.9
94
  * @access public
95
  * @author Grégory Viguier
96
  *
97
+ * @return string|bool The file path. False on failure.
98
  */
99
+ public function get_raw_original_path();
100
 
101
  /**
102
+ * Get the original media's path if the file exists.
103
  *
104
  * @since 1.9
105
  * @access public
106
  * @author Grégory Viguier
107
  *
108
+ * @return string|bool The file path. False if it doesn't exist.
109
+ */
110
+ public function get_original_path();
111
+
112
+
113
+ /** ----------------------------------------------------------------------------------------- */
114
+ /** FULL SIZE FILE ========================================================================== */
115
+ /** ----------------------------------------------------------------------------------------- */
116
+
117
+ /**
118
+ * Get the URL of the media’s full size file.
119
+ *
120
+ * @since 1.9.8
121
+ * @access public
122
+ * @author Grégory Viguier
123
+ *
124
+ * @return string|bool The file URL. False on failure.
125
+ */
126
+ public function get_fullsize_url();
127
+
128
+ /**
129
+ * Get the path to the media’s full size file, even if the file doesn't exist.
130
+ *
131
+ * @since 1.9.8
132
+ * @access public
133
+ * @author Grégory Viguier
134
+ *
135
  * @return string|bool The file path. False on failure.
136
  */
137
+ public function get_raw_fullsize_path();
138
 
139
  /**
140
+ * Get the path to the medias full size file if the file exists.
141
  *
142
+ * @since 1.9.8
143
  * @access public
144
  * @author Grégory Viguier
145
  *
146
  * @return string|bool The file path. False if it doesn't exist.
147
  */
148
+ public function get_fullsize_path();
149
 
150
 
151
  /** ----------------------------------------------------------------------------------------- */
classes/Media/Noop.php CHANGED
@@ -10,6 +10,7 @@ defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
10
  * @author Grégory Viguier
11
  */
12
  class Noop implements MediaInterface {
 
13
 
14
  /**
15
  * Tell if the given entry can be accepted in the constructor.
@@ -97,41 +98,72 @@ class Noop implements MediaInterface {
97
  /** ----------------------------------------------------------------------------------------- */
98
 
99
  /**
100
- * Get the original media's URL.
101
  *
102
  * @since 1.9
103
  * @access public
104
  * @author Grégory Viguier
105
  *
106
- * @return string|bool The file URL. False on failure.
107
  */
108
- public function get_original_url() {
109
  return false;
110
  }
111
 
112
  /**
113
- * Get the original file path, even if the file doesn't exist.
114
  *
115
  * @since 1.9
116
  * @access public
117
  * @author Grégory Viguier
118
  *
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  * @return string|bool The file path. False on failure.
120
  */
121
- public function get_raw_original_path() {
122
  return false;
123
  }
124
 
125
  /**
126
- * Get the original media's path if the file exists.
127
  *
128
- * @since 1.9
129
  * @access public
130
  * @author Grégory Viguier
131
  *
132
  * @return string|bool The file path. False if it doesn't exist.
133
  */
134
- public function get_original_path() {
135
  return false;
136
  }
137
 
10
  * @author Grégory Viguier
11
  */
12
  class Noop implements MediaInterface {
13
+ use \Imagify\Deprecated\Traits\Media\NoopDeprecatedTrait;
14
 
15
  /**
16
  * Tell if the given entry can be accepted in the constructor.
98
  /** ----------------------------------------------------------------------------------------- */
99
 
100
  /**
101
+ * Get the original file path, even if the file doesn't exist.
102
  *
103
  * @since 1.9
104
  * @access public
105
  * @author Grégory Viguier
106
  *
107
+ * @return string|bool The file path. False on failure.
108
  */
109
+ public function get_raw_original_path() {
110
  return false;
111
  }
112
 
113
  /**
114
+ * Get the original media's path if the file exists.
115
  *
116
  * @since 1.9
117
  * @access public
118
  * @author Grégory Viguier
119
  *
120
+ * @return string|bool The file path. False if it doesn't exist.
121
+ */
122
+ public function get_original_path() {
123
+ return false;
124
+ }
125
+
126
+
127
+ /** ----------------------------------------------------------------------------------------- */
128
+ /** FULL SIZE FILE ========================================================================== */
129
+ /** ----------------------------------------------------------------------------------------- */
130
+
131
+ /**
132
+ * Get the URL of the media’s full size file.
133
+ *
134
+ * @since 1.9.8
135
+ * @access public
136
+ * @author Grégory Viguier
137
+ *
138
+ * @return string|bool The file URL. False on failure.
139
+ */
140
+ public function get_fullsize_url() {
141
+ return false;
142
+ }
143
+
144
+ /**
145
+ * Get the path to the media’s full size file, even if the file doesn't exist.
146
+ *
147
+ * @since 1.9.8
148
+ * @access public
149
+ * @author Grégory Viguier
150
+ *
151
  * @return string|bool The file path. False on failure.
152
  */
153
+ public function get_raw_fullsize_path() {
154
  return false;
155
  }
156
 
157
  /**
158
+ * Get the path to the medias full size file if the file exists.
159
  *
160
+ * @since 1.9.8
161
  * @access public
162
  * @author Grégory Viguier
163
  *
164
  * @return string|bool The file path. False if it doesn't exist.
165
  */
166
+ public function get_fullsize_path() {
167
  return false;
168
  }
169
 
classes/Media/WP.php CHANGED
@@ -10,6 +10,17 @@ defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
10
  * @author Grégory Viguier
11
  */
12
  class WP extends AbstractMedia {
 
 
 
 
 
 
 
 
 
 
 
13
 
14
  /**
15
  * The constructor.
@@ -58,15 +69,52 @@ class WP extends AbstractMedia {
58
  /** ----------------------------------------------------------------------------------------- */
59
 
60
  /**
61
- * Get the original media's URL.
62
  *
63
  * @since 1.9
64
  * @access public
65
  * @author Grégory Viguier
66
  *
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  * @return string|bool The file URL. False on failure.
68
  */
69
- public function get_original_url() {
70
  if ( ! $this->is_valid() ) {
71
  return false;
72
  }
@@ -81,15 +129,15 @@ class WP extends AbstractMedia {
81
  }
82
 
83
  /**
84
- * Get the original media's path.
85
  *
86
- * @since 1.9
87
  * @access public
88
  * @author Grégory Viguier
89
  *
90
  * @return string|bool The file path. False on failure.
91
  */
92
- public function get_raw_original_path() {
93
  if ( ! $this->is_valid() ) {
94
  return false;
95
  }
@@ -149,6 +197,7 @@ class WP extends AbstractMedia {
149
 
150
  /**
151
  * Create the media thumbnails.
 
152
  *
153
  * @since 1.9
154
  * @access public
@@ -165,10 +214,34 @@ class WP extends AbstractMedia {
165
  require_once ABSPATH . 'wp-admin/includes/image.php';
166
  }
167
 
168
- $metadata = wp_generate_attachment_metadata( $this->get_id(), $this->get_raw_original_path() );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
 
170
- if ( empty( $metadata['sizes'] ) ) {
171
- return new \WP_Error( 'thumbnails_creation_filure', __( 'New thumbnails could not be created.', 'imagify' ) );
 
 
 
 
172
  }
173
 
174
  update_post_meta( $this->get_id(), '_wp_attachment_metadata', $metadata );
@@ -205,14 +278,14 @@ class WP extends AbstractMedia {
205
  }
206
 
207
  /**
208
- * Get the list of the files of this media, including the original file.
209
  *
210
  * @since 1.9
211
  * @access public
212
  * @author Grégory Viguier
213
  *
214
  * @return array {
215
- * An array with the size names as keys ('full' is used for the original file), and arrays of data as values:
216
  *
217
  * @type string $size The size name.
218
  * @type string $path Absolute path to the file.
@@ -227,9 +300,9 @@ class WP extends AbstractMedia {
227
  return [];
228
  }
229
 
230
- $original_path = $this->get_raw_original_path();
231
 
232
- if ( ! $original_path ) {
233
  return [];
234
  }
235
 
@@ -237,7 +310,7 @@ class WP extends AbstractMedia {
237
  $all_sizes = [
238
  'full' => [
239
  'size' => 'full',
240
- 'path' => $original_path,
241
  'width' => $dimensions['width'],
242
  'height' => $dimensions['height'],
243
  'mime-type' => $this->get_mime_type(),
@@ -257,7 +330,7 @@ class WP extends AbstractMedia {
257
  return $all_sizes;
258
  }
259
 
260
- $dir_path = $this->filesystem->dir_path( $original_path );
261
  $disallowed_sizes = get_imagify_option( 'disallowed-sizes' );
262
  $is_active_for_network = imagify_is_active_for_network();
263
 
@@ -304,7 +377,7 @@ class WP extends AbstractMedia {
304
  * Update the media data dimensions.
305
  *
306
  * @since 1.9
307
- * @access public
308
  * @author Grégory Viguier
309
  *
310
  * @param array $dimensions {
@@ -330,4 +403,28 @@ class WP extends AbstractMedia {
330
 
331
  update_post_meta( $this->get_id(), '_wp_attachment_metadata', $metadata );
332
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
333
  }
10
  * @author Grégory Viguier
11
  */
12
  class WP extends AbstractMedia {
13
+ use \Imagify\Deprecated\Traits\Media\WPDeprecatedTrait;
14
+
15
+ /**
16
+ * Tell if we’re playing in WP 5.3’s garden.
17
+ *
18
+ * @var bool
19
+ * @since 1.9.8
20
+ * @access protected
21
+ * @author Grégory Viguier
22
+ */
23
+ protected $is_wp53;
24
 
25
  /**
26
  * The constructor.
69
  /** ----------------------------------------------------------------------------------------- */
70
 
71
  /**
72
+ * Get the original file path, even if the file doesn't exist.
73
  *
74
  * @since 1.9
75
  * @access public
76
  * @author Grégory Viguier
77
  *
78
+ * @return string|bool The file path. False on failure.
79
+ */
80
+ public function get_raw_original_path() {
81
+ if ( ! $this->is_valid() ) {
82
+ return false;
83
+ }
84
+
85
+ if ( $this->get_cdn() ) {
86
+ return $this->get_cdn()->get_file_path( 'original' );
87
+ }
88
+
89
+ if ( $this->is_wp_53() ) {
90
+ // `wp_get_original_image_path()` may return false.
91
+ $path = wp_get_original_image_path( $this->id );
92
+ } else {
93
+ $path = false;
94
+ }
95
+
96
+ if ( ! $path ) {
97
+ $path = get_attached_file( $this->id );
98
+ }
99
+
100
+ return $path ? $path : false;
101
+ }
102
+
103
+
104
+ /** ----------------------------------------------------------------------------------------- */
105
+ /** FULL SIZE FILE ========================================================================== */
106
+ /** ----------------------------------------------------------------------------------------- */
107
+
108
+ /**
109
+ * Get the URL of the media’s full size file.
110
+ *
111
+ * @since 1.9.8
112
+ * @access public
113
+ * @author Grégory Viguier
114
+ *
115
  * @return string|bool The file URL. False on failure.
116
  */
117
+ public function get_fullsize_url() {
118
  if ( ! $this->is_valid() ) {
119
  return false;
120
  }
129
  }
130
 
131
  /**
132
+ * Get the path to the medias full size file, even if the file doesn't exist.
133
  *
134
+ * @since 1.9.8
135
  * @access public
136
  * @author Grégory Viguier
137
  *
138
  * @return string|bool The file path. False on failure.
139
  */
140
+ public function get_raw_fullsize_path() {
141
  if ( ! $this->is_valid() ) {
142
  return false;
143
  }
197
 
198
  /**
199
  * Create the media thumbnails.
200
+ * With WP 5.3+, this will also generate a new full size file if the original file is wider or taller than a defined threshold.
201
  *
202
  * @since 1.9
203
  * @access public
214
  require_once ABSPATH . 'wp-admin/includes/image.php';
215
  }
216
 
217
+ // Store the path to the current full size file before generating the thumbnails.
218
+ $old_full_size_path = $this->get_raw_fullsize_path();
219
+ $metadata = wp_generate_attachment_metadata( $this->get_id(), $this->get_raw_original_path() );
220
+
221
+ if ( empty( $metadata['file'] ) ) {
222
+ // Σ(゚Д゚).
223
+ update_post_meta( $this->get_id(), '_wp_attachment_metadata', $metadata );
224
+
225
+ return true;
226
+ }
227
+
228
+ /**
229
+ * Don't change the full size file name.
230
+ * WP 5.3+ will rename the full size file if the resizing threshold has changed (not the same as the one used to generate it previously).
231
+ * This will force WP to keep the previous file name.
232
+ */
233
+ $old_full_size_file_name = $this->filesystem->file_name( $old_full_size_path );
234
+ $new_full_size_file_name = $this->filesystem->file_name( $metadata['file'] );
235
+
236
+ if ( $new_full_size_file_name !== $old_full_size_file_name ) {
237
+ $new_full_size_path = $this->filesystem->dir_path( $old_full_size_path ) . $new_full_size_file_name;
238
 
239
+ $moved = $this->filesystem->move( $new_full_size_path, $old_full_size_path, true );
240
+
241
+ if ( $moved ) {
242
+ $metadata['file'] = $this->filesystem->dir_path( $metadata['file'] ) . $old_full_size_file_name;
243
+ update_post_meta( $this->get_id(), '_wp_attached_file', $metadata['file'] );
244
+ }
245
  }
246
 
247
  update_post_meta( $this->get_id(), '_wp_attachment_metadata', $metadata );
278
  }
279
 
280
  /**
281
+ * Get the list of the files of this media, including the full size file.
282
  *
283
  * @since 1.9
284
  * @access public
285
  * @author Grégory Viguier
286
  *
287
  * @return array {
288
+ * An array with the size names as keys ('full' is used for the full size file), and arrays of data as values:
289
  *
290
  * @type string $size The size name.
291
  * @type string $path Absolute path to the file.
300
  return [];
301
  }
302
 
303
+ $fullsize_path = $this->get_raw_fullsize_path();
304
 
305
+ if ( ! $fullsize_path ) {
306
  return [];
307
  }
308
 
310
  $all_sizes = [
311
  'full' => [
312
  'size' => 'full',
313
+ 'path' => $fullsize_path,
314
  'width' => $dimensions['width'],
315
  'height' => $dimensions['height'],
316
  'mime-type' => $this->get_mime_type(),
330
  return $all_sizes;
331
  }
332
 
333
+ $dir_path = $this->filesystem->dir_path( $fullsize_path );
334
  $disallowed_sizes = get_imagify_option( 'disallowed-sizes' );
335
  $is_active_for_network = imagify_is_active_for_network();
336
 
377
  * Update the media data dimensions.
378
  *
379
  * @since 1.9
380
+ * @access protected
381
  * @author Grégory Viguier
382
  *
383
  * @param array $dimensions {
403
 
404
  update_post_meta( $this->get_id(), '_wp_attachment_metadata', $metadata );
405
  }
406
+
407
+
408
+ /** ----------------------------------------------------------------------------------------- */
409
+ /** INTERNAL TOOLS ========================================================================== */
410
+ /** ----------------------------------------------------------------------------------------- */
411
+
412
+ /**
413
+ * Tell if we’re playing in WP 5.3’s garden.
414
+ *
415
+ * @since 1.9.8
416
+ * @access protected
417
+ * @author Grégory Viguier
418
+ *
419
+ * @return bool
420
+ */
421
+ protected function is_wp_53() {
422
+ if ( isset( $this->is_wp53 ) ) {
423
+ return $this->is_wp53;
424
+ }
425
+
426
+ $this->is_wp53 = function_exists( 'wp_get_original_image_path' );
427
+
428
+ return $this->is_wp53;
429
+ }
430
  }
classes/Optimization/Data/AbstractData.php CHANGED
@@ -321,7 +321,7 @@ abstract class AbstractData implements DataInterface {
321
 
322
  if ( $use_webp && ! empty( $data['sizes'][ $webp_size_name ]['success'] ) ) {
323
  // Try with the webp file first.
324
- $filepath = $media->get_raw_original_path();
325
  $filepath = $filepath ? imagify_path_to_webp( $filepath ) : false;
326
 
327
  if ( ! $filepath || ! $this->filesystem->exists( $filepath ) ) {
@@ -331,7 +331,7 @@ abstract class AbstractData implements DataInterface {
331
 
332
  if ( ! $filepath ) {
333
  // No webp? The full size then.
334
- $filepath = $media->get_original_path();
335
  }
336
 
337
  if ( ! $filepath ) {
321
 
322
  if ( $use_webp && ! empty( $data['sizes'][ $webp_size_name ]['success'] ) ) {
323
  // Try with the webp file first.
324
+ $filepath = $media->get_raw_fullsize_path();
325
  $filepath = $filepath ? imagify_path_to_webp( $filepath ) : false;
326
 
327
  if ( ! $filepath || ! $this->filesystem->exists( $filepath ) ) {
331
 
332
  if ( ! $filepath ) {
333
  // No webp? The full size then.
334
+ $filepath = $media->get_fullsize_path();
335
  }
336
 
337
  if ( ! $filepath ) {
classes/Optimization/Data/CustomFolders.php CHANGED
@@ -153,7 +153,7 @@ class CustomFolders extends AbstractData {
153
  $old_data['status'] = $data['status'];
154
  $old_data['modified'] = 0;
155
 
156
- $file_path = $this->get_media()->get_original_path();
157
 
158
  if ( $file_path ) {
159
  $old_data['hash'] = md5_file( $file_path );
@@ -223,6 +223,48 @@ class CustomFolders extends AbstractData {
223
  $this->update_row( $this->get_reset_data() );
224
  }
225
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226
  /**
227
  * Get default values used to reset optimization data.
228
  *
@@ -263,7 +305,7 @@ class CustomFolders extends AbstractData {
263
  $imagify_columns = $column_defaults;
264
 
265
  // Also set the new file hash.
266
- $file_path = $this->get_media()->get_original_path();
267
 
268
  if ( $file_path ) {
269
  $imagify_columns['hash'] = md5_file( $file_path );
153
  $old_data['status'] = $data['status'];
154
  $old_data['modified'] = 0;
155
 
156
+ $file_path = $this->get_media()->get_fullsize_path();
157
 
158
  if ( $file_path ) {
159
  $old_data['hash'] = md5_file( $file_path );
223
  $this->update_row( $this->get_reset_data() );
224
  }
225
 
226
+ /**
227
+ * Delete the optimization data for the given sizes.
228
+ * If all sizes are removed, all optimization data is deleted.
229
+ * Status and level are not modified nor removed if the "full" size is removed. This leaves the media in a Schrödinger state.
230
+ *
231
+ * @since 1.9.8
232
+ * @access public
233
+ * @author Grégory Viguier
234
+ *
235
+ * @param array $sizes A list of sizes to remove.
236
+ */
237
+ public function delete_sizes_optimization_data( array $sizes ) {
238
+ if ( ! $sizes || ! $this->is_valid() ) {
239
+ return;
240
+ }
241
+
242
+ $data = array_merge( $this->get_reset_data(), $this->get_row() );
243
+
244
+ $data['data']['sizes'] = ! empty( $data['data']['sizes'] ) && is_array( $data['data']['sizes'] ) ? $data['data']['sizes'] : [];
245
+
246
+ if ( ! $data['data']['sizes'] ) {
247
+ return;
248
+ }
249
+
250
+ $remaining_sizes_data = array_diff_key( $data['data']['sizes'], array_flip( $sizes ) );
251
+
252
+ if ( ! $remaining_sizes_data ) {
253
+ // All sizes have been removed: delete everything.
254
+ $this->delete_optimization_data();
255
+ return;
256
+ }
257
+
258
+ if ( count( $remaining_sizes_data ) === count( $data['data']['sizes'] ) ) {
259
+ // Nothing has been removed.
260
+ return;
261
+ }
262
+
263
+ $data['data']['sizes'] = $remaining_sizes_data;
264
+
265
+ $this->update_row( $data );
266
+ }
267
+
268
  /**
269
  * Get default values used to reset optimization data.
270
  *
305
  $imagify_columns = $column_defaults;
306
 
307
  // Also set the new file hash.
308
+ $file_path = $this->get_media()->get_fullsize_path();
309
 
310
  if ( $file_path ) {
311
  $imagify_columns['hash'] = md5_file( $file_path );
classes/Optimization/Data/DataInterface.php CHANGED
@@ -147,6 +147,19 @@ interface DataInterface {
147
  */
148
  public function delete_optimization_data();
149
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  /**
151
  * Get the media's optimization level.
152
  *
147
  */
148
  public function delete_optimization_data();
149
 
150
+ /**
151
+ * Delete the optimization data for the given sizes.
152
+ * If all sizes are removed, all optimization data is deleted.
153
+ * Status and level are not modified nor removed if the "full" size is removed. This leaves the media in a Schrödinger state.
154
+ *
155
+ * @since 1.9.8
156
+ * @access public
157
+ * @author Grégory Viguier
158
+ *
159
+ * @param array $sizes A list of sizes to remove.
160
+ */
161
+ public function delete_sizes_optimization_data( array $sizes );
162
+
163
  /**
164
  * Get the media's optimization level.
165
  *
classes/Optimization/Data/Noop.php CHANGED
@@ -139,6 +139,19 @@ class Noop implements DataInterface {
139
  */
140
  public function delete_optimization_data() {}
141
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  /**
143
  * Get the media's optimization level.
144
  *
139
  */
140
  public function delete_optimization_data() {}
141
 
142
+ /**
143
+ * Delete the optimization data for the given sizes.
144
+ * If all sizes are removed, all optimization data is deleted.
145
+ * Status and level are not modified nor removed if the "full" size is removed. This leaves the media in a Schrödinger state.
146
+ *
147
+ * @since 1.9.8
148
+ * @access public
149
+ * @author Grégory Viguier
150
+ *
151
+ * @param array $sizes A list of sizes to remove.
152
+ */
153
+ public function delete_sizes_optimization_data( array $sizes ) {}
154
+
155
  /**
156
  * Get the media's optimization level.
157
  *
classes/Optimization/Data/WP.php CHANGED
@@ -140,4 +140,63 @@ class WP extends AbstractData {
140
  delete_post_meta( $id, '_imagify_status' );
141
  delete_post_meta( $id, '_imagify_optimization_level' );
142
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  }
140
  delete_post_meta( $id, '_imagify_status' );
141
  delete_post_meta( $id, '_imagify_optimization_level' );
142
  }
143
+
144
+ /**
145
+ * Delete the optimization data for the given sizes.
146
+ * If all sizes are removed, all optimization data is deleted.
147
+ * Status and level are not modified nor removed if the "full" size is removed. This leaves the media in a Schrödinger state.
148
+ *
149
+ * @since 1.9.8
150
+ * @access public
151
+ * @author Grégory Viguier
152
+ *
153
+ * @param array $sizes A list of sizes to remove.
154
+ */
155
+ public function delete_sizes_optimization_data( array $sizes ) {
156
+ if ( ! $sizes || ! $this->is_valid() ) {
157
+ return;
158
+ }
159
+
160
+ $media_id = $this->get_media()->get_id();
161
+ $data = get_post_meta( $media_id, '_imagify_data', true );
162
+
163
+ if ( empty( $data['sizes'] ) || ! is_array( $data['sizes'] ) ) {
164
+ return;
165
+ }
166
+
167
+ $remaining_sizes_data = array_diff_key( $data['sizes'], array_flip( $sizes ) );
168
+
169
+ if ( ! $remaining_sizes_data ) {
170
+ // All sizes have been removed: delete everything.
171
+ $this->delete_optimization_data();
172
+ return;
173
+ }
174
+
175
+ if ( count( $remaining_sizes_data ) === count( $data['sizes'] ) ) {
176
+ // Nothing has been removed.
177
+ return;
178
+ }
179
+
180
+ $data['sizes'] = $remaining_sizes_data;
181
+
182
+ // Update stats.
183
+ $data['stats'] = [
184
+ 'original_size' => 0,
185
+ 'optimized_size' => 0,
186
+ 'percent' => 0,
187
+ ];
188
+
189
+ foreach ( $data['sizes'] as $size_data ) {
190
+ if ( empty( $size_data['success'] ) ) {
191
+ continue;
192
+ }
193
+
194
+ $data['stats']['original_size'] += $size_data['original_size'];
195
+ $data['stats']['optimized_size'] += $size_data['optimized_size'];
196
+ }
197
+
198
+ $data['stats']['percent'] = round( ( ( $data['stats']['original_size'] - $data['stats']['optimized_size'] ) / $data['stats']['original_size'] ) * 100, 2 );
199
+
200
+ update_post_meta( $media_id, '_imagify_data', $data );
201
+ }
202
  }
classes/Optimization/File.php CHANGED
@@ -173,7 +173,7 @@ class File {
173
  /** ----------------------------------------------------------------------------------------- */
174
 
175
  /**
176
- * Resize an image if it is bigger than the maximum width defined in the settings.
177
  *
178
  * @since 1.9
179
  * @access public
@@ -186,7 +186,7 @@ class File {
186
  * @type int $width The image width.
187
  * @type int $height The image height.
188
  * }
189
- * @param int $max_width Maximum width defined in the settings.
190
  * @return string|WP_Error Path the the resized image. A WP_Error object on failure.
191
  */
192
  public function resize( $dimensions = [], $max_width = 0 ) {
@@ -196,6 +196,13 @@ class File {
196
  return $can_be_processed;
197
  }
198
 
 
 
 
 
 
 
 
199
  if ( ! $this->is_image() ) {
200
  return new \WP_Error(
201
  'not_an_image',
@@ -219,14 +226,43 @@ class File {
219
  $orientation = isset( $exif['Orientation'] ) ? (int) $exif['Orientation'] : 1;
220
 
221
  switch ( $orientation ) {
 
 
 
 
222
  case 3:
223
- $editor->rotate( 180 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
  break;
225
  case 6:
226
- $editor->rotate( -90 );
 
 
 
 
 
 
 
 
 
227
  break;
228
  case 8:
 
229
  $editor->rotate( 90 );
 
230
  }
231
  }
232
 
@@ -234,10 +270,6 @@ class File {
234
  $dimensions = $this->get_dimensions();
235
  }
236
 
237
- if ( ! $max_width ) {
238
- $max_width = $this->get_option( 'resize_larger_w' );
239
- }
240
-
241
  // Prevent removal of the exif data when resizing (only works with Imagick).
242
  add_filter( 'image_strip_meta', '__return_false', 789 );
243
 
@@ -351,23 +383,21 @@ class File {
351
  * Backup a file.
352
  *
353
  * @since 1.9
 
354
  * @access public
355
  * @author Grégory Viguier
356
  *
357
- * @param string $backup_path The backup path.
358
- * @return bool|WP_Error True on success. False if the backup option is disabled. A WP_Error object on failure.
 
359
  */
360
- public function backup( $backup_path = null ) {
361
  $can_be_processed = $this->can_be_processed();
362
 
363
  if ( is_wp_error( $can_be_processed ) ) {
364
  return $can_be_processed;
365
  }
366
 
367
- if ( ! isset( $backup_path ) ) {
368
- $backup_path = get_imagify_attachment_backup_path( $this->path );
369
- }
370
-
371
  // Make sure the backups directory has no errors.
372
  if ( ! $backup_path ) {
373
  return new \WP_Error( 'wp_upload_error', __( 'Error while retrieving the backups directory path.', 'imagify' ) );
@@ -380,6 +410,8 @@ class File {
380
  return new \WP_Error( 'backup_dir_not_writable', __( 'The backup directory is not writable.', 'imagify' ) );
381
  }
382
 
 
 
383
  /**
384
  * Allow to overwrite the backup file if it already exists.
385
  *
@@ -390,15 +422,15 @@ class File {
390
  * @param string $path The file path.
391
  * @param string $backup_path The backup path.
392
  */
393
- $overwrite = apply_filters( 'imagify_backup_overwrite_backup', false, $this->path, $backup_path );
394
 
395
  // Copy the file.
396
- $this->filesystem->copy( $this->path, $backup_path, $overwrite, FS_CHMOD_FILE );
397
 
398
  // Make sure the backup copy exists.
399
  if ( ! $this->filesystem->exists( $backup_path ) ) {
400
  return new \WP_Error( 'backup_doesnt_exist', __( 'The file could not be saved.', 'imagify' ), array(
401
- 'file_path' => $this->filesystem->make_path_relative( $this->path ),
402
  'backup_path' => $this->filesystem->make_path_relative( $backup_path ),
403
  ) );
404
  }
@@ -430,6 +462,7 @@ class File {
430
  $args = array_merge( [
431
  'backup' => true,
432
  'backup_path' => null,
 
433
  'optimization_level' => 0,
434
  'keep_exif' => true,
435
  'convert' => '',
@@ -471,7 +504,7 @@ class File {
471
  do_action_deprecated( 'before_do_imagify', [ $this->path, $args['backup'] ], '1.9', 'imagify_before_optimize_file' );
472
 
473
  if ( $args['backup'] ) {
474
- $backup_result = $this->backup( $args['backup_path'] );
475
 
476
  if ( is_wp_error( $backup_result ) ) {
477
  // Stop the process if we can't backup the file.
173
  /** ----------------------------------------------------------------------------------------- */
174
 
175
  /**
176
+ * Resize (and rotate) an image if it is bigger than the maximum width provided.
177
  *
178
  * @since 1.9
179
  * @access public
186
  * @type int $width The image width.
187
  * @type int $height The image height.
188
  * }
189
+ * @param int $max_width Maximum width to resize to.
190
  * @return string|WP_Error Path the the resized image. A WP_Error object on failure.
191
  */
192
  public function resize( $dimensions = [], $max_width = 0 ) {
196
  return $can_be_processed;
197
  }
198
 
199
+ if ( ! $max_width ) {
200
+ return new \WP_Error(
201
+ 'no_resizing_threshold',
202
+ __( 'No threshold provided for resizing.', 'imagify' )
203
+ );
204
+ }
205
+
206
  if ( ! $this->is_image() ) {
207
  return new \WP_Error(
208
  'not_an_image',
226
  $orientation = isset( $exif['Orientation'] ) ? (int) $exif['Orientation'] : 1;
227
 
228
  switch ( $orientation ) {
229
+ case 2:
230
+ // Flip horizontally.
231
+ $editor->flip( true, false );
232
+ break;
233
  case 3:
234
+ // Rotate 180 degrees or flip horizontally and vertically.
235
+ // Flipping seems faster/uses less resources.
236
+ $editor->flip( true, true );
237
+ break;
238
+ case 4:
239
+ // Flip vertically.
240
+ $editor->flip( false, true );
241
+ break;
242
+ case 5:
243
+ // Rotate 90 degrees counter-clockwise and flip vertically.
244
+ $result = $editor->rotate( 90 );
245
+
246
+ if ( ! is_wp_error( $result ) ) {
247
+ $editor->flip( false, true );
248
+ }
249
  break;
250
  case 6:
251
+ // Rotate 90 degrees clockwise (270 counter-clockwise).
252
+ $editor->rotate( 270 );
253
+ break;
254
+ case 7:
255
+ // Rotate 90 degrees counter-clockwise and flip horizontally.
256
+ $result = $editor->rotate( 90 );
257
+
258
+ if ( ! is_wp_error( $result ) ) {
259
+ $editor->flip( true, false );
260
+ }
261
  break;
262
  case 8:
263
+ // Rotate 90 degrees counter-clockwise.
264
  $editor->rotate( 90 );
265
+ break;
266
  }
267
  }
268
 
270
  $dimensions = $this->get_dimensions();
271
  }
272
 
 
 
 
 
273
  // Prevent removal of the exif data when resizing (only works with Imagick).
274
  add_filter( 'image_strip_meta', '__return_false', 789 );
275
 
383
  * Backup a file.
384
  *
385
  * @since 1.9
386
+ * @since 1.9.8 Added $backup_source argument.
387
  * @access public
388
  * @author Grégory Viguier
389
  *
390
+ * @param string $backup_path The backup path.
391
+ * @param string $backup_source Path to the file to backup. This is useful in WP 5.3+ when we want to optimize the full size: in that case we need to backup the original file.
392
+ * @return bool|WP_Error True on success. False if the backup option is disabled. A WP_Error object on failure.
393
  */
394
+ public function backup( $backup_path = null, $backup_source = null ) {
395
  $can_be_processed = $this->can_be_processed();
396
 
397
  if ( is_wp_error( $can_be_processed ) ) {
398
  return $can_be_processed;
399
  }
400
 
 
 
 
 
401
  // Make sure the backups directory has no errors.
402
  if ( ! $backup_path ) {
403
  return new \WP_Error( 'wp_upload_error', __( 'Error while retrieving the backups directory path.', 'imagify' ) );
410
  return new \WP_Error( 'backup_dir_not_writable', __( 'The backup directory is not writable.', 'imagify' ) );
411
  }
412
 
413
+ $path = $backup_source && $this->filesystem->exists( $backup_source ) ? $backup_source : $this->path;
414
+
415
  /**
416
  * Allow to overwrite the backup file if it already exists.
417
  *
422
  * @param string $path The file path.
423
  * @param string $backup_path The backup path.
424
  */
425
+ $overwrite = apply_filters( 'imagify_backup_overwrite_backup', false, $path, $backup_path );
426
 
427
  // Copy the file.
428
+ $this->filesystem->copy( $path, $backup_path, $overwrite, FS_CHMOD_FILE );
429
 
430
  // Make sure the backup copy exists.
431
  if ( ! $this->filesystem->exists( $backup_path ) ) {
432
  return new \WP_Error( 'backup_doesnt_exist', __( 'The file could not be saved.', 'imagify' ), array(
433
+ 'file_path' => $this->filesystem->make_path_relative( $path ),
434
  'backup_path' => $this->filesystem->make_path_relative( $backup_path ),
435
  ) );
436
  }
462
  $args = array_merge( [
463
  'backup' => true,
464
  'backup_path' => null,
465
+ 'backup_source' => null,
466
  'optimization_level' => 0,
467
  'keep_exif' => true,
468
  'convert' => '',
504
  do_action_deprecated( 'before_do_imagify', [ $this->path, $args['backup'] ], '1.9', 'imagify_before_optimize_file' );
505
 
506
  if ( $args['backup'] ) {
507
+ $backup_result = $this->backup( $args['backup_path'], $args['backup_source'] );
508
 
509
  if ( is_wp_error( $backup_result ) ) {
510
  // Stop the process if we can't backup the file.
classes/Optimization/Process/AbstractProcess.php CHANGED
@@ -14,6 +14,7 @@ defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
14
  * @author Grégory Viguier
15
  */
16
  abstract class AbstractProcess implements ProcessInterface {
 
17
 
18
  /**
19
  * The suffix used in the thumbnail size name.
@@ -176,15 +177,15 @@ abstract class AbstractProcess implements ProcessInterface {
176
  }
177
 
178
  /**
179
- * Get the File instance.
180
  *
181
- * @since 1.9
182
  * @access public
183
  * @author Grégory Viguier
184
  *
185
  * @return File|false
186
  */
187
- public function get_file() {
188
  if ( isset( $this->file ) ) {
189
  return $this->file;
190
  }
@@ -198,6 +199,29 @@ abstract class AbstractProcess implements ProcessInterface {
198
  return $this->file;
199
  }
200
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
  /**
202
  * Tell if the current media is valid.
203
  *
@@ -381,6 +405,9 @@ abstract class AbstractProcess implements ProcessInterface {
381
  if ( 'image/webp' === $files[ $size_name ]['mime-type'] ) {
382
  continue;
383
  }
 
 
 
384
 
385
  array_unshift( $sizes, $size_name . static::WEBP_SUFFIX );
386
  }
@@ -402,7 +429,7 @@ abstract class AbstractProcess implements ProcessInterface {
402
 
403
  if ( $webp ) {
404
  // We have at least one webp conversion to do: create a temporary backup.
405
- $backuped = $this->get_file()->backup( $media->get_raw_backup_path() );
406
 
407
  if ( $backuped ) {
408
  // See \Imagify\Job\MediaOptimization->delete_backup().
@@ -412,6 +439,7 @@ abstract class AbstractProcess implements ProcessInterface {
412
  }
413
  }
414
 
 
415
  $optimization_level = $this->sanitize_optimization_level( $optimization_level );
416
 
417
  /**
@@ -438,7 +466,7 @@ abstract class AbstractProcess implements ProcessInterface {
438
  */
439
  MediaOptimization::get_instance()->push_to_queue( [
440
  'id' => $media->get_id(),
441
- 'sizes' => array_unique( $sizes ),
442
  'optimization_level' => $optimization_level,
443
  'process_class' => get_class( $this ),
444
  'data' => $args,
@@ -652,6 +680,7 @@ abstract class AbstractProcess implements ProcessInterface {
652
  $response = $file->optimize( [
653
  'backup' => ! $response['backuped'] && $this->can_backup( $size ),
654
  'backup_path' => $media->get_raw_backup_path(),
 
655
  'optimization_level' => $optimization_level,
656
  'convert' => $webp ? 'webp' : '',
657
  'keep_exif' => $this->can_keep_exif( $size ),
@@ -847,22 +876,22 @@ abstract class AbstractProcess implements ProcessInterface {
847
 
848
  $this->lock( 'restoring' );
849
 
850
- $backup_path = $media->get_backup_path();
851
- $media_path = $media->get_raw_original_path();
852
 
853
- if ( $backup_path === $media_path ) {
854
  // Uh?!
855
  $this->unlock();
856
  return new \WP_Error( 'same_path', __( 'Image path and backup path are identical.', 'imagify' ) );
857
  }
858
 
859
- $dest_dir = $this->filesystem->dir_path( $media_path );
860
 
861
  if ( ! $this->filesystem->exists( $dest_dir ) ) {
862
  $this->filesystem->make_dir( $dest_dir );
863
  }
864
 
865
- $dest_file_is_writable = ! $this->filesystem->exists( $media_path ) || $this->filesystem->is_writable( $media_path );
866
 
867
  if ( ! $dest_file_is_writable || ! $this->filesystem->is_writable( $dest_dir ) ) {
868
  $this->unlock();
@@ -887,14 +916,14 @@ abstract class AbstractProcess implements ProcessInterface {
887
 
888
  if ( ! is_wp_error( $response ) ) {
889
  // Create the original image from the backup.
890
- $response = $this->filesystem->copy( $backup_path, $media_path, true );
891
 
892
  if ( ! $response ) {
893
  // Failure.
894
  $response = new \WP_Error( 'copy_failed', __( 'The backup file could not be copied over the optimized one.', 'imagify' ) );
895
  } else {
896
  // Backup successfully copied.
897
- $this->filesystem->chmod_file( $media_path );
898
 
899
  // Remove old optimization data.
900
  $this->get_data()->delete_optimization_data();
@@ -904,7 +933,7 @@ abstract class AbstractProcess implements ProcessInterface {
904
  $media->update_dimensions();
905
 
906
  // Delete the webp version.
907
- $this->delete_webp_file( $media_path );
908
 
909
  // Restore the thumbnails.
910
  $response = $this->restore_thumbnails();
@@ -940,10 +969,18 @@ abstract class AbstractProcess implements ProcessInterface {
940
  * @return bool|WP_Error True on success. A \WP_Error instance on failure.
941
  */
942
  protected function restore_thumbnails() {
943
- // Delete the webp versions.
944
- $this->delete_webp_files( true );
 
 
 
 
 
 
 
 
945
  // Generate new thumbnails.
946
- return $this->get_media()->generate_thumbnails();
947
  }
948
 
949
 
@@ -1144,7 +1181,7 @@ abstract class AbstractProcess implements ProcessInterface {
1144
  */
1145
  protected function get_temporary_copy_path( $size, $sizes = null ) {
1146
  if ( 'full' === $size ) {
1147
- $path = $this->get_media()->get_raw_original_path();
1148
  } else {
1149
  if ( ! isset( $sizes ) ) {
1150
  $sizes = $this->get_media()->get_media_files();
@@ -1216,7 +1253,7 @@ abstract class AbstractProcess implements ProcessInterface {
1216
  );
1217
  }
1218
 
1219
- $resize_width = $this->get_option( 'resize_larger_w' );
1220
 
1221
  if ( $resize_width >= $dimensions['width'] ) {
1222
  // No need to resize.
@@ -1242,7 +1279,8 @@ abstract class AbstractProcess implements ProcessInterface {
1242
  }
1243
 
1244
  if ( $this->can_backup( $size ) ) {
1245
- $backuped = $file->backup( $media->get_raw_backup_path() );
 
1246
 
1247
  if ( is_wp_error( $backuped ) ) {
1248
  // The backup failed.
14
  * @author Grégory Viguier
15
  */
16
  abstract class AbstractProcess implements ProcessInterface {
17
+ use \Imagify\Deprecated\Traits\Optimization\Process\AbstractProcessDeprecatedTrait;
18
 
19
  /**
20
  * The suffix used in the thumbnail size name.
177
  }
178
 
179
  /**
180
+ * Get the File instance of the original file.
181
  *
182
+ * @since 1.9.8
183
  * @access public
184
  * @author Grégory Viguier
185
  *
186
  * @return File|false
187
  */
188
+ public function get_original_file() {
189
  if ( isset( $this->file ) ) {
190
  return $this->file;
191
  }
199
  return $this->file;
200
  }
201
 
202
+ /**
203
+ * Get the File instance of the full size file.
204
+ *
205
+ * @since 1.9.8
206
+ * @access public
207
+ * @author Grégory Viguier
208
+ *
209
+ * @return File|false
210
+ */
211
+ public function get_fullsize_file() {
212
+ if ( isset( $this->file ) ) {
213
+ return $this->file;
214
+ }
215
+
216
+ $this->file = false;
217
+
218
+ if ( $this->get_media() ) {
219
+ $this->file = new File( $this->get_media()->get_raw_fullsize_path() );
220
+ }
221
+
222
+ return $this->file;
223
+ }
224
+
225
  /**
226
  * Tell if the current media is valid.
227
  *
405
  if ( 'image/webp' === $files[ $size_name ]['mime-type'] ) {
406
  continue;
407
  }
408
+ if ( in_array( $size_name . static::WEBP_SUFFIX, $sizes, true ) ) {
409
+ continue;
410
+ }
411
 
412
  array_unshift( $sizes, $size_name . static::WEBP_SUFFIX );
413
  }
429
 
430
  if ( $webp ) {
431
  // We have at least one webp conversion to do: create a temporary backup.
432
+ $backuped = $this->get_original_file()->backup( $media->get_raw_backup_path() );
433
 
434
  if ( $backuped ) {
435
  // See \Imagify\Job\MediaOptimization->delete_backup().
439
  }
440
  }
441
 
442
+ $sizes = array_unique( $sizes );
443
  $optimization_level = $this->sanitize_optimization_level( $optimization_level );
444
 
445
  /**
466
  */
467
  MediaOptimization::get_instance()->push_to_queue( [
468
  'id' => $media->get_id(),
469
+ 'sizes' => $sizes,
470
  'optimization_level' => $optimization_level,
471
  'process_class' => get_class( $this ),
472
  'data' => $args,
680
  $response = $file->optimize( [
681
  'backup' => ! $response['backuped'] && $this->can_backup( $size ),
682
  'backup_path' => $media->get_raw_backup_path(),
683
+ 'backup_source' => 'full' === $thumb_size ? $media->get_original_path() : null,
684
  'optimization_level' => $optimization_level,
685
  'convert' => $webp ? 'webp' : '',
686
  'keep_exif' => $this->can_keep_exif( $size ),
876
 
877
  $this->lock( 'restoring' );
878
 
879
+ $backup_path = $media->get_backup_path();
880
+ $original_path = $media->get_raw_original_path();
881
 
882
+ if ( $backup_path === $original_path ) {
883
  // Uh?!
884
  $this->unlock();
885
  return new \WP_Error( 'same_path', __( 'Image path and backup path are identical.', 'imagify' ) );
886
  }
887
 
888
+ $dest_dir = $this->filesystem->dir_path( $original_path );
889
 
890
  if ( ! $this->filesystem->exists( $dest_dir ) ) {
891
  $this->filesystem->make_dir( $dest_dir );
892
  }
893
 
894
+ $dest_file_is_writable = ! $this->filesystem->exists( $original_path ) || $this->filesystem->is_writable( $original_path );
895
 
896
  if ( ! $dest_file_is_writable || ! $this->filesystem->is_writable( $dest_dir ) ) {
897
  $this->unlock();
916
 
917
  if ( ! is_wp_error( $response ) ) {
918
  // Create the original image from the backup.
919
+ $response = $this->filesystem->copy( $backup_path, $original_path, true );
920
 
921
  if ( ! $response ) {
922
  // Failure.
923
  $response = new \WP_Error( 'copy_failed', __( 'The backup file could not be copied over the optimized one.', 'imagify' ) );
924
  } else {
925
  // Backup successfully copied.
926
+ $this->filesystem->chmod_file( $original_path );
927
 
928
  // Remove old optimization data.
929
  $this->get_data()->delete_optimization_data();
933
  $media->update_dimensions();
934
 
935
  // Delete the webp version.
936
+ $this->delete_webp_file( $original_path );
937
 
938
  // Restore the thumbnails.
939
  $response = $this->restore_thumbnails();
969
  * @return bool|WP_Error True on success. A \WP_Error instance on failure.
970
  */
971
  protected function restore_thumbnails() {
972
+ $media = $this->get_media();
973
+
974
+ /**
975
+ * Delete the webp versions.
976
+ * If the full size file and the original file are not the same, the full size is considered like a thumbnail.
977
+ * In that case we must also delete the webp file associated to the full size.
978
+ */
979
+ $keep_full_webp = $media->get_raw_original_path() === $media->get_raw_fullsize_path();
980
+ $this->delete_webp_files( $keep_full_webp );
981
+
982
  // Generate new thumbnails.
983
+ return $media->generate_thumbnails();
984
  }
985
 
986
 
1181
  */
1182
  protected function get_temporary_copy_path( $size, $sizes = null ) {
1183
  if ( 'full' === $size ) {
1184
+ $path = $this->get_media()->get_raw_fullsize_path();
1185
  } else {
1186
  if ( ! isset( $sizes ) ) {
1187
  $sizes = $this->get_media()->get_media_files();
1253
  );
1254
  }
1255
 
1256
+ $resize_width = $media->get_context_instance()->get_resizing_threshold();
1257
 
1258
  if ( $resize_width >= $dimensions['width'] ) {
1259
  // No need to resize.
1279
  }
1280
 
1281
  if ( $this->can_backup( $size ) ) {
1282
+ $source = 'full' === $size ? $media->get_original_path() : null;
1283
+ $backuped = $file->backup( $media->get_raw_backup_path(), $source );
1284
 
1285
  if ( is_wp_error( $backuped ) ) {
1286
  // The backup failed.
classes/Optimization/Process/ProcessInterface.php CHANGED
@@ -47,15 +47,26 @@ interface ProcessInterface {
47
  public function get_media();
48
 
49
  /**
50
- * Get the File instance.
51
  *
52
- * @since 1.9
 
 
 
 
 
 
 
 
 
 
 
53
  * @access public
54
  * @author Grégory Viguier
55
  *
56
  * @return File|false
57
  */
58
- public function get_file();
59
 
60
  /**
61
  * Tell if the current media is valid.
47
  public function get_media();
48
 
49
  /**
50
+ * Get the File instance of the original file.
51
  *
52
+ * @since 1.9.8
53
+ * @access public
54
+ * @author Grégory Viguier
55
+ *
56
+ * @return File|false
57
+ */
58
+ public function get_original_file();
59
+
60
+ /**
61
+ * Get the File instance of the full size file.
62
+ *
63
+ * @since 1.9.8
64
  * @access public
65
  * @author Grégory Viguier
66
  *
67
  * @return File|false
68
  */
69
+ public function get_fullsize_file();
70
 
71
  /**
72
  * Tell if the current media is valid.
classes/Optimization/Process/WP.php CHANGED
@@ -214,8 +214,8 @@ class WP extends AbstractProcess {
214
  $metadata = wp_get_attachment_metadata( $media_id );
215
  $metadata['sizes'] = ! empty( $metadata['sizes'] ) && is_array( $metadata['sizes'] ) ? $metadata['sizes'] : [];
216
 
217
- $destination_dir = $this->filesystem->dir_path( $media->get_raw_original_path() );
218
- $file = new File( $media->get_backup_path() );
219
  $without_errors = [];
220
  $has_new_data = false;
221
 
@@ -225,7 +225,7 @@ class WP extends AbstractProcess {
225
  $thumbnail_data['path'] = $destination_dir . $thumbnail_data['file'];
226
 
227
  if ( ! $this->filesystem->exists( $thumbnail_data['path'] ) ) {
228
- $result = $file->create_thumbnail( $thumbnail_data );
229
 
230
  if ( is_array( $result ) ) {
231
  // New file.
214
  $metadata = wp_get_attachment_metadata( $media_id );
215
  $metadata['sizes'] = ! empty( $metadata['sizes'] ) && is_array( $metadata['sizes'] ) ? $metadata['sizes'] : [];
216
 
217
+ $destination_dir = $this->filesystem->dir_path( $media->get_raw_fullsize_path() );
218
+ $backup_file = new File( $media->get_backup_path() );
219
  $without_errors = [];
220
  $has_new_data = false;
221
 
225
  $thumbnail_data['path'] = $destination_dir . $thumbnail_data['file'];
226
 
227
  if ( ! $this->filesystem->exists( $thumbnail_data['path'] ) ) {
228
+ $result = $backup_file->create_thumbnail( $thumbnail_data );
229
 
230
  if ( is_array( $result ) ) {
231
  // New file.
classes/Webp/Picture/Display.php CHANGED
@@ -168,6 +168,8 @@ class Display {
168
  protected function build_picture_tag( $image ) {
169
  $to_remove = [
170
  'alt' => '',
 
 
171
  'data-lazy-src' => '',
172
  'data-src' => '',
173
  'src' => '',
@@ -225,9 +227,7 @@ class Display {
225
  $srcset_source = ! empty( $image['srcset_attribute'] ) ? $image['srcset_attribute'] : $image['src_attribute'] . 'set';
226
  $attributes = [
227
  'type' => 'image/webp',
228
- $srcset_source => [
229
- $image['src']['webp_url'],
230
- ],
231
  ];
232
 
233
  if ( ! empty( $image['srcset'] ) ) {
@@ -235,9 +235,6 @@ class Display {
235
  if ( empty( $srcset['webp_url'] ) ) {
236
  continue;
237
  }
238
- if ( $srcset['webp_url'] === $image['src']['webp_url'] ) {
239
- continue;
240
- }
241
 
242
  $attributes[ $srcset_source ][] = $srcset['webp_url'] . ' ' . $srcset['descriptor'];
243
  }
@@ -290,11 +287,9 @@ class Display {
290
  protected function build_img_tag( $image ) {
291
  $to_remove = [
292
  'class' => '',
293
- 'height' => '',
294
  'id' => '',
295
  'style' => '',
296
  'title' => '',
297
- 'width' => '',
298
  ];
299
 
300
  $attributes = array_diff_key( $image['attributes'], $to_remove );
@@ -630,7 +625,7 @@ class Display {
630
 
631
  $url = set_url_scheme( $url );
632
 
633
- if ( $domain_url && stripos( $url, $cdn_url ) === 0 ) {
634
  // CDN.
635
  $url = str_ireplace( $cdn_url, $domain_url, $url );
636
  }
168
  protected function build_picture_tag( $image ) {
169
  $to_remove = [
170
  'alt' => '',
171
+ 'height' => '',
172
+ 'width' => '',
173
  'data-lazy-src' => '',
174
  'data-src' => '',
175
  'src' => '',
227
  $srcset_source = ! empty( $image['srcset_attribute'] ) ? $image['srcset_attribute'] : $image['src_attribute'] . 'set';
228
  $attributes = [
229
  'type' => 'image/webp',
230
+ $srcset_source => [],
 
 
231
  ];
232
 
233
  if ( ! empty( $image['srcset'] ) ) {
235
  if ( empty( $srcset['webp_url'] ) ) {
236
  continue;
237
  }
 
 
 
238
 
239
  $attributes[ $srcset_source ][] = $srcset['webp_url'] . ' ' . $srcset['descriptor'];
240
  }
287
  protected function build_img_tag( $image ) {
288
  $to_remove = [
289
  'class' => '',
 
290
  'id' => '',
291
  'style' => '',
292
  'title' => '',
 
293
  ];
294
 
295
  $attributes = array_diff_key( $image['attributes'], $to_remove );
625
 
626
  $url = set_url_scheme( $url );
627
 
628
+ if ( $cdn_url && $domain_url && stripos( $url, $cdn_url ) === 0 ) {
629
  // CDN.
630
  $url = str_ireplace( $cdn_url, $domain_url, $url );
631
  }
composer.json CHANGED
@@ -44,6 +44,7 @@
44
  "autoload": {
45
  "psr-4": {
46
  "Imagify\\": "classes/",
 
47
  "Imagify\\ThirdParty\\AS3CF\\": "inc/3rd-party/amazon-s3-and-cloudfront/classes/",
48
  "Imagify\\ThirdParty\\EnableMediaReplace\\": "inc/3rd-party/enable-media-replace/classes/",
49
  "Imagify\\ThirdParty\\FormidablePro\\": "inc/3rd-party/formidable-pro/classes/",
44
  "autoload": {
45
  "psr-4": {
46
  "Imagify\\": "classes/",
47
+ "Imagify\\Deprecated\\Traits\\": "inc/deprecated/Traits/",
48
  "Imagify\\ThirdParty\\AS3CF\\": "inc/3rd-party/amazon-s3-and-cloudfront/classes/",
49
  "Imagify\\ThirdParty\\EnableMediaReplace\\": "inc/3rd-party/enable-media-replace/classes/",
50
  "Imagify\\ThirdParty\\FormidablePro\\": "inc/3rd-party/formidable-pro/classes/",
imagify.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Imagify
4
  * Plugin URI: https://wordpress.org/plugins/imagify/
5
  * Description: Dramaticaly reduce image file sizes without losing quality, make your website load faster, boost your SEO and save money on your bandwidth using Imagify, the new most advanced image optimization tool.
6
- * Version: 1.9.7
7
  * Requires PHP: 5.4
8
  * Author: WP Media
9
  * Author URI: https://wp-media.me/
@@ -20,7 +20,7 @@
20
  defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
21
 
22
  // Imagify defines.
23
- define( 'IMAGIFY_VERSION', '1.9.7' );
24
  define( 'IMAGIFY_SLUG', 'imagify' );
25
  define( 'IMAGIFY_FILE', __FILE__ );
26
  define( 'IMAGIFY_PATH', realpath( plugin_dir_path( IMAGIFY_FILE ) ) . '/' );
3
  * Plugin Name: Imagify
4
  * Plugin URI: https://wordpress.org/plugins/imagify/
5
  * Description: Dramaticaly reduce image file sizes without losing quality, make your website load faster, boost your SEO and save money on your bandwidth using Imagify, the new most advanced image optimization tool.
6
+ * Version: 1.9.8
7
  * Requires PHP: 5.4
8
  * Author: WP Media
9
  * Author URI: https://wp-media.me/
20
  defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
21
 
22
  // Imagify defines.
23
+ define( 'IMAGIFY_VERSION', '1.9.8' );
24
  define( 'IMAGIFY_SLUG', 'imagify' );
25
  define( 'IMAGIFY_FILE', __FILE__ );
26
  define( 'IMAGIFY_PATH', realpath( plugin_dir_path( IMAGIFY_FILE ) ) . '/' );
inc/3rd-party/amazon-s3-and-cloudfront/classes/CDN/WP/AS3.php CHANGED
@@ -34,6 +34,16 @@ class AS3 implements PushCDNInterface {
34
  */
35
  protected $filesystem;
36
 
 
 
 
 
 
 
 
 
 
 
37
  /**
38
  * Constructor.
39
  *
@@ -309,17 +319,35 @@ class AS3 implements PushCDNInterface {
309
  * @access public
310
  * @author Grégory Viguier
311
  *
312
- * @param string $file_name Name of the file. Leave empty for the full size file.
313
  * @return string Path to the file.
314
  */
315
  public function get_file_path( $file_name = false ) {
316
- $file_path = get_attached_file( $this->id, true );
 
 
 
317
 
318
- if ( $file_name ) {
319
- // It's not the full size.
320
- $file_path = $this->filesystem->dir_path( $file_path ) . $file_name;
 
 
 
 
 
 
 
 
 
 
 
321
  }
322
 
 
 
 
 
323
  return $file_path;
324
  }
325
 
@@ -463,4 +491,23 @@ class AS3 implements PushCDNInterface {
463
  // If the attachment has a 'filesize' metadata, that means the local files are meant to be deleted.
464
  return (bool) get_post_meta( $this->id, 'wpos3_filesize_total', true );
465
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
466
  }
34
  */
35
  protected $filesystem;
36
 
37
+ /**
38
+ * Tell if we’re playing in WP 5.3’s garden.
39
+ *
40
+ * @var bool
41
+ * @since 1.9.8
42
+ * @access protected
43
+ * @author Grégory Viguier
44
+ */
45
+ protected $is_wp53;
46
+
47
  /**
48
  * Constructor.
49
  *
319
  * @access public
320
  * @author Grégory Viguier
321
  *
322
+ * @param string $file_name Name of the file. Leave empty for the full size file. Use 'original' to get the path to the original file.
323
  * @return string Path to the file.
324
  */
325
  public function get_file_path( $file_name = false ) {
326
+ if ( ! $file_name ) {
327
+ // Full size.
328
+ return get_attached_file( $this->id, true );
329
+ }
330
 
331
+ if ( 'original' === $file_name ) {
332
+ // Original file.
333
+ if ( $this->is_wp_53() ) {
334
+ // `wp_get_original_image_path()` may return false.
335
+ $file_path = wp_get_original_image_path( $this->id );
336
+ } else {
337
+ $file_path = false;
338
+ }
339
+
340
+ if ( ! $file_path ) {
341
+ $file_path = get_attached_file( $this->id, true );
342
+ }
343
+
344
+ return $file_path;
345
  }
346
 
347
+ // Thumbnail.
348
+ $file_path = get_attached_file( $this->id, true );
349
+ $file_path = $this->filesystem->dir_path( $file_path ) . $file_name;
350
+
351
  return $file_path;
352
  }
353
 
491
  // If the attachment has a 'filesize' metadata, that means the local files are meant to be deleted.
492
  return (bool) get_post_meta( $this->id, 'wpos3_filesize_total', true );
493
  }
494
+
495
+ /**
496
+ * Tell if we’re playing in WP 5.3’s garden.
497
+ *
498
+ * @since 1.9.8
499
+ * @access protected
500
+ * @author Grégory Viguier
501
+ *
502
+ * @return bool
503
+ */
504
+ protected function is_wp_53() {
505
+ if ( isset( $this->is_wp53 ) ) {
506
+ return $this->is_wp53;
507
+ }
508
+
509
+ $this->is_wp53 = function_exists( 'wp_get_original_image_path' );
510
+
511
+ return $this->is_wp53;
512
+ }
513
  }
inc/3rd-party/enable-media-replace/classes/Main.php CHANGED
@@ -51,6 +51,16 @@ class Main extends \Imagify_Enable_Media_Replace_Deprecated {
51
  */
52
  protected $old_backup_path;
53
 
 
 
 
 
 
 
 
 
 
 
54
  /**
55
  * Launch the hooks before the files and data are replaced.
56
  *
@@ -76,6 +86,21 @@ class Main extends \Imagify_Enable_Media_Replace_Deprecated {
76
  return $unfiltered;
77
  }
78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  // Store the old backup file path.
80
  add_filter( 'emr_unique_filename', [ $this, 'store_old_backup_path' ], 10, 3 );
81
  // Delete the old backup file.
@@ -114,13 +139,24 @@ class Main extends \Imagify_Enable_Media_Replace_Deprecated {
114
  return $new_filename;
115
  }
116
 
117
- $backup_path = $this->process->get_media()->get_backup_path();
 
118
 
119
  if ( $backup_path ) {
120
  $this->old_backup_path = $backup_path;
 
 
 
 
 
 
 
 
 
121
  } else {
122
  $this->media_id = 0;
123
  $this->old_backup_path = false;
 
124
  }
125
 
126
  return $new_filename;
@@ -143,12 +179,17 @@ class Main extends \Imagify_Enable_Media_Replace_Deprecated {
143
 
144
  $filesystem = \Imagify_Filesystem::get_instance();
145
 
146
- if ( ! $filesystem->exists( $this->old_backup_path ) ) {
147
- return;
 
148
  }
149
 
150
- $filesystem->delete( $this->old_backup_path );
151
- $this->old_backup_path = false;
 
 
 
 
152
  }
153
 
154
 
51
  */
52
  protected $old_backup_path;
53
 
54
+ /**
55
+ * List of paths to the old webp files.
56
+ *
57
+ * @var array
58
+ * @since 1.9.8
59
+ * @access protected
60
+ * @author Grégory Viguier
61
+ */
62
+ protected $old_webp_paths = [];
63
+
64
  /**
65
  * Launch the hooks before the files and data are replaced.
66
  *
86
  return $unfiltered;
87
  }
88
 
89
+ // Store the old backup file path.
90
+ $this->get_process();
91
+
92
+ if ( ! $this->process ) {
93
+ $this->media_id = 0;
94
+ return $unfiltered;
95
+ }
96
+
97
+ $this->old_backup_path = $this->process->get_media()->get_backup_path();
98
+
99
+ if ( ! $this->old_backup_path ) {
100
+ $this->media_id = 0;
101
+ return $unfiltered;
102
+ }
103
+
104
  // Store the old backup file path.
105
  add_filter( 'emr_unique_filename', [ $this, 'store_old_backup_path' ], 10, 3 );
106
  // Delete the old backup file.
139
  return $new_filename;
140
  }
141
 
142
+ $media = $this->process->get_media();
143
+ $backup_path = $media->get_backup_path();
144
 
145
  if ( $backup_path ) {
146
  $this->old_backup_path = $backup_path;
147
+
148
+ // Keep track of existing webp files.
149
+ $media_files = $media->get_media_files();
150
+
151
+ if ( $media_files ) {
152
+ foreach ( $media_files as $media_file ) {
153
+ $this->old_webp_paths[] = imagify_path_to_webp( $media_file['path'] );
154
+ }
155
+ }
156
  } else {
157
  $this->media_id = 0;
158
  $this->old_backup_path = false;
159
+ $this->old_webp_paths = [];
160
  }
161
 
162
  return $new_filename;
179
 
180
  $filesystem = \Imagify_Filesystem::get_instance();
181
 
182
+ if ( $filesystem->exists( $this->old_backup_path ) ) {
183
+ $filesystem->delete( $this->old_backup_path );
184
+ $this->old_backup_path = false;
185
  }
186
 
187
+ if ( $this->old_webp_paths ) {
188
+ // If the files have been renamed, delete old webp files.
189
+ $this->old_webp_paths = array_filter( $this->old_webp_paths, [ $filesystem, 'exists' ] );
190
+ array_map( [ $filesystem, 'delete' ], $this->old_webp_paths );
191
+ $this->old_webp_paths = [];
192
+ }
193
  }
194
 
195
 
inc/3rd-party/enable-media-replace/enable-media-replace.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
3
 
4
- if ( function_exists( 'enable_media_replace' ) ) :
5
 
6
  class_alias( '\\Imagify\\ThirdParty\\EnableMediaReplace\\Main', '\\Imagify_Enable_Media_Replace' );
7
 
1
  <?php
2
  defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
3
 
4
+ if ( function_exists( 'enable_media_replace' ) || class_exists( '\\EnableMediaReplace\\EnableMediaReplacePlugin' ) ) :
5
 
6
  class_alias( '\\Imagify\\ThirdParty\\EnableMediaReplace\\Main', '\\Imagify_Enable_Media_Replace' );
7
 
inc/3rd-party/nextgen-gallery/classes/Context/NGG.php CHANGED
@@ -55,34 +55,38 @@ class NGG extends \Imagify\Context\AbstractContext {
55
  protected $thumbnail_sizes = [];
56
 
57
  /**
58
- * Tell if the optimization process is allowed resize in this context.
59
  *
60
  * @var bool
61
  * @since 1.9
62
  * @access protected
63
  * @author Grégory Viguier
64
  */
65
- protected $can_resize = false;
66
 
67
  /**
68
- * Tell if the optimization process is allowed to backup in this context.
69
  *
70
  * @var bool
71
  * @since 1.9
72
  * @access protected
73
  * @author Grégory Viguier
74
  */
75
- protected $can_backup = true;
76
 
77
  /**
78
- * Tell if the optimization process is allowed to keep exif in this context.
 
79
  *
80
- * @var bool
81
- * @since 1.9
82
- * @access protected
83
  * @author Grégory Viguier
 
 
84
  */
85
- protected $can_keep_exif = true;
 
 
86
 
87
  /**
88
  * Get user capacity to operate Imagify in this context.
55
  protected $thumbnail_sizes = [];
56
 
57
  /**
58
+ * Tell if the optimization process is allowed to backup in this context.
59
  *
60
  * @var bool
61
  * @since 1.9
62
  * @access protected
63
  * @author Grégory Viguier
64
  */
65
+ protected $can_backup = true;
66
 
67
  /**
68
+ * Tell if the optimization process is allowed to keep exif in this context.
69
  *
70
  * @var bool
71
  * @since 1.9
72
  * @access protected
73
  * @author Grégory Viguier
74
  */
75
+ protected $can_keep_exif = true;
76
 
77
  /**
78
+ * Get images max width for this context. This is used when resizing.
79
+ * 0 means to not resize.
80
  *
81
+ * @since 1.9.8
82
+ * @access public
 
83
  * @author Grégory Viguier
84
+ *
85
+ * @return int
86
  */
87
+ public function get_resizing_threshold() {
88
+ return 0;
89
+ }
90
 
91
  /**
92
  * Get user capacity to operate Imagify in this context.
inc/3rd-party/nextgen-gallery/classes/DynamicThumbnails.php CHANGED
@@ -107,7 +107,7 @@ class DynamicThumbnails {
107
  continue;
108
  }
109
 
110
- $sizes = array_unique( $sizes, true );
111
 
112
  foreach ( $sizes as $i => $size ) {
113
  $size_status = $data->get_size_data( $size, 'success' );
107
  continue;
108
  }
109
 
110
+ $sizes = array_unique( $sizes );
111
 
112
  foreach ( $sizes as $i => $size ) {
113
  $size_status = $data->get_size_data( $size, 'success' );
inc/3rd-party/nextgen-gallery/classes/Media/NGG.php CHANGED
@@ -10,6 +10,7 @@ defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
10
  * @author Grégory Viguier
11
  */
12
  class NGG extends \Imagify\Media\AbstractMedia {
 
13
 
14
  /**
15
  * Context (where the media "comes from").
@@ -151,15 +152,41 @@ class NGG extends \Imagify\Media\AbstractMedia {
151
  /** ----------------------------------------------------------------------------------------- */
152
 
153
  /**
154
- * Get the original media's URL.
155
  *
156
  * @since 1.9
157
  * @access public
158
  * @author Grégory Viguier
159
  *
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  * @return string|bool The file URL. False on failure.
161
  */
162
- public function get_original_url() {
163
  if ( ! $this->is_valid() ) {
164
  return false;
165
  }
@@ -172,15 +199,15 @@ class NGG extends \Imagify\Media\AbstractMedia {
172
  }
173
 
174
  /**
175
- * Get the original media's path.
176
  *
177
- * @since 1.9
178
  * @access public
179
  * @author Grégory Viguier
180
  *
181
  * @return string|bool The file path. False on failure.
182
  */
183
- public function get_raw_original_path() {
184
  if ( ! $this->is_valid() ) {
185
  return false;
186
  }
@@ -357,18 +384,18 @@ class NGG extends \Imagify\Media\AbstractMedia {
357
  $sizes = $this->get_media_files();
358
  }
359
 
360
- return $sizes && $this->get_raw_original_path();
361
  }
362
 
363
  /**
364
- * Get the list of the files of this media, including the original file.
365
  *
366
  * @since 1.9
367
  * @access public
368
  * @author Grégory Viguier
369
  *
370
  * @return array {
371
- * An array with the size names as keys ('full' is used for the original file), and arrays of data as values:
372
  *
373
  * @type string $size The size name.
374
  * @type string $path Absolute path to the file.
@@ -383,9 +410,9 @@ class NGG extends \Imagify\Media\AbstractMedia {
383
  return [];
384
  }
385
 
386
- $original_path = $this->get_raw_original_path();
387
 
388
- if ( ! $original_path ) {
389
  return [];
390
  }
391
 
@@ -393,7 +420,7 @@ class NGG extends \Imagify\Media\AbstractMedia {
393
  $all_sizes = [
394
  'full' => [
395
  'size' => 'full',
396
- 'path' => $original_path,
397
  'width' => $dimensions['width'],
398
  'height' => $dimensions['height'],
399
  'mime-type' => $this->get_mime_type(),
@@ -499,7 +526,7 @@ class NGG extends \Imagify\Media\AbstractMedia {
499
  $data = [
500
  'width' => $dimensions['width'],
501
  'height' => $dimensions['height'],
502
- 'md5' => md5_file( $this->get_raw_original_path() ),
503
  ];
504
 
505
  foreach ( $data as $k => $v ) {
10
  * @author Grégory Viguier
11
  */
12
  class NGG extends \Imagify\Media\AbstractMedia {
13
+ use \Imagify\Deprecated\Traits\Media\NGGDeprecatedTrait;
14
 
15
  /**
16
  * Context (where the media "comes from").
152
  /** ----------------------------------------------------------------------------------------- */
153
 
154
  /**
155
+ * Get the original file path, even if the file doesn't exist.
156
  *
157
  * @since 1.9
158
  * @access public
159
  * @author Grégory Viguier
160
  *
161
+ * @return string|bool The file path. False on failure.
162
+ */
163
+ public function get_raw_original_path() {
164
+ if ( ! $this->is_valid() ) {
165
+ return false;
166
+ }
167
+
168
+ if ( $this->get_cdn() ) {
169
+ return $this->get_cdn()->get_file_path( 'original' );
170
+ }
171
+
172
+ return ! empty( $this->image->imagePath ) ? $this->image->imagePath : false;
173
+ }
174
+
175
+
176
+ /** ----------------------------------------------------------------------------------------- */
177
+ /** FULL SIZE FILE ========================================================================== */
178
+ /** ----------------------------------------------------------------------------------------- */
179
+
180
+ /**
181
+ * Get the URL of the media’s full size file.
182
+ *
183
+ * @since 1.9.8
184
+ * @access public
185
+ * @author Grégory Viguier
186
+ *
187
  * @return string|bool The file URL. False on failure.
188
  */
189
+ public function get_fullsize_url() {
190
  if ( ! $this->is_valid() ) {
191
  return false;
192
  }
199
  }
200
 
201
  /**
202
+ * Get the path to the medias full size file, even if the file doesn't exist.
203
  *
204
+ * @since 1.9.8
205
  * @access public
206
  * @author Grégory Viguier
207
  *
208
  * @return string|bool The file path. False on failure.
209
  */
210
+ public function get_raw_fullsize_path() {
211
  if ( ! $this->is_valid() ) {
212
  return false;
213
  }
384
  $sizes = $this->get_media_files();
385
  }
386
 
387
+ return $sizes && ! empty( $this->image->imagePath );
388
  }
389
 
390
  /**
391
+ * Get the list of the files of this media, including the full size file.
392
  *
393
  * @since 1.9
394
  * @access public
395
  * @author Grégory Viguier
396
  *
397
  * @return array {
398
+ * An array with the size names as keys ('full' is used for the full size file), and arrays of data as values:
399
  *
400
  * @type string $size The size name.
401
  * @type string $path Absolute path to the file.
410
  return [];
411
  }
412
 
413
+ $fullsize_path = $this->get_raw_fullsize_path();
414
 
415
+ if ( ! $fullsize_path ) {
416
  return [];
417
  }
418
 
420
  $all_sizes = [
421
  'full' => [
422
  'size' => 'full',
423
+ 'path' => $fullsize_path,
424
  'width' => $dimensions['width'],
425
  'height' => $dimensions['height'],
426
  'mime-type' => $this->get_mime_type(),
526
  $data = [
527
  'width' => $dimensions['width'],
528
  'height' => $dimensions['height'],
529
+ 'md5' => md5_file( $this->get_raw_fullsize_path() ),
530
  ];
531
 
532
  foreach ( $data as $k => $v ) {
inc/3rd-party/nextgen-gallery/classes/Optimization/Data/NGG.php CHANGED
@@ -69,6 +69,11 @@ class NGG extends \Imagify\Optimization\Data\AbstractData {
69
  $data['status'] = $row['status'];
70
  $data['level'] = $row['optimization_level'];
71
  $data['level'] = is_numeric( $data['level'] ) ? (int) $data['level'] : false;
 
 
 
 
 
72
 
73
  if ( ! empty( $row['data']['sizes'] ) && is_array( $row['data']['sizes'] ) ) {
74
  $data['sizes'] = $row['data']['sizes'];
@@ -139,7 +144,6 @@ class NGG extends \Imagify\Optimization\Data\AbstractData {
139
  $old_data = array_merge( $this->get_reset_data(), $this->get_row() );
140
 
141
  $old_data['data']['sizes'] = ! empty( $old_data['data']['sizes'] ) && is_array( $old_data['data']['sizes'] ) ? $old_data['data']['sizes'] : [];
142
- $old_data['data']['stats'] = ! empty( $old_data['data']['stats'] ) && is_array( $old_data['data']['stats'] ) ? $old_data['data']['stats'] : [];
143
 
144
  if ( 'full' === $size ) {
145
  /**
@@ -187,6 +191,48 @@ class NGG extends \Imagify\Optimization\Data\AbstractData {
187
  $this->delete_row();
188
  }
189
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
  /**
191
  * Get default values used to reset optimization data.
192
  *
69
  $data['status'] = $row['status'];
70
  $data['level'] = $row['optimization_level'];
71
  $data['level'] = is_numeric( $data['level'] ) ? (int) $data['level'] : false;
72
+ $data['stats'] = [
73
+ 'original_size' => 0,
74
+ 'optimized_size' => 0,
75
+ 'percent' => 0,
76
+ ];
77
 
78
  if ( ! empty( $row['data']['sizes'] ) && is_array( $row['data']['sizes'] ) ) {
79
  $data['sizes'] = $row['data']['sizes'];
144
  $old_data = array_merge( $this->get_reset_data(), $this->get_row() );
145
 
146
  $old_data['data']['sizes'] = ! empty( $old_data['data']['sizes'] ) && is_array( $old_data['data']['sizes'] ) ? $old_data['data']['sizes'] : [];
 
147
 
148
  if ( 'full' === $size ) {
149
  /**
191
  $this->delete_row();
192
  }
193
 
194
+ /**
195
+ * Delete the optimization data for the given sizes.
196
+ * If all sizes are removed, all optimization data is deleted.
197
+ * Status and level are not modified nor removed if the "full" size is removed. This leaves the media in a Schrödinger state.
198
+ *
199
+ * @since 1.9.8
200
+ * @access public
201
+ * @author Grégory Viguier
202
+ *
203
+ * @param array $sizes A list of sizes to remove.
204
+ */
205
+ public function delete_sizes_optimization_data( array $sizes ) {
206
+ if ( ! $sizes || ! $this->is_valid() ) {
207
+ return;
208
+ }
209
+
210
+ $data = array_merge( $this->get_reset_data(), $this->get_row() );
211
+
212
+ $data['data']['sizes'] = ! empty( $data['data']['sizes'] ) && is_array( $data['data']['sizes'] ) ? $data['data']['sizes'] : [];
213
+
214
+ if ( ! $data['data']['sizes'] ) {
215
+ return;
216
+ }
217
+
218
+ $remaining_sizes_data = array_diff_key( $data['data']['sizes'], array_flip( $sizes ) );
219
+
220
+ if ( ! $remaining_sizes_data ) {
221
+ // All sizes have been removed: delete everything.
222
+ $this->delete_optimization_data();
223
+ return;
224
+ }
225
+
226
+ if ( count( $remaining_sizes_data ) === count( $data['data']['sizes'] ) ) {
227
+ // Nothing has been removed.
228
+ return;
229
+ }
230
+
231
+ $data['data']['sizes'] = $remaining_sizes_data;
232
+
233
+ $this->update_row( $data );
234
+ }
235
+
236
  /**
237
  * Get default values used to reset optimization data.
238
  *
inc/3rd-party/nextgen-gallery/inc/common/attachments.php CHANGED
@@ -164,7 +164,7 @@ function _imagify_ngg_media_library_imported_image_data( $image, $attachment ) {
164
  $wp_webp_data = $wp_data->get_size_data( $webp_size_name );
165
 
166
  // Get the path to the webp image if it exists.
167
- $wp_full_path_webp = $wp_process->get_file()->get_path_to_webp();
168
 
169
  if ( $wp_full_path_webp && ! $filesystem->exists( $wp_full_path_webp ) ) {
170
  $wp_full_path_webp = false;
@@ -202,7 +202,7 @@ function _imagify_ngg_media_library_imported_image_data( $image, $attachment ) {
202
  if ( $wp_full_path_webp && $wp_webp_data ) {
203
  // We have the file and the data.
204
  // Copy the file.
205
- $ngg_full_file = new File( $ngg_media->get_raw_original_path() );
206
  $ngg_full_path_webp = $ngg_full_file->get_path_to_webp(); // Destination.
207
 
208
  if ( $ngg_full_path_webp ) {
164
  $wp_webp_data = $wp_data->get_size_data( $webp_size_name );
165
 
166
  // Get the path to the webp image if it exists.
167
+ $wp_full_path_webp = $wp_process->get_fullsize_file()->get_path_to_webp();
168
 
169
  if ( $wp_full_path_webp && ! $filesystem->exists( $wp_full_path_webp ) ) {
170
  $wp_full_path_webp = false;
202
  if ( $wp_full_path_webp && $wp_webp_data ) {
203
  // We have the file and the data.
204
  // Copy the file.
205
+ $ngg_full_file = new File( $ngg_media->get_raw_fullsize_path() );
206
  $ngg_full_path_webp = $ngg_full_file->get_path_to_webp(); // Destination.
207
 
208
  if ( $ngg_full_path_webp ) {
inc/3rd-party/regenerate-thumbnails/classes/Main.php CHANGED
@@ -40,6 +40,16 @@ class Main extends \Imagify_Regenerate_Thumbnails_Deprecated {
40
  */
41
  protected $processes = [];
42
 
 
 
 
 
 
 
 
 
 
 
43
 
44
  /** ----------------------------------------------------------------------------------------- */
45
  /** INIT ==================================================================================== */
@@ -58,7 +68,6 @@ class Main extends \Imagify_Regenerate_Thumbnails_Deprecated {
58
  }
59
 
60
  add_filter( 'rest_dispatch_request', [ $this, 'maybe_init_attachment' ], 4, 4 );
61
- add_filter( 'wp_generate_attachment_metadata', [ $this, 'launch_async_optimization' ], IMAGIFY_INT_MAX - 30, 2 );
62
  add_action( 'imagify_after_' . static::HOOK_SUFFIX, [ $this, 'after_regenerate_thumbnails' ], 8, 2 );
63
  }
64
 
@@ -91,10 +100,14 @@ class Main extends \Imagify_Regenerate_Thumbnails_Deprecated {
91
  return $dispatch_result;
92
  }
93
 
 
 
94
  // The attachment can be regenerated: keep the optimized full-sized file safe, and replace it by the backup file.
95
  $this->backup_optimized_file( $media_id );
96
  // Prevent automatic optimization.
97
  \Imagify_Auto_Optimization::prevent_optimization( $media_id );
 
 
98
 
99
  return $dispatch_result;
100
  }
@@ -106,32 +119,69 @@ class Main extends \Imagify_Regenerate_Thumbnails_Deprecated {
106
  * @access public
107
  * @author Grégory Viguier
108
  *
109
- * @param array $metadata An array of attachment meta data.
110
  * @param int $media_id Current media ID.
111
  * @return array
112
  */
113
  public function launch_async_optimization( $metadata, $media_id ) {
114
- if ( ! $this->get_process( $media_id ) ) {
 
 
115
  return $metadata;
116
  }
117
 
118
- $sizes = isset( $metadata['sizes'] ) && is_array( $metadata['sizes'] ) ? $metadata['sizes'] : [];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
 
120
  if ( ! $sizes ) {
121
  // Put the optimized full-sized file back.
122
  $this->put_optimized_file_back( $media_id );
123
- // Allow auto-optimization back.
124
- \Imagify_Auto_Optimization::allow_optimization( $media_id );
125
-
126
  return $metadata;
127
  }
128
 
129
- // Optimize the sizes that have been regenerated.
130
- $process = $this->get_process( $media_id );
131
- $level = $process->get_data()->get_optimization_level();
132
- $args = [ 'hook_suffix' => static::HOOK_SUFFIX ];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
 
134
- $process->optimize_sizes( array_keys( $sizes ), $level, $args );
 
 
 
 
135
 
136
  return $metadata;
137
  }
@@ -224,7 +274,25 @@ class Main extends \Imagify_Regenerate_Thumbnails_Deprecated {
224
  * @param int $media_id Media ID.
225
  */
226
  protected function backup_optimized_file( $media_id ) {
227
- $media = $this->get_process( $media_id )->get_media();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
  $backup_path = $media->get_backup_path();
229
 
230
  if ( ! $backup_path ) {
@@ -236,15 +304,14 @@ class Main extends \Imagify_Regenerate_Thumbnails_Deprecated {
236
  * Replace the optimized full-sized file by the backup, so any optimization will not use an optimized file, but the original one.
237
  * The optimized full-sized file is kept and renamed, and will be put back in place at the end of the optimization process.
238
  */
239
- $filesystem = \Imagify_Filesystem::get_instance();
240
- $file_path = $media->get_raw_original_path();
241
- $tmp_file_path = static::get_temporary_file_path( $file_path );
242
 
243
- if ( $filesystem->exists( $file_path ) ) {
244
- $moved = $filesystem->move( $file_path, $tmp_file_path, true );
 
245
  }
246
 
247
- $copied = $filesystem->copy( $backup_path, $file_path );
248
  }
249
 
250
  /**
@@ -258,7 +325,7 @@ class Main extends \Imagify_Regenerate_Thumbnails_Deprecated {
258
  * @param int $media_id Media ID.
259
  */
260
  protected function put_optimized_file_back( $media_id ) {
261
- $file_path = $this->get_process( $media_id )->get_media()->get_raw_original_path();
262
  $tmp_file_path = static::get_temporary_file_path( $file_path );
263
  $filesystem = \Imagify_Filesystem::get_instance();
264
 
@@ -267,6 +334,25 @@ class Main extends \Imagify_Regenerate_Thumbnails_Deprecated {
267
  }
268
  }
269
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
270
 
271
  /** ----------------------------------------------------------------------------------------- */
272
  /** PUBLIC TOOLS ============================================================================ */
40
  */
41
  protected $processes = [];
42
 
43
+ /**
44
+ * Tell if we’re playing in WP 5.3’s garden.
45
+ *
46
+ * @var bool
47
+ * @since 1.9.8
48
+ * @access protected
49
+ * @author Grégory Viguier
50
+ */
51
+ protected $is_wp53;
52
+
53
 
54
  /** ----------------------------------------------------------------------------------------- */
55
  /** INIT ==================================================================================== */
68
  }
69
 
70
  add_filter( 'rest_dispatch_request', [ $this, 'maybe_init_attachment' ], 4, 4 );
 
71
  add_action( 'imagify_after_' . static::HOOK_SUFFIX, [ $this, 'after_regenerate_thumbnails' ], 8, 2 );
72
  }
73
 
100
  return $dispatch_result;
101
  }
102
 
103
+ $media_id = $this->get_process( $media_id )->get_media()->get_id();
104
+
105
  // The attachment can be regenerated: keep the optimized full-sized file safe, and replace it by the backup file.
106
  $this->backup_optimized_file( $media_id );
107
  // Prevent automatic optimization.
108
  \Imagify_Auto_Optimization::prevent_optimization( $media_id );
109
+ // Launch the needed hook.
110
+ add_filter( 'wp_generate_attachment_metadata', [ $this, 'launch_async_optimization' ], IMAGIFY_INT_MAX - 30, 2 );
111
 
112
  return $dispatch_result;
113
  }
119
  * @access public
120
  * @author Grégory Viguier
121
  *
122
+ * @param array $metadata An array of attachment meta data, containing the sizes that have been regenerated.
123
  * @param int $media_id Current media ID.
124
  * @return array
125
  */
126
  public function launch_async_optimization( $metadata, $media_id ) {
127
+ $process = $this->get_process( $media_id );
128
+
129
+ if ( ! $process ) {
130
  return $metadata;
131
  }
132
 
133
+ $sizes = isset( $metadata['sizes'] ) && is_array( $metadata['sizes'] ) ? $metadata['sizes'] : [];
134
+ $media = $process->get_media();
135
+ $fullsize_path = $media->get_raw_fullsize_path();
136
+
137
+ if ( $fullsize_path ) {
138
+ $original_path = $media->get_original_path();
139
+
140
+ if ( $original_path && $this->is_wp_53() && $original_path !== $fullsize_path ) {
141
+ /**
142
+ * The original file and the full-sized file are not the same:
143
+ * That means wp_generate_attachment_metadata() recreated the full-sized file, based on the original one.
144
+ * So it must be optimized again now.
145
+ */
146
+ $sizes['full'] = [];
147
+ }
148
+ }
149
 
150
  if ( ! $sizes ) {
151
  // Put the optimized full-sized file back.
152
  $this->put_optimized_file_back( $media_id );
 
 
 
153
  return $metadata;
154
  }
155
 
156
+ /**
157
+ * Optimize the sizes that have been regenerated.
158
+ */
159
+ // If the media has webp versions, recreate them for the sizes that have been regenerated.
160
+ $data = $process->get_data();
161
+ $optimization_data = $data->get_optimization_data();
162
+
163
+ if ( ! empty( $optimization_data['sizes'] ) ) {
164
+ foreach ( $optimization_data['sizes'] as $size_name => $size_data ) {
165
+ $non_webp_size_name = $process->is_size_webp( $size_name );
166
+
167
+ if ( ! $non_webp_size_name || ! isset( $sizes[ $non_webp_size_name ] ) ) {
168
+ continue;
169
+ }
170
+
171
+ // Add the webp size.
172
+ $sizes[ $size_name ] = [];
173
+ }
174
+ }
175
+
176
+ $sizes = array_keys( $sizes );
177
+ $optimization_level = $data->get_optimization_level();
178
+ $optimization_args = [ 'hook_suffix' => static::HOOK_SUFFIX ];
179
 
180
+ // Delete related optimization data or nothing will be optimized.
181
+ $data->delete_sizes_optimization_data( $sizes );
182
+ $process->optimize_sizes( $sizes, $optimization_level, $optimization_args );
183
+
184
+ $this->unset_process( $media_id );
185
 
186
  return $metadata;
187
  }
274
  * @param int $media_id Media ID.
275
  */
276
  protected function backup_optimized_file( $media_id ) {
277
+ $media = $this->get_process( $media_id )->get_media();
278
+ $fullsize_path = $media->get_raw_fullsize_path();
279
+
280
+ if ( ! $fullsize_path ) {
281
+ // Uh?
282
+ return;
283
+ }
284
+
285
+ $original_path = $media->get_original_path();
286
+
287
+ if ( $original_path && $this->is_wp_53() && $original_path !== $fullsize_path ) {
288
+ /**
289
+ * The original file and the full-sized file are not the same:
290
+ * That means wp_generate_attachment_metadata() will recreate the full-sized file, based on the original one.
291
+ * Then, the thumbnails will be created from a newly created (unoptimized) file.
292
+ */
293
+ return;
294
+ }
295
+
296
  $backup_path = $media->get_backup_path();
297
 
298
  if ( ! $backup_path ) {
304
  * Replace the optimized full-sized file by the backup, so any optimization will not use an optimized file, but the original one.
305
  * The optimized full-sized file is kept and renamed, and will be put back in place at the end of the optimization process.
306
  */
307
+ $filesystem = \Imagify_Filesystem::get_instance();
 
 
308
 
309
+ if ( $filesystem->exists( $fullsize_path ) ) {
310
+ $tmp_file_path = static::get_temporary_file_path( $fullsize_path );
311
+ $moved = $filesystem->move( $fullsize_path, $tmp_file_path, true );
312
  }
313
 
314
+ $filesystem->copy( $backup_path, $fullsize_path );
315
  }
316
 
317
  /**
325
  * @param int $media_id Media ID.
326
  */
327
  protected function put_optimized_file_back( $media_id ) {
328
+ $file_path = $this->get_process( $media_id )->get_media()->get_raw_fullsize_path();
329
  $tmp_file_path = static::get_temporary_file_path( $file_path );
330
  $filesystem = \Imagify_Filesystem::get_instance();
331
 
334
  }
335
  }
336
 
337
+ /**
338
+ * Tell if we’re playing in WP 5.3’s garden.
339
+ *
340
+ * @since 1.9.8
341
+ * @access protected
342
+ * @author Grégory Viguier
343
+ *
344
+ * @return bool
345
+ */
346
+ protected function is_wp_53() {
347
+ if ( isset( $this->is_wp53 ) ) {
348
+ return $this->is_wp53;
349
+ }
350
+
351
+ $this->is_wp53 = function_exists( 'wp_get_original_image_path' );
352
+
353
+ return $this->is_wp53;
354
+ }
355
+
356
 
357
  /** ----------------------------------------------------------------------------------------- */
358
  /** PUBLIC TOOLS ============================================================================ */
inc/3rd-party/wp-rocket/classes/Main.php CHANGED
@@ -68,7 +68,7 @@ class Main {
68
  * @return array
69
  */
70
  public function set_cdn_source( $source ) {
71
- if ( ! function_exists( 'get_rocket_cdn_cnames' ) || ! function_exists( 'get_rocket_option' ) ) {
72
  return $source;
73
  }
74
 
@@ -76,9 +76,21 @@ class Main {
76
  return $source;
77
  }
78
 
79
- $url = get_rocket_cdn_cnames( [ 'all', 'images' ] );
80
 
81
- if ( ! $url ) {
 
 
 
 
 
 
 
 
 
 
 
 
82
  return $source;
83
  }
84
 
68
  * @return array
69
  */
70
  public function set_cdn_source( $source ) {
71
+ if ( ! function_exists( 'get_rocket_option' ) ) {
72
  return $source;
73
  }
74
 
76
  return $source;
77
  }
78
 
79
+ $container = apply_filters( 'rocket_container', null );
80
 
81
+ if ( is_object( $container ) && method_exists( $container, 'get' ) ) {
82
+ $cdn = $container->get( 'cdn' );
83
+
84
+ if ( $cdn && method_exists( $cdn, 'get_cdn_urls' ) ) {
85
+ $url = $cdn->get_cdn_urls( [ 'all', 'images' ] );
86
+ }
87
+ }
88
+
89
+ if ( ! isset( $url ) && function_exists( 'get_rocket_cdn_cnames' ) ) {
90
+ $url = get_rocket_cdn_cnames( [ 'all', 'images' ] );
91
+ }
92
+
93
+ if ( empty( $url ) ) {
94
  return $source;
95
  }
96
 
inc/admin/media.php CHANGED
@@ -88,7 +88,7 @@ function _imagify_add_actions_to_media_list_row( $actions, $post ) {
88
  $actions['imagify-compare'] = Imagify_Views::get_instance()->get_template( 'button/compare-images', [
89
  'url' => get_edit_post_link( $media->get_id() ) . '#imagify-compare',
90
  'backup_url' => $media->get_backup_url(),
91
- 'original_url' => $media->get_original_url(),
92
  'media_id' => $media->get_id(),
93
  'width' => $dimensions['width'],
94
  'height' => $dimensions['height'],
88
  $actions['imagify-compare'] = Imagify_Views::get_instance()->get_template( 'button/compare-images', [
89
  'url' => get_edit_post_link( $media->get_id() ) . '#imagify-compare',
90
  'backup_url' => $media->get_backup_url(),
91
+ 'original_url' => $media->get_fullsize_url(),
92
  'media_id' => $media->get_id(),
93
  'width' => $dimensions['width'],
94
  'height' => $dimensions['height'],
inc/classes/class-imagify-auto-optimization.php CHANGED
@@ -10,15 +10,7 @@ defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
10
  * @author Grégory Viguier
11
  */
12
  class Imagify_Auto_Optimization {
13
-
14
- /**
15
- * Class version.
16
- *
17
- * @var string
18
- * @since 1.8.4
19
- * @author Grégory Viguier
20
- */
21
- const VERSION = '1.1';
22
 
23
  /**
24
  * An array containing the IDs (as keys) of attachments just being uploaded.
@@ -42,14 +34,14 @@ class Imagify_Auto_Optimization {
42
  protected $attachments = [];
43
 
44
  /**
45
- * The single instance of the class.
46
  *
47
- * @var object
48
- * @since 1.8.4
49
  * @access protected
50
  * @author Grégory Viguier
51
  */
52
- protected static $instance;
53
 
54
  /**
55
  * Used to prevent an auto-optimization locally.
@@ -62,31 +54,14 @@ class Imagify_Auto_Optimization {
62
  private static $prevented = [];
63
 
64
  /**
65
- * Get the main Instance.
66
- * Ensures only one instance of class is loaded or can be loaded.
67
  *
68
- * @since 1.8.4
69
- * @access public
70
- * @author Grégory Viguier
71
- *
72
- * @return object Main instance.
73
- */
74
- public static function get_instance() {
75
- if ( ! isset( self::$instance ) ) {
76
- self::$instance = new self();
77
- }
78
-
79
- return self::$instance;
80
- }
81
-
82
- /**
83
- * The class constructor.
84
- *
85
- * @since 1.8.4
86
- * @access protected
87
  * @author Grégory Viguier
88
  */
89
- protected function __construct() {}
90
 
91
  /**
92
  * Init.
@@ -96,15 +71,25 @@ class Imagify_Auto_Optimization {
96
  * @author Grégory Viguier
97
  */
98
  public function init() {
 
99
  $prio = IMAGIFY_INT_MAX - 30;
100
 
101
  // Automatic optimization tunel.
102
  add_action( 'add_attachment', [ $this, 'store_upload_ids' ], $prio );
103
  add_filter( 'wp_update_attachment_metadata', [ $this, 'store_ids_to_optimize' ], $prio, 2 );
104
- add_action( 'updated_post_meta', [ $this, 'do_auto_optimization' ], $prio, 4 );
105
- add_action( 'added_post_meta', [ $this, 'do_auto_optimization' ], $prio, 4 );
106
  add_action( 'deleted_post_meta', [ $this, 'unset_optimization' ], $prio, 3 );
107
 
 
 
 
 
 
 
 
 
 
108
  // Prevent to re-optimize when updating the image width and height (when resizing the full image).
109
  add_action( 'imagify_before_update_wp_media_data_dimensions', [ __CLASS__, 'prevent_optimization' ], 5 );
110
  add_action( 'imagify_after_update_wp_media_data_dimensions', [ __CLASS__, 'allow_optimization' ], 5 );
@@ -120,11 +105,23 @@ class Imagify_Auto_Optimization {
120
  public function remove_hooks() {
121
  $prio = IMAGIFY_INT_MAX - 30;
122
 
 
123
  remove_action( 'add_attachment', [ $this, 'store_upload_ids' ], $prio );
124
  remove_filter( 'wp_update_attachment_metadata', [ $this, 'store_ids_to_optimize' ], $prio );
125
- remove_action( 'updated_post_meta', [ $this, 'do_auto_optimization' ], $prio );
126
- remove_action( 'added_post_meta', [ $this, 'do_auto_optimization' ], $prio );
127
  remove_action( 'deleted_post_meta', [ $this, 'unset_optimization' ], $prio );
 
 
 
 
 
 
 
 
 
 
 
128
  remove_action( 'imagify_before_update_wp_media_data_dimensions', [ __CLASS__, 'prevent_optimization' ], 5 );
129
  remove_action( 'imagify_after_update_wp_media_data_dimensions', [ __CLASS__, 'allow_optimization' ], 5 );
130
  }
@@ -270,13 +267,25 @@ class Imagify_Auto_Optimization {
270
  // Ready for the next step.
271
  $this->attachments[ $attachment_id ] = $is_new_upload;
272
 
 
 
 
 
 
 
 
 
 
 
 
273
  return $metadata;
274
  }
275
 
276
  /**
277
  * Launch auto optimization immediately after the post meta '_wp_attachment_metadata' is added or updated.
278
  *
279
- * @since 1.8.4
 
280
  * @access public
281
  * @author Grégory Viguier
282
  *
@@ -285,8 +294,12 @@ class Imagify_Auto_Optimization {
285
  * @param string $meta_key Meta key.
286
  * @param mixed $metadata Meta value.
287
  */
288
- public function do_auto_optimization( $meta_id, $attachment_id, $meta_key, $metadata ) {
289
- if ( '_wp_attachment_metadata' !== $meta_key || ! isset( $this->attachments[ $attachment_id ] ) ) {
 
 
 
 
290
  return;
291
  }
292
 
@@ -297,6 +310,21 @@ class Imagify_Auto_Optimization {
297
  $is_new_upload = $this->attachments[ $attachment_id ];
298
  unset( $this->attachments[ $attachment_id ] );
299
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
300
  $process = imagify_get_optimization_process( $attachment_id, 'wp' );
301
 
302
  /**
@@ -392,6 +420,144 @@ class Imagify_Auto_Optimization {
392
  }
393
 
394
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
395
  /** ----------------------------------------------------------------------------------------- */
396
  /** TOOLS =================================================================================== */
397
  /** ----------------------------------------------------------------------------------------- */
@@ -404,13 +570,18 @@ class Imagify_Auto_Optimization {
404
  * Imagify_Auto_Optimization::allow_optimization( $attachment_id );
405
  *
406
  * @since 1.8.4
 
407
  * @access public
408
  * @author Grégory Viguier
409
  *
410
  * @param int $attachment_id Current attachment ID.
411
  */
412
  public static function prevent_optimization( $attachment_id ) {
413
- self::$prevented[ $attachment_id ] = 1;
 
 
 
 
414
  }
415
 
416
  /**
@@ -421,13 +592,21 @@ class Imagify_Auto_Optimization {
421
  * Imagify_Auto_Optimization::allow_optimization( $attachment_id );
422
  *
423
  * @since 1.8.4
 
424
  * @access public
425
  * @author Grégory Viguier
426
  *
427
  * @param int $attachment_id Current attachment ID.
428
  */
429
  public static function allow_optimization( $attachment_id ) {
430
- unset( self::$prevented[ $attachment_id ] );
 
 
 
 
 
 
 
431
  }
432
 
433
  /**
@@ -441,6 +620,32 @@ class Imagify_Auto_Optimization {
441
  * @return bool
442
  */
443
  public static function is_optimization_prevented( $attachment_id ) {
444
- return ! empty( self::$prevented[ $attachment_id ] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
445
  }
446
  }
10
  * @author Grégory Viguier
11
  */
12
  class Imagify_Auto_Optimization {
13
+ use \Imagify\Traits\InstanceGetterTrait;
 
 
 
 
 
 
 
 
14
 
15
  /**
16
  * An array containing the IDs (as keys) of attachments just being uploaded.
34
  protected $attachments = [];
35
 
36
  /**
37
+ * The ID of the attachment that failed to be uploaded.
38
  *
39
+ * @var int
40
+ * @since 1.9.8
41
  * @access protected
42
  * @author Grégory Viguier
43
  */
44
+ protected $upload_failure_id = 0;
45
 
46
  /**
47
  * Used to prevent an auto-optimization locally.
54
  private static $prevented = [];
55
 
56
  /**
57
+ * Used to prevent an auto-optimization internally.
 
58
  *
59
+ * @var array
60
+ * @since 1.9.8
61
+ * @access private
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  * @author Grégory Viguier
63
  */
64
+ private static $prevented_internally = [];
65
 
66
  /**
67
  * Init.
71
  * @author Grégory Viguier
72
  */
73
  public function init() {
74
+ global $wp_version;
75
  $prio = IMAGIFY_INT_MAX - 30;
76
 
77
  // Automatic optimization tunel.
78
  add_action( 'add_attachment', [ $this, 'store_upload_ids' ], $prio );
79
  add_filter( 'wp_update_attachment_metadata', [ $this, 'store_ids_to_optimize' ], $prio, 2 );
80
+ add_action( 'updated_post_meta', [ $this, 'do_auto_optimization_after_meta_update' ], $prio, 4 );
81
+ add_action( 'added_post_meta', [ $this, 'do_auto_optimization_after_meta_update' ], $prio, 4 );
82
  add_action( 'deleted_post_meta', [ $this, 'unset_optimization' ], $prio, 3 );
83
 
84
+ if ( version_compare( $wp_version, '5.3-alpha1' ) >= 0 ) {
85
+ // WP 5.3+.
86
+ add_filter( 'big_image_size_threshold', [ $this, 'prevent_auto_optimization_when_generating_thumbnails' ], $prio, 4 );
87
+ add_filter( 'wp_generate_attachment_metadata', [ $this, 'allow_auto_optimization_when_generating_thumbnails' ], $prio, 3 );
88
+ add_action( 'imagify_after_auto_optimization_init', [ $this, 'do_auto_optimization' ], $prio, 2 );
89
+ // Upload failure recovering.
90
+ add_action( 'wp_ajax_media-create-image-subsizes', [ $this, 'prevent_auto_optimization_when_recovering_from_upload_failure' ], -5 ); // Before WP’s hook (priority 1).
91
+ }
92
+
93
  // Prevent to re-optimize when updating the image width and height (when resizing the full image).
94
  add_action( 'imagify_before_update_wp_media_data_dimensions', [ __CLASS__, 'prevent_optimization' ], 5 );
95
  add_action( 'imagify_after_update_wp_media_data_dimensions', [ __CLASS__, 'allow_optimization' ], 5 );
105
  public function remove_hooks() {
106
  $prio = IMAGIFY_INT_MAX - 30;
107
 
108
+ // Automatic optimization tunel.
109
  remove_action( 'add_attachment', [ $this, 'store_upload_ids' ], $prio );
110
  remove_filter( 'wp_update_attachment_metadata', [ $this, 'store_ids_to_optimize' ], $prio );
111
+ remove_action( 'updated_post_meta', [ $this, 'do_auto_optimization_after_meta_update' ], $prio );
112
+ remove_action( 'added_post_meta', [ $this, 'do_auto_optimization_after_meta_update' ], $prio );
113
  remove_action( 'deleted_post_meta', [ $this, 'unset_optimization' ], $prio );
114
+
115
+ if ( version_compare( $wp_version, '5.3-alpha1' ) >= 0 ) {
116
+ // WP 5.3+.
117
+ remove_filter( 'big_image_size_threshold', [ $this, 'prevent_auto_optimization_when_generating_thumbnails' ], $prio );
118
+ remove_filter( 'wp_generate_attachment_metadata', [ $this, 'allow_auto_optimization_when_generating_thumbnails' ], $prio );
119
+ remove_action( 'imagify_after_auto_optimization_init', [ $this, 'do_auto_optimization' ], $prio );
120
+ // Upload failure handling.
121
+ remove_action( 'wp_ajax_media_create_image_subsizes', [ $this, 'prevent_auto_optimization_when_recovering_from_upload_failure' ], -5 );
122
+ }
123
+
124
+ // Prevent to re-optimize when updating the image width and height (when resizing the full image).
125
  remove_action( 'imagify_before_update_wp_media_data_dimensions', [ __CLASS__, 'prevent_optimization' ], 5 );
126
  remove_action( 'imagify_after_update_wp_media_data_dimensions', [ __CLASS__, 'allow_optimization' ], 5 );
127
  }
267
  // Ready for the next step.
268
  $this->attachments[ $attachment_id ] = $is_new_upload;
269
 
270
+ /**
271
+ * Triggered after a media auto-optimization init.
272
+ *
273
+ * @since 1.9.8
274
+ * @author Grégory Viguier
275
+ *
276
+ * @param int $attachment_id The media ID.
277
+ * @param bool $is_new_upload True if it's a new upload. False otherwize.
278
+ */
279
+ do_action( 'imagify_after_auto_optimization_init', $attachment_id, $is_new_upload );
280
+
281
  return $metadata;
282
  }
283
 
284
  /**
285
  * Launch auto optimization immediately after the post meta '_wp_attachment_metadata' is added or updated.
286
  *
287
+ * @since 1.9
288
+ * @since 1.9 Previously named do_auto_optimization().
289
  * @access public
290
  * @author Grégory Viguier
291
  *
294
  * @param string $meta_key Meta key.
295
  * @param mixed $metadata Meta value.
296
  */
297
+ public function do_auto_optimization_after_meta_update( $meta_id, $attachment_id, $meta_key, $metadata ) {
298
+ if ( '_wp_attachment_metadata' !== $meta_key ) {
299
+ return;
300
+ }
301
+
302
+ if ( ! isset( $this->attachments[ $attachment_id ] ) ) {
303
  return;
304
  }
305
 
310
  $is_new_upload = $this->attachments[ $attachment_id ];
311
  unset( $this->attachments[ $attachment_id ] );
312
 
313
+ $this->do_auto_optimization( $attachment_id, $is_new_upload );
314
+ }
315
+
316
+ /**
317
+ * Launch auto optimization immediately after the post meta '_wp_attachment_metadata' is added or updated.
318
+ *
319
+ * @since 1.8.4
320
+ * @since 1.9.8 Changed signature.
321
+ * @access public
322
+ * @author Grégory Viguier
323
+ *
324
+ * @param int $attachment_id The media ID.
325
+ * @param bool $is_new_upload True if it's a new upload. False otherwize.
326
+ */
327
+ public function do_auto_optimization( $attachment_id, $is_new_upload ) {
328
  $process = imagify_get_optimization_process( $attachment_id, 'wp' );
329
 
330
  /**
420
  }
421
 
422
 
423
+ /** ----------------------------------------------------------------------------------------- */
424
+ /** WP 5.3+ HOOKS =========================================================================== */
425
+ /** ----------------------------------------------------------------------------------------- */
426
+
427
+ /**
428
+ * With WP 5.3+, prevent auto-optimization inside wp_generate_attachment_metadata() because it triggers a wp_update_attachment_metadata() for each thumbnail size.
429
+ *
430
+ * @since 1.9.8
431
+ * @access public
432
+ * @see wp_generate_attachment_metadata()
433
+ * @see wp_create_image_subsizes()
434
+ * @author Grégory Viguier
435
+ *
436
+ * @param int $threshold The threshold value in pixels. Default 2560.
437
+ * @param array $imagesize Indexed array of the image width and height (in that order).
438
+ * @param string $file Full path to the uploaded image file.
439
+ * @param int $attachment_id Attachment post ID.
440
+ * @return int The threshold value in pixels.
441
+ */
442
+ public function prevent_auto_optimization_when_generating_thumbnails( $threshold, $imagesize, $file, $attachment_id ) {
443
+ static::prevent_optimization_internally( $attachment_id );
444
+ return $threshold;
445
+ }
446
+
447
+ /**
448
+ * With WP 5.3+, allow auto-optimization back after wp_generate_attachment_metadata().
449
+ *
450
+ * @since 1.9.8
451
+ * @access public
452
+ * @see $this->prevent_auto_optimization_when_generating_thumbnails()
453
+ * @author Grégory Viguier
454
+ *
455
+ * @param array $metadata An array of attachment meta data.
456
+ * @param int $attachment_id Current attachment ID.
457
+ * @param string $context Additional context. Can be 'create' when metadata was initially created for new attachment or 'update' when the metadata was updated.
458
+ * @return array An array of attachment meta data.
459
+ */
460
+ public function allow_auto_optimization_when_generating_thumbnails( $metadata, $attachment_id, $context = null ) {
461
+ if ( ! empty( $context ) && 'create' !== $context ) {
462
+ return $metadata;
463
+ }
464
+
465
+ // Fired from wp_generate_attachment_metadata(): $context is empty (WP < 5.3) or equal to 'create' (>P >= 5.3).
466
+ static::allow_optimization_internally( $attachment_id );
467
+ return $metadata;
468
+ }
469
+
470
+
471
+ /** ----------------------------------------------------------------------------------------- */
472
+ /** HOOKS FOR WP 5.3+’S UPLOAD FAILURE RECOVERING =========================================== */
473
+ /** ----------------------------------------------------------------------------------------- */
474
+
475
+ /**
476
+ * With WP 5.3+, prevent auto-optimization when WP tries to create thumbnails after an upload error, because it triggers wp_update_attachment_metadata() for each thumbnail size.
477
+ *
478
+ * @since 1.9.8
479
+ * @access public
480
+ * @see wp_ajax_media_create_image_subsizes()
481
+ * @see wp_update_image_subsizes()
482
+ * @author Grégory Viguier
483
+ */
484
+ public function prevent_auto_optimization_when_recovering_from_upload_failure() {
485
+ if ( ! check_ajax_referer( 'media-form', false, false ) ) {
486
+ return;
487
+ }
488
+
489
+ if ( ! current_user_can( 'upload_files' ) ) {
490
+ return;
491
+ }
492
+
493
+ if ( ! imagify_get_context( 'wp' )->current_user_can( 'auto-optimize' ) ) {
494
+ return;
495
+ }
496
+
497
+ $attachment_id = ! empty( $_POST['attachment_id'] ) ? (int) $_POST['attachment_id'] : 0;
498
+
499
+ if ( ! $attachment_id ) {
500
+ return;
501
+ }
502
+
503
+ if ( ! imagify_is_attachment_mime_type_supported( $attachment_id ) ) {
504
+ return;
505
+ }
506
+
507
+ $this->upload_failure_id = $attachment_id;
508
+
509
+ static::prevent_optimization_internally( $attachment_id );
510
+
511
+ // Auto-optimization will be done on shutdown.
512
+ ob_start( [ $this, 'maybe_do_auto_optimization_after_recovering_from_upload_failure' ] );
513
+ }
514
+
515
+ /**
516
+ * Maybe launch auto-optimization after recovering from an upload failure, when all thumbnails are created.
517
+ *
518
+ * @since 1.9.8
519
+ * @access public
520
+ * @see wp_ajax_media_create_image_subsizes()
521
+ * @author Grégory Viguier
522
+ *
523
+ * @param string $content Buffer’s content.
524
+ * @return string Buffer’s content.
525
+ */
526
+ public function maybe_do_auto_optimization_after_recovering_from_upload_failure( $content ) {
527
+ if ( empty( $content ) ) {
528
+ return $content;
529
+ }
530
+
531
+ if ( ! $this->upload_failure_id ) {
532
+ // Uh?
533
+ return $content;
534
+ }
535
+
536
+ if ( ! get_post( $this->upload_failure_id ) ) {
537
+ return $content;
538
+ }
539
+
540
+ $json = @json_decode( $content );
541
+
542
+ if ( empty( $json->success ) ) {
543
+ return $content;
544
+ }
545
+
546
+ $attachment_id = $this->upload_failure_id;
547
+ $metadata = wp_get_attachment_metadata( $attachment_id );
548
+
549
+ $this->upload_failure_id = 0;
550
+ $this->uploads[ $attachment_id ] = 1; // New upload.
551
+
552
+ static::allow_optimization_internally( $attachment_id );
553
+
554
+ // Launch the process.
555
+ $this->store_ids_to_optimize( $metadata, $attachment_id );
556
+
557
+ return $content;
558
+ }
559
+
560
+
561
  /** ----------------------------------------------------------------------------------------- */
562
  /** TOOLS =================================================================================== */
563
  /** ----------------------------------------------------------------------------------------- */
570
  * Imagify_Auto_Optimization::allow_optimization( $attachment_id );
571
  *
572
  * @since 1.8.4
573
+ * @since 1.9.8 Prevents/Allows can stack.
574
  * @access public
575
  * @author Grégory Viguier
576
  *
577
  * @param int $attachment_id Current attachment ID.
578
  */
579
  public static function prevent_optimization( $attachment_id ) {
580
+ if ( ! isset( self::$prevented[ $attachment_id ] ) ) {
581
+ self::$prevented[ $attachment_id ] = 1;
582
+ } else {
583
+ ++self::$prevented[ $attachment_id ];
584
+ }
585
  }
586
 
587
  /**
592
  * Imagify_Auto_Optimization::allow_optimization( $attachment_id );
593
  *
594
  * @since 1.8.4
595
+ * @since 1.9.8 Prevents/Allows can stack.
596
  * @access public
597
  * @author Grégory Viguier
598
  *
599
  * @param int $attachment_id Current attachment ID.
600
  */
601
  public static function allow_optimization( $attachment_id ) {
602
+ if ( ! isset( self::$prevented[ $attachment_id ] ) ) {
603
+ return;
604
+ }
605
+ --self::$prevented[ $attachment_id ];
606
+
607
+ if ( self::$prevented[ $attachment_id ] <= 0 ) {
608
+ unset( self::$prevented[ $attachment_id ] );
609
+ }
610
  }
611
 
612
  /**
620
  * @return bool
621
  */
622
  public static function is_optimization_prevented( $attachment_id ) {
623
+ return ! empty( self::$prevented[ $attachment_id ] ) || ! empty( self::$prevented_internally[ $attachment_id ] );
624
+ }
625
+
626
+ /**
627
+ * Prevent an auto-optimization internally.
628
+ *
629
+ * @since 1.9.8
630
+ * @access protected
631
+ * @author Grégory Viguier
632
+ *
633
+ * @param int $attachment_id Current attachment ID.
634
+ */
635
+ protected static function prevent_optimization_internally( $attachment_id ) {
636
+ self::$prevented_internally[ $attachment_id ] = 1;
637
+ }
638
+
639
+ /**
640
+ * Allow an auto-optimization internally.
641
+ *
642
+ * @since 1.9.8
643
+ * @access protected
644
+ * @author Grégory Viguier
645
+ *
646
+ * @param int $attachment_id Current attachment ID.
647
+ */
648
+ protected static function allow_optimization_internally( $attachment_id ) {
649
+ unset( self::$prevented_internally[ $attachment_id ] );
650
  }
651
  }
inc/classes/class-imagify-custom-folders.php CHANGED
@@ -194,7 +194,7 @@ class Imagify_Custom_Folders {
194
  }
195
 
196
  if ( ! $args['file_path'] && $args['file_id'] ) {
197
- $args['file_path'] = $process->get_media()->get_original_path();
198
  }
199
 
200
  if ( ! $args['backup_path'] && $args['file_path'] ) {
@@ -254,7 +254,7 @@ class Imagify_Custom_Folders {
254
 
255
  $filesystem = imagify_get_filesystem();
256
  $media = $process->get_media();
257
- $file_path = $media->get_original_path();
258
  $mime_type = $filesystem->get_mime_type( $file_path );
259
  $is_image = $mime_type && strpos( $mime_type, 'image/' ) === 0;
260
  $webp_path = $is_image ? imagify_path_to_webp( $file_path ) : false;
194
  }
195
 
196
  if ( ! $args['file_path'] && $args['file_id'] ) {
197
+ $args['file_path'] = $process->get_media()->get_fullsize_path();
198
  }
199
 
200
  if ( ! $args['backup_path'] && $args['file_path'] ) {
254
 
255
  $filesystem = imagify_get_filesystem();
256
  $media = $process->get_media();
257
+ $file_path = $media->get_fullsize_path();
258
  $mime_type = $filesystem->get_mime_type( $file_path );
259
  $is_image = $mime_type && strpos( $mime_type, 'image/' ) === 0;
260
  $webp_path = $is_image ? imagify_path_to_webp( $file_path ) : false;
inc/classes/class-imagify-db.php CHANGED
@@ -489,7 +489,7 @@ class Imagify_DB {
489
 
490
  // Sanitize the IDs.
491
  $media_ids = array_filter( $media_ids );
492
- $media_ids = array_unique( $media_ids, true );
493
 
494
  if ( ! $media_ids ) {
495
  return;
489
 
490
  // Sanitize the IDs.
491
  $media_ids = array_filter( $media_ids );
492
+ $media_ids = array_unique( $media_ids );
493
 
494
  if ( ! $media_ids ) {
495
  return;
inc/classes/class-imagify-files-list-table.php CHANGED
@@ -526,9 +526,9 @@ class Imagify_Files_List_Table extends WP_List_Table {
526
  public function column_title( $item ) {
527
  $item = $this->maybe_set_item_folder( $item );
528
  $media = $item->process->get_media();
529
- $url = $media->get_original_url();
530
  $base = ! empty( $item->folder_path ) ? Imagify_Files_Scan::remove_placeholder( $item->folder_path ) : '';
531
- $title = $this->filesystem->make_path_relative( $media->get_original_path(), $base );
532
 
533
  list( $mime ) = explode( '/', $media->get_mime_type() );
534
 
@@ -946,7 +946,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
946
  return;
947
  }
948
 
949
- $file_path = $media->get_original_path();
950
 
951
  if ( ! $file_path ) {
952
  return;
@@ -963,7 +963,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
963
  echo $this->views->get_template( 'button/compare-images', [
964
  'url' => $backup_url,
965
  'backup_url' => $backup_url,
966
- 'original_url' => $media->get_original_url(),
967
  'media_id' => $media->get_id(),
968
  'width' => $dimensions['width'],
969
  'height' => $dimensions['height'],
526
  public function column_title( $item ) {
527
  $item = $this->maybe_set_item_folder( $item );
528
  $media = $item->process->get_media();
529
+ $url = $media->get_fullsize_url();
530
  $base = ! empty( $item->folder_path ) ? Imagify_Files_Scan::remove_placeholder( $item->folder_path ) : '';
531
+ $title = $this->filesystem->make_path_relative( $media->get_fullsize_path(), $base );
532
 
533
  list( $mime ) = explode( '/', $media->get_mime_type() );
534
 
946
  return;
947
  }
948
 
949
+ $file_path = $media->get_fullsize_path();
950
 
951
  if ( ! $file_path ) {
952
  return;
963
  echo $this->views->get_template( 'button/compare-images', [
964
  'url' => $backup_url,
965
  'backup_url' => $backup_url,
966
+ 'original_url' => $media->get_fullsize_url(),
967
  'media_id' => $media->get_id(),
968
  'width' => $dimensions['width'],
969
  'height' => $dimensions['height'],
inc/classes/class-imagify-options.php CHANGED
@@ -90,6 +90,25 @@ class Imagify_Options extends Imagify_Abstract_Options {
90
  $this->default_values['api_key'] = (string) IMAGIFY_API_KEY;
91
  }
92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  $this->network_option = imagify_is_active_for_network();
94
 
95
  parent::__construct();
@@ -160,7 +179,7 @@ class Imagify_Options extends Imagify_Abstract_Options {
160
  case 'resize_larger_w':
161
  if ( $value <= 0 ) {
162
  // Invalid.
163
- return 0;
164
  }
165
  if ( ! isset( $max_sizes ) ) {
166
  $max_sizes = get_imagify_max_intermediate_image_size();
90
  $this->default_values['api_key'] = (string) IMAGIFY_API_KEY;
91
  }
92
 
93
+ if ( function_exists( 'wp_get_original_image_path' ) ) {
94
+ $this->reset_values['resize_larger'] = 1;
95
+
96
+ $filter_cb = [ imagify_get_context( 'wp' ), 'get_resizing_threshold' ];
97
+ $filtered = has_filter( 'big_image_size_threshold', $filter_cb );
98
+
99
+ if ( $filtered ) {
100
+ remove_filter( 'big_image_size_threshold', $filter_cb, IMAGIFY_INT_MAX );
101
+ }
102
+
103
+ /** This filter is documented in wp-admin/includes/image.php */
104
+ $this->reset_values['resize_larger_w'] = (int) apply_filters( 'big_image_size_threshold', 2560, [ 0, 0 ], '', 0 );
105
+ $this->reset_values['resize_larger_w'] = $this->sanitize_and_validate_value( 'resize_larger_w', $this->reset_values['resize_larger_w'], $this->default_values['resize_larger_w'] );
106
+
107
+ if ( $filtered ) {
108
+ add_filter( 'big_image_size_threshold', $filter_cb, IMAGIFY_INT_MAX );
109
+ }
110
+ }
111
+
112
  $this->network_option = imagify_is_active_for_network();
113
 
114
  parent::__construct();
179
  case 'resize_larger_w':
180
  if ( $value <= 0 ) {
181
  // Invalid.
182
+ return $default;
183
  }
184
  if ( ! isset( $max_sizes ) ) {
185
  $max_sizes = get_imagify_max_intermediate_image_size();
inc/classes/class-imagify-views.php CHANGED
@@ -160,7 +160,7 @@ class Imagify_Views {
160
  $wp_context = imagify_get_context( 'wp' );
161
 
162
  // Sub-menu item: bulk optimization.
163
- add_media_page( __( 'Bulk Optimization', 'imagify' ), __( 'Bulk Optimization', 'imagify' ), $wp_context->get_capacity( 'bulk-optimize' ), $this->get_bulk_page_slug(), array( $this, 'display_bulk_page' ) );
164
 
165
  if ( imagify_is_active_for_network() ) {
166
  return;
@@ -172,16 +172,16 @@ class Imagify_Views {
172
  if ( imagify_can_optimize_custom_folders() ) {
173
  // Sub-menu item: custom folders list.
174
  $cf_context = imagify_get_context( 'custom-folders' );
175
- $screen_id = add_media_page( __( 'Other Media optimized by Imagify', 'imagify' ), __( 'Other Media', 'imagify' ), $cf_context->current_user_can( 'optimize' ), $this->get_files_page_slug(), array( $this, 'display_files_list' ) );
176
 
177
  if ( $screen_id ) {
178
  // Load the data for this page.
179
- add_action( 'load-' . $screen_id, array( $this, 'load_files_list' ) );
180
  }
181
  }
182
 
183
  // Sub-menu item: settings.
184
- add_options_page( 'Imagify', 'Imagify', $wp_context->get_capacity( 'manage' ), $this->get_settings_page_slug(), array( $this, 'display_settings_page' ) );
185
  }
186
 
187
  /**
160
  $wp_context = imagify_get_context( 'wp' );
161
 
162
  // Sub-menu item: bulk optimization.
163
+ add_media_page( __( 'Bulk Optimization', 'imagify' ), __( 'Bulk Optimization', 'imagify' ), $wp_context->get_capacity( 'bulk-optimize' ), $this->get_bulk_page_slug(), [ $this, 'display_bulk_page' ] );
164
 
165
  if ( imagify_is_active_for_network() ) {
166
  return;
172
  if ( imagify_can_optimize_custom_folders() ) {
173
  // Sub-menu item: custom folders list.
174
  $cf_context = imagify_get_context( 'custom-folders' );
175
+ $screen_id = add_media_page( __( 'Other Media optimized by Imagify', 'imagify' ), __( 'Other Media', 'imagify' ), $cf_context->get_capacity( 'optimize' ), $this->get_files_page_slug(), [ $this, 'display_files_list' ] );
176
 
177
  if ( $screen_id ) {
178
  // Load the data for this page.
179
+ add_action( 'load-' . $screen_id, [ $this, 'load_files_list' ] );
180
  }
181
  }
182
 
183
  // Sub-menu item: settings.
184
+ add_options_page( 'Imagify', 'Imagify', $wp_context->get_capacity( 'manage' ), $this->get_settings_page_slug(), [ $this, 'display_settings_page' ] );
185
  }
186
 
187
  /**
inc/common/attachments.php CHANGED
@@ -58,3 +58,12 @@ function imagify_add_webp_type( $ext2type ) {
58
  }
59
  return $ext2type;
60
  }
 
 
 
 
 
 
 
 
 
58
  }
59
  return $ext2type;
60
  }
61
+
62
+ /**
63
+ * Set WP’s "big images threshold" to Imagify’s resizing value.
64
+ *
65
+ * @since 1.9.8
66
+ * @since WP 5.3
67
+ * @author Grégory Viguier
68
+ */
69
+ add_filter( 'big_image_size_threshold', [ imagify_get_context( 'wp' ), 'get_resizing_threshold' ], IMAGIFY_INT_MAX );
inc/deprecated/Traits/Media/CustomFoldersDeprecatedTrait.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Imagify\Deprecated\Traits\Media;
3
+
4
+ defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
5
+
6
+ /**
7
+ * Trait containing deprecated methods of the class \Imagify\Media\CustomFolders.
8
+ *
9
+ * @since 1.9.8
10
+ * @author Grégory Viguier
11
+ */
12
+ trait CustomFoldersDeprecatedTrait {
13
+
14
+ /**
15
+ * Get the original media's URL.
16
+ *
17
+ * @since 1.9
18
+ * @since 1.9.8 Deprecated
19
+ * @access public
20
+ * @author Grégory Viguier
21
+ * @deprecated
22
+ *
23
+ * @return string|bool The file URL. False on failure.
24
+ */
25
+ public function get_original_url() {
26
+ _deprecated_function( get_class( $this ) . '::' . __FUNCTION__ . '()', '1.9.8', '( new \Imagify\Media\CustomFolders( $id ) )->get_fullsize_url()' );
27
+
28
+ if ( ! $this->is_valid() ) {
29
+ return false;
30
+ }
31
+
32
+ if ( $this->get_cdn() ) {
33
+ return $this->get_cdn()->get_file_url();
34
+ }
35
+
36
+ $row = $this->get_row();
37
+
38
+ if ( ! $row || empty( $row['path'] ) ) {
39
+ return false;
40
+ }
41
+
42
+ return \Imagify_Files_Scan::remove_placeholder( $row['path'], 'url' );
43
+ }
44
+ }
inc/deprecated/Traits/Media/NGGDeprecatedTrait.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Imagify\Deprecated\Traits\Media;
3
+
4
+ defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
5
+
6
+ /**
7
+ * Trait containing deprecated methods of the class \Imagify\Media\NGG.
8
+ *
9
+ * @since
10
+ * @author Grégory Viguier
11
+ */
12
+ trait NGGDeprecatedTrait {
13
+
14
+ /**
15
+ * Get the original media's URL.
16
+ *
17
+ * @since 1.9
18
+ * @since Deprecated
19
+ * @access public
20
+ * @author Grégory Viguier
21
+ * @deprecated
22
+ *
23
+ * @return string|bool The file URL. False on failure.
24
+ */
25
+ public function get_original_url() {
26
+ _deprecated_function( get_class( $this ) . '::' . __FUNCTION__ . '()', '', '( new \Imagify\Media\NGG( $id ) )->get_fullsize_url()' );
27
+
28
+ if ( ! $this->is_valid() ) {
29
+ return false;
30
+ }
31
+
32
+ if ( $this->get_cdn() ) {
33
+ return $this->get_cdn()->get_file_url();
34
+ }
35
+
36
+ return ! empty( $this->image->imageURL ) ? $this->image->imageURL : false;
37
+ }
38
+ }
inc/deprecated/Traits/Media/NoopDeprecatedTrait.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Imagify\Deprecated\Traits\Media;
3
+
4
+ defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
5
+
6
+ /**
7
+ * Trait containing deprecated methods of the class \Imagify\Media\Noop.
8
+ *
9
+ * @since
10
+ * @author Grégory Viguier
11
+ */
12
+ trait NoopDeprecatedTrait {
13
+
14
+ /**
15
+ * Get the original media's URL.
16
+ *
17
+ * @since 1.9
18
+ * @since Deprecated
19
+ * @access public
20
+ * @author Grégory Viguier
21
+ * @deprecated
22
+ *
23
+ * @return string|bool The file URL. False on failure.
24
+ */
25
+ public function get_original_url() {
26
+ _deprecated_function( get_class( $this ) . '::' . __FUNCTION__ . '()', '', '( new \Imagify\Media\Noop( $id ) )->get_fullsize_url()' );
27
+
28
+ return false;
29
+ }
30
+ }
inc/deprecated/Traits/Media/WPDeprecatedTrait.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Imagify\Deprecated\Traits\Media;
3
+
4
+ defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
5
+
6
+ /**
7
+ * Trait containing deprecated methods of the class \Imagify\Media\WP.
8
+ *
9
+ * @since
10
+ * @author Grégory Viguier
11
+ */
12
+ trait WPDeprecatedTrait {
13
+
14
+ /**
15
+ * Get the original media's URL.
16
+ *
17
+ * @since 1.9
18
+ * @since Deprecated
19
+ * @access public
20
+ * @author Grégory Viguier
21
+ * @deprecated
22
+ *
23
+ * @return string|bool The file URL. False on failure.
24
+ */
25
+ public function get_original_url() {
26
+ _deprecated_function( get_class( $this ) . '::' . __FUNCTION__ . '()', '', '( new \Imagify\Media\WP( $id ) )->get_fullsize_url()' );
27
+
28
+ if ( ! $this->is_valid() ) {
29
+ return false;
30
+ }
31
+
32
+ if ( $this->get_cdn() ) {
33
+ return $this->get_cdn()->get_file_url();
34
+ }
35
+
36
+ $url = wp_get_attachment_url( $this->id );
37
+
38
+ return $url ? $url : false;
39
+ }
40
+ }
inc/deprecated/Traits/Optimization/Process/AbstractProcessDeprecatedTrait.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Imagify\Deprecated\Traits\Optimization\Process;
3
+
4
+ defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
5
+
6
+ /**
7
+ * Trait containing deprecated methods of the class \Imagify\Optimization\Process\AbstractProcess.
8
+ *
9
+ * @since
10
+ * @author Grégory Viguier
11
+ */
12
+ trait AbstractProcessDeprecatedTrait {
13
+
14
+ /**
15
+ * Get the File instance.
16
+ *
17
+ * @since 1.9
18
+ * @since Deprecated
19
+ * @access public
20
+ * @author Grégory Viguier
21
+ * @deprecated
22
+ *
23
+ * @return File|false
24
+ */
25
+ public function get_file() {
26
+ $full_class = get_class( $this );
27
+ $class_name = explode( '\\', trim( $full_class, '\\' ) );
28
+ $class_name = end( $class_name );
29
+
30
+ _deprecated_function( get_class( $this ) . '::' . __FUNCTION__ . '()', '', '( new \Imagify\Optimization\Process\\' . $class_name . '( $id ) )->get_fullsize_file()' );
31
+
32
+ if ( isset( $this->file ) ) {
33
+ return $this->file;
34
+ }
35
+
36
+ $this->file = false;
37
+
38
+ if ( $this->get_media() ) {
39
+ $this->file = new File( $this->get_media()->get_raw_fullsize_path() );
40
+ }
41
+
42
+ return $this->file;
43
+ }
44
+ }
inc/functions/admin-ui.php CHANGED
@@ -124,7 +124,7 @@ function get_imagify_attachment_optimization_text( $process ) {
124
  if ( ! $is_library_page ) {
125
  $output .= '<input id="imagify-original-src" type="hidden" value="' . esc_url( $media->get_backup_url() ) . '">';
126
  $output .= '<input id="imagify-original-size" type="hidden" value="' . $data->get_original_size() . '">';
127
- $output .= '<input id="imagify-full-src" type="hidden" value="' . esc_url( $media->get_original_url() ) . '">';
128
 
129
  if ( $media->is_image() ) {
130
  $dimensions = $media->get_dimensions();
124
  if ( ! $is_library_page ) {
125
  $output .= '<input id="imagify-original-src" type="hidden" value="' . esc_url( $media->get_backup_url() ) . '">';
126
  $output .= '<input id="imagify-original-size" type="hidden" value="' . $data->get_original_size() . '">';
127
+ $output .= '<input id="imagify-full-src" type="hidden" value="' . esc_url( $media->get_fullsize_url() ) . '">';
128
 
129
  if ( $media->is_image() ) {
130
  $dimensions = $media->get_dimensions();
inc/functions/i18n.php CHANGED
@@ -164,7 +164,7 @@ function get_imagify_localize_script_translations( $context ) {
164
  if ( $media->is_image() ) {
165
  $dimensions = $media->get_dimensions();
166
  $image = [
167
- 'src' => $media->get_original_url(),
168
  'width' => $dimensions['width'],
169
  'height' => $dimensions['height'],
170
  ];
164
  if ( $media->is_image() ) {
165
  $dimensions = $media->get_dimensions();
166
  $image = [
167
+ 'src' => $media->get_fullsize_url(),
168
  'width' => $dimensions['width'],
169
  'height' => $dimensions['height'],
170
  ];
package.json CHANGED
@@ -1,7 +1,7 @@
1
  {
2
  "name": "imagify",
3
  "description": "Imagify Image Optimizer. Dramatically reduce image file sizes without losing quality, make your website load faster, boost your SEO and save money on your bandwidth.",
4
- "version": "1.9.7",
5
  "homepage": "https://wordpress.org/plugins/imagify/",
6
  "license": "GPL-2.0",
7
  "private": true,
1
  {
2
  "name": "imagify",
3
  "description": "Imagify Image Optimizer. Dramatically reduce image file sizes without losing quality, make your website load faster, boost your SEO and save money on your bandwidth.",
4
+ "version": "1.9.8",
5
  "homepage": "https://wordpress.org/plugins/imagify/",
6
  "license": "GPL-2.0",
7
  "private": true,
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: wp_media, GregLone
3
  Tags: optimize images, images, optimize, performance, webp
4
  Requires at least: 4.0.0
5
- Tested up to: 5.2.2
6
- Stable tag: 1.9.7
7
 
8
  Optimize images in one click: reduce image file sizes, convert WebP, keep your images beautiful… and boost your loading time and your SEO!
9
 
@@ -153,6 +153,15 @@ When the plugin is disabled, your existing images remain optimized. Backups of t
153
  4. Other Media Page
154
 
155
  == Changelog ==
 
 
 
 
 
 
 
 
 
156
  = 1.9.7 - 2019/10/08 =
157
  * Improvement: prevent greedy antiviruses from crashing the website by renaming our highly dangerous php file with a ".suspected" suffix.
158
  * Improvement: on the settings page, display the "Save & Go to Bulk Optimizer" button only if the user has the ability to bulk optimize.
2
  Contributors: wp_media, GregLone
3
  Tags: optimize images, images, optimize, performance, webp
4
  Requires at least: 4.0.0
5
+ Tested up to: 5.3
6
+ Stable tag: 1.9.8
7
 
8
  Optimize images in one click: reduce image file sizes, convert WebP, keep your images beautiful… and boost your loading time and your SEO!
9
 
153
  4. Other Media Page
154
 
155
  == Changelog ==
156
+ = 1.9.8 - 2019/11/11 =
157
+ * Improvement: compatibility with WordPress 5.3!
158
+ * New: among other things, WordPress 5.3 automatically resizes large images on upload, using a predefined threshold value that can be changed only by filter (no setting fields are provided). Imagify’s "Resize larger images" setting field is now used to tweak this threshold.
159
+ * Caution: to be able to work on WordPress 5.3, some adjustments have been made to our compatibility with Enable Media Replace and Regenerate Thumbnails. However, these plugins must be updated to work with WordPress 5.3: do not use them until then.
160
+ * Improvement: moved the `width` and `height` attributes from the `<picture>` tag to the `<img>` tag to be valid HTML markup.
161
+ * Fix: added a missing descriptor in `srcset` attribute when using `<picture>` tags to display webp images. This should also fix an issue with LasyLoad.
162
+ * Fix: fixed an issue with the user capacity used for "Other Media" menu item.
163
+ * Fix: a php notice `stripos(): Non-string needles will be interpreted as strings in the future.`.
164
+
165
  = 1.9.7 - 2019/10/08 =
166
  * Improvement: prevent greedy antiviruses from crashing the website by renaming our highly dangerous php file with a ".suspected" suffix.
167
  * Improvement: on the settings page, display the "Save & Go to Bulk Optimizer" button only if the user has the ability to bulk optimize.
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
- return ComposerAutoloaderInit1b7d202ad01d839050ec4112544e7221::getLoader();
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit9a65f06d351d3ca28131bdc6dbd92154::getLoader();
vendor/composer/autoload_classmap.php CHANGED
@@ -111,6 +111,11 @@ return array(
111
  'Imagify\\Context\\Noop' => $baseDir . '/classes/Context/Noop.php',
112
  'Imagify\\Context\\WP' => $baseDir . '/classes/Context/WP.php',
113
  'Imagify\\DB\\DBInterface' => $baseDir . '/classes/DB/DBInterface.php',
 
 
 
 
 
114
  'Imagify\\Imagifybeat\\Actions' => $baseDir . '/classes/Imagifybeat/Actions.php',
115
  'Imagify\\Imagifybeat\\Core' => $baseDir . '/classes/Imagifybeat/Core.php',
116
  'Imagify\\Job\\MediaOptimization' => $baseDir . '/classes/Job/MediaOptimization.php',
111
  'Imagify\\Context\\Noop' => $baseDir . '/classes/Context/Noop.php',
112
  'Imagify\\Context\\WP' => $baseDir . '/classes/Context/WP.php',
113
  'Imagify\\DB\\DBInterface' => $baseDir . '/classes/DB/DBInterface.php',
114
+ 'Imagify\\Deprecated\\Traits\\Media\\CustomFoldersDeprecatedTrait' => $baseDir . '/inc/deprecated/Traits/Media/CustomFoldersDeprecatedTrait.php',
115
+ 'Imagify\\Deprecated\\Traits\\Media\\NGGDeprecatedTrait' => $baseDir . '/inc/deprecated/Traits/Media/NGGDeprecatedTrait.php',
116
+ 'Imagify\\Deprecated\\Traits\\Media\\NoopDeprecatedTrait' => $baseDir . '/inc/deprecated/Traits/Media/NoopDeprecatedTrait.php',
117
+ 'Imagify\\Deprecated\\Traits\\Media\\WPDeprecatedTrait' => $baseDir . '/inc/deprecated/Traits/Media/WPDeprecatedTrait.php',
118
+ 'Imagify\\Deprecated\\Traits\\Optimization\\Process\\AbstractProcessDeprecatedTrait' => $baseDir . '/inc/deprecated/Traits/Optimization/Process/AbstractProcessDeprecatedTrait.php',
119
  'Imagify\\Imagifybeat\\Actions' => $baseDir . '/classes/Imagifybeat/Actions.php',
120
  'Imagify\\Imagifybeat\\Core' => $baseDir . '/classes/Imagifybeat/Core.php',
121
  'Imagify\\Job\\MediaOptimization' => $baseDir . '/classes/Job/MediaOptimization.php',
vendor/composer/autoload_psr4.php CHANGED
@@ -12,6 +12,7 @@ return array(
12
  'Imagify\\ThirdParty\\FormidablePro\\' => array($baseDir . '/inc/3rd-party/formidable-pro/classes'),
13
  'Imagify\\ThirdParty\\EnableMediaReplace\\' => array($baseDir . '/inc/3rd-party/enable-media-replace/classes'),
14
  'Imagify\\ThirdParty\\AS3CF\\' => array($baseDir . '/inc/3rd-party/amazon-s3-and-cloudfront/classes'),
 
15
  'Imagify\\' => array($baseDir . '/classes'),
16
  'Dangoodman\\ComposerForWordpress\\' => array($vendorDir . '/dangoodman/composer-for-wordpress'),
17
  'Composer\\Installers\\' => array($vendorDir . '/composer/installers/src/Composer/Installers'),
12
  'Imagify\\ThirdParty\\FormidablePro\\' => array($baseDir . '/inc/3rd-party/formidable-pro/classes'),
13
  'Imagify\\ThirdParty\\EnableMediaReplace\\' => array($baseDir . '/inc/3rd-party/enable-media-replace/classes'),
14
  'Imagify\\ThirdParty\\AS3CF\\' => array($baseDir . '/inc/3rd-party/amazon-s3-and-cloudfront/classes'),
15
+ 'Imagify\\Deprecated\\Traits\\' => array($baseDir . '/inc/deprecated/Traits'),
16
  'Imagify\\' => array($baseDir . '/classes'),
17
  'Dangoodman\\ComposerForWordpress\\' => array($vendorDir . '/dangoodman/composer-for-wordpress'),
18
  'Composer\\Installers\\' => array($vendorDir . '/composer/installers/src/Composer/Installers'),
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInit1b7d202ad01d839050ec4112544e7221
6
  {
7
  private static $loader;
8
 
@@ -19,15 +19,15 @@ class ComposerAutoloaderInit1b7d202ad01d839050ec4112544e7221
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInit1b7d202ad01d839050ec4112544e7221', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\AutoloadWPMediaImagifyWordPressPlugin\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInit1b7d202ad01d839050ec4112544e7221', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
- call_user_func(\Composer\Autoload\ComposerStaticInit1b7d202ad01d839050ec4112544e7221::getInitializer($loader));
31
  } else {
32
  $classMap = require __DIR__ . '/autoload_classmap.php';
33
  if ($classMap) {
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInit9a65f06d351d3ca28131bdc6dbd92154
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInit9a65f06d351d3ca28131bdc6dbd92154', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\AutoloadWPMediaImagifyWordPressPlugin\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit9a65f06d351d3ca28131bdc6dbd92154', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
+ call_user_func(\Composer\Autoload\ComposerStaticInit9a65f06d351d3ca28131bdc6dbd92154::getInitializer($loader));
31
  } else {
32
  $classMap = require __DIR__ . '/autoload_classmap.php';
33
  if ($classMap) {
vendor/composer/autoload_static.php CHANGED
@@ -7,7 +7,7 @@ namespace Composer\Autoload;
7
  use Composer\AutoloadWPMediaImagifyWordPressPlugin\ClassLoader as ClassLoaderWPMediaImagifyWordPressPlugin;
8
 
9
 
10
- class ComposerStaticInit1b7d202ad01d839050ec4112544e7221
11
  {
12
  public static $prefixLengthsPsr4 = array (
13
  'I' =>
@@ -18,6 +18,7 @@ class ComposerStaticInit1b7d202ad01d839050ec4112544e7221
18
  'Imagify\\ThirdParty\\FormidablePro\\' => 33,
19
  'Imagify\\ThirdParty\\EnableMediaReplace\\' => 38,
20
  'Imagify\\ThirdParty\\AS3CF\\' => 25,
 
21
  'Imagify\\' => 8,
22
  ),
23
  'D' =>
@@ -55,6 +56,10 @@ class ComposerStaticInit1b7d202ad01d839050ec4112544e7221
55
  array (
56
  0 => __DIR__ . '/../..' . '/inc/3rd-party/amazon-s3-and-cloudfront/classes',
57
  ),
 
 
 
 
58
  'Imagify\\' =>
59
  array (
60
  0 => __DIR__ . '/../..' . '/classes',
@@ -175,6 +180,11 @@ class ComposerStaticInit1b7d202ad01d839050ec4112544e7221
175
  'Imagify\\Context\\Noop' => __DIR__ . '/../..' . '/classes/Context/Noop.php',
176
  'Imagify\\Context\\WP' => __DIR__ . '/../..' . '/classes/Context/WP.php',
177
  'Imagify\\DB\\DBInterface' => __DIR__ . '/../..' . '/classes/DB/DBInterface.php',
 
 
 
 
 
178
  'Imagify\\Imagifybeat\\Actions' => __DIR__ . '/../..' . '/classes/Imagifybeat/Actions.php',
179
  'Imagify\\Imagifybeat\\Core' => __DIR__ . '/../..' . '/classes/Imagifybeat/Core.php',
180
  'Imagify\\Job\\MediaOptimization' => __DIR__ . '/../..' . '/classes/Job/MediaOptimization.php',
@@ -273,9 +283,9 @@ class ComposerStaticInit1b7d202ad01d839050ec4112544e7221
273
  public static function getInitializer(ClassLoaderWPMediaImagifyWordPressPlugin $loader)
274
  {
275
  return \Closure::bind(function () use ($loader) {
276
- $loader->prefixLengthsPsr4 = ComposerStaticInit1b7d202ad01d839050ec4112544e7221::$prefixLengthsPsr4;
277
- $loader->prefixDirsPsr4 = ComposerStaticInit1b7d202ad01d839050ec4112544e7221::$prefixDirsPsr4;
278
- $loader->classMap = ComposerStaticInit1b7d202ad01d839050ec4112544e7221::$classMap;
279
 
280
  }, null, ClassLoaderWPMediaImagifyWordPressPlugin::class);
281
  }
7
  use Composer\AutoloadWPMediaImagifyWordPressPlugin\ClassLoader as ClassLoaderWPMediaImagifyWordPressPlugin;
8
 
9
 
10
+ class ComposerStaticInit9a65f06d351d3ca28131bdc6dbd92154
11
  {
12
  public static $prefixLengthsPsr4 = array (
13
  'I' =>
18
  'Imagify\\ThirdParty\\FormidablePro\\' => 33,
19
  'Imagify\\ThirdParty\\EnableMediaReplace\\' => 38,
20
  'Imagify\\ThirdParty\\AS3CF\\' => 25,
21
+ 'Imagify\\Deprecated\\Traits\\' => 26,
22
  'Imagify\\' => 8,
23
  ),
24
  'D' =>
56
  array (
57
  0 => __DIR__ . '/../..' . '/inc/3rd-party/amazon-s3-and-cloudfront/classes',
58
  ),
59
+ 'Imagify\\Deprecated\\Traits\\' =>
60
+ array (
61
+ 0 => __DIR__ . '/../..' . '/inc/deprecated/Traits',
62
+ ),
63
  'Imagify\\' =>
64
  array (
65
  0 => __DIR__ . '/../..' . '/classes',
180
  'Imagify\\Context\\Noop' => __DIR__ . '/../..' . '/classes/Context/Noop.php',
181
  'Imagify\\Context\\WP' => __DIR__ . '/../..' . '/classes/Context/WP.php',
182
  'Imagify\\DB\\DBInterface' => __DIR__ . '/../..' . '/classes/DB/DBInterface.php',
183
+ 'Imagify\\Deprecated\\Traits\\Media\\CustomFoldersDeprecatedTrait' => __DIR__ . '/../..' . '/inc/deprecated/Traits/Media/CustomFoldersDeprecatedTrait.php',
184
+ 'Imagify\\Deprecated\\Traits\\Media\\NGGDeprecatedTrait' => __DIR__ . '/../..' . '/inc/deprecated/Traits/Media/NGGDeprecatedTrait.php',
185
+ 'Imagify\\Deprecated\\Traits\\Media\\NoopDeprecatedTrait' => __DIR__ . '/../..' . '/inc/deprecated/Traits/Media/NoopDeprecatedTrait.php',
186
+ 'Imagify\\Deprecated\\Traits\\Media\\WPDeprecatedTrait' => __DIR__ . '/../..' . '/inc/deprecated/Traits/Media/WPDeprecatedTrait.php',
187
+ 'Imagify\\Deprecated\\Traits\\Optimization\\Process\\AbstractProcessDeprecatedTrait' => __DIR__ . '/../..' . '/inc/deprecated/Traits/Optimization/Process/AbstractProcessDeprecatedTrait.php',
188
  'Imagify\\Imagifybeat\\Actions' => __DIR__ . '/../..' . '/classes/Imagifybeat/Actions.php',
189
  'Imagify\\Imagifybeat\\Core' => __DIR__ . '/../..' . '/classes/Imagifybeat/Core.php',
190
  'Imagify\\Job\\MediaOptimization' => __DIR__ . '/../..' . '/classes/Job/MediaOptimization.php',
283
  public static function getInitializer(ClassLoaderWPMediaImagifyWordPressPlugin $loader)
284
  {
285
  return \Closure::bind(function () use ($loader) {
286
+ $loader->prefixLengthsPsr4 = ComposerStaticInit9a65f06d351d3ca28131bdc6dbd92154::$prefixLengthsPsr4;
287
+ $loader->prefixDirsPsr4 = ComposerStaticInit9a65f06d351d3ca28131bdc6dbd92154::$prefixDirsPsr4;
288
+ $loader->classMap = ComposerStaticInit9a65f06d351d3ca28131bdc6dbd92154::$classMap;
289
 
290
  }, null, ClassLoaderWPMediaImagifyWordPressPlugin::class);
291
  }
views/part-settings-library.php CHANGED
@@ -6,17 +6,19 @@ $options = Imagify_Options::get_instance();
6
  $option_name = $options->get_option_name();
7
  ?>
8
  <div class="<?php echo imagify_can_optimize_custom_folders() ? 'imagify-col' : ''; ?>">
9
- <h3 class="imagify-options-subtitle"><?php _e( 'Media Library', 'imagify' ); ?></h3>
10
 
11
  <p class="imagify-setting-line">
12
  <?php
13
- $settings->field_checkbox( array(
14
- 'option_name' => 'resize_larger',
15
- 'label' => __( 'Resize larger images', 'imagify' ),
16
- 'attributes' => array(
17
- 'aria-describedby' => 'describe-resize_larger',
18
- ),
19
- ) );
 
 
20
  ?>
21
 
22
  <span class="imagify-options-line">
@@ -26,7 +28,7 @@ $option_name = $options->get_option_name();
26
  $resize_larger_w = $options->get( 'resize_larger_w' );
27
  printf(
28
  /* translators: 1 is a text input for a number of pixels (don't use %d). */
29
- __( 'to maximum %s pixels width', 'imagify' ),
30
  '<input type="number" id="imagify_resize_larger_w" min="' . $max_sizes['width'] . '" name="' . $option_name . '[resize_larger_w]" value="' . ( $resize_larger_w ? $resize_larger_w : '' ) . '" size="5">'
31
  );
32
  ?>
@@ -38,9 +40,17 @@ $option_name = $options->get_option_name();
38
  <?php
39
  printf(
40
  /* translators: 1 is a number of pixels. */
41
- __( 'This option is recommended to reduce larger images. You can save up to 80%% after resizing. The new width should not be less than your largest thumbnail width, which is actually %dpx.', 'imagify' ),
42
  $max_sizes['width']
43
  );
 
 
 
 
 
 
 
 
44
  ?>
45
  </span>
46
  </p>
@@ -49,23 +59,23 @@ $option_name = $options->get_option_name();
49
 
50
  <div class="imagify-divider"></div>
51
 
52
- <h4 class="imagify-h4-like"><?php _e( 'Files optimization', 'imagify' ); ?></h4>
53
 
54
  <p>
55
- <?php _e( 'You can choose to optimize different image sizes created by WordPress here.', 'imagify' ); ?>
56
  </p>
57
 
58
  <p>
59
  <?php
60
  printf(
61
  /* translators: 1 is a "bold" tag start, 2 is the "bold" tag end. */
62
- __( 'The %1$soriginal size%2$s is %1$sautomatically optimized%2$s by Imagify.', 'imagify' ),
63
  '<strong>', '</strong>'
64
  );
65
  ?>
66
  <br>
67
  <span class="imagify-success">
68
- <?php _e( 'Remember each additional image size will affect your Imagify monthly usage!', 'imagify' ); ?>
69
  </span>
70
  </p>
71
 
@@ -73,12 +83,14 @@ $option_name = $options->get_option_name();
73
  /**
74
  * Disallowed thumbnail sizes.
75
  */
76
- $settings->field_checkbox_list( array(
77
- 'option_name' => 'disallowed-sizes',
78
- 'legend' => __( 'Choose the sizes to optimize', 'imagify' ),
79
- 'values' => Imagify_Settings::get_thumbnail_sizes(),
80
- 'reverse_check' => true,
81
- ) );
 
 
82
  ?>
83
 
84
  <?php endif; ?>
6
  $option_name = $options->get_option_name();
7
  ?>
8
  <div class="<?php echo imagify_can_optimize_custom_folders() ? 'imagify-col' : ''; ?>">
9
+ <h3 class="imagify-options-subtitle"><?php esc_html_e( 'Media Library', 'imagify' ); ?></h3>
10
 
11
  <p class="imagify-setting-line">
12
  <?php
13
+ $settings->field_checkbox(
14
+ [
15
+ 'option_name' => 'resize_larger',
16
+ 'label' => __( 'Resize larger images', 'imagify' ),
17
+ 'attributes' => [
18
+ 'aria-describedby' => 'describe-resize_larger',
19
+ ],
20
+ ]
21
+ );
22
  ?>
23
 
24
  <span class="imagify-options-line">
28
  $resize_larger_w = $options->get( 'resize_larger_w' );
29
  printf(
30
  /* translators: 1 is a text input for a number of pixels (don't use %d). */
31
+ esc_html__( 'to maximum %s pixels width', 'imagify' ),
32
  '<input type="number" id="imagify_resize_larger_w" min="' . $max_sizes['width'] . '" name="' . $option_name . '[resize_larger_w]" value="' . ( $resize_larger_w ? $resize_larger_w : '' ) . '" size="5">'
33
  );
34
  ?>
40
  <?php
41
  printf(
42
  /* translators: 1 is a number of pixels. */
43
+ esc_html__( 'This option is recommended to reduce larger images. You can save up to 80%% after resizing. The new width should not be less than your largest thumbnail width, which is actually %dpx.', 'imagify' ),
44
  $max_sizes['width']
45
  );
46
+ echo ' ';
47
+
48
+ if ( function_exists( 'wp_get_original_image_path' ) ) {
49
+ // WP 5.3+.
50
+ echo '<strong>' . esc_html__( 'Resizing is done on upload or during optimization.', 'imagify' ) . '</strong>';
51
+ } else {
52
+ esc_html_e( 'Resizing is done only during optimization.', 'imagify' );
53
+ }
54
  ?>
55
  </span>
56
  </p>
59
 
60
  <div class="imagify-divider"></div>
61
 
62
+ <h4 class="imagify-h4-like"><?php esc_html_e( 'Files optimization', 'imagify' ); ?></h4>
63
 
64
  <p>
65
+ <?php esc_html_e( 'You can choose to optimize different image sizes created by WordPress here.', 'imagify' ); ?>
66
  </p>
67
 
68
  <p>
69
  <?php
70
  printf(
71
  /* translators: 1 is a "bold" tag start, 2 is the "bold" tag end. */
72
+ esc_html__( 'The %1$soriginal size%2$s is %1$sautomatically optimized%2$s by Imagify.', 'imagify' ),
73
  '<strong>', '</strong>'
74
  );
75
  ?>
76
  <br>
77
  <span class="imagify-success">
78
+ <?php esc_html_e( 'Remember each additional image size will affect your Imagify monthly usage!', 'imagify' ); ?>
79
  </span>
80
  </p>
81
 
83
  /**
84
  * Disallowed thumbnail sizes.
85
  */
86
+ $settings->field_checkbox_list(
87
+ [
88
+ 'option_name' => 'disallowed-sizes',
89
+ 'legend' => __( 'Choose the sizes to optimize', 'imagify' ),
90
+ 'values' => Imagify_Settings::get_thumbnail_sizes(),
91
+ 'reverse_check' => true,
92
+ ]
93
+ );
94
  ?>
95
 
96
  <?php endif; ?>