PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / 1.9.8
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF v1.9.8
2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.9 2.2.8 trunk 1.10 1.3.3 1.3.4 1.3.5 1.3.5.1 1.3.5.2 1.3.6 1.3.6.1 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.5 All 103 releases
imagify / classes / Optimization / Data / AbstractData.php

AbstractData.php in Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF 1.9.8, at classes/Optimization/Data/AbstractData.php

452 lines 10.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Imagify\Optimization\Data;
3
4 use Imagify\Media\MediaInterface;
5
6 defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
7
8 /**
9 * Abstract class used to handle the optimization data of "media groups" (aka attachments).
10 *
11 * @since 1.9
12 * @author Grégory Viguier
13 */
14 abstract class AbstractData implements DataInterface {
15
16 /**
17 * Optimization data structure.
18 * This is the format returned when we "get" optimization data from the DB.
19 *
20 * @var array
21 * @since 1.9
22 * @access protected
23 * @see $this->get_optimization_data()
24 * @author Grégory Viguier
25 */
26 protected $default_optimization_data = [
27 'status' => '',
28 'level' => false,
29 'sizes' => [],
30 'stats' => [
31 'original_size' => 0,
32 'optimized_size' => 0,
33 'percent' => 0,
34 ],
35 ];
36
37 /**
38 * The media object.
39 *
40 * @var MediaInterface
41 * @since 1.9
42 * @access protected
43 * @author Grégory Viguier
44 */
45 protected $media;
46
47 /**
48 * Filesystem object.
49 *
50 * @var object Imagify_Filesystem
51 * @since 1.9
52 * @access protected
53 * @author Grégory Viguier
54 */
55 protected $filesystem;
56
57 /**
58 * The constructor.
59 *
60 * @since 1.9
61 * @access public
62 * @see self::constructor_accepts()
63 * @author Grégory Viguier
64 *
65 * @param mixed $id An ID, or whatever type the constructor accepts.
66 */
67 public function __construct( $id ) {
68 // Set the Media instance.
69 if ( $id instanceof MediaInterface ) {
70 $this->media = $id;
71 } elseif ( static::constructor_accepts( $id ) ) {
72 $media_class = str_replace( '\\Optimization\\Data\\', '\\Media\\', get_called_class() );
73 $media_class = '\\' . ltrim( $media_class, '\\' );
74 $this->media = new $media_class( $id );
75 } else {
76 $this->media = false;
77 }
78
79 $this->filesystem = \Imagify_Filesystem::get_instance();
80 }
81
82 /**
83 * Tell if the given entry can be accepted in the constructor.
84 *
85 * @since 1.9
86 * @access public
87 * @author Grégory Viguier
88 *
89 * @param mixed $id Whatever.
90 * @return bool
91 */
92 public static function constructor_accepts( $id ) {
93 if ( $id instanceof MediaInterface ) {
94 return true;
95 }
96
97 $media_class = str_replace( '\\Optimization\\Data\\', '\\Media\\', get_called_class() );
98 $media_class = '\\' . ltrim( $media_class, '\\' );
99
100 return $media_class::constructor_accepts( $id );
101 }
102
103 /**
104 * Get the media instance.
105 *
106 * @since 1.9
107 * @access public
108 * @author Grégory Viguier
109 *
110 * @return MediaInterface|false
111 */
112 public function get_media() {
113 return $this->media;
114 }
115
116 /**
117 * Tell if the current media is valid.
118 *
119 * @since 1.9
120 * @access public
121 * @author Grégory Viguier
122 *
123 * @return bool
124 */
125 public function is_valid() {
126 return $this->get_media() && $this->get_media()->is_valid();
127 }
128
129
130 /** ----------------------------------------------------------------------------------------- */
131 /** OPTIMIZATION DATA ======================================================================= */
132 /** ----------------------------------------------------------------------------------------- */
133
134 /**
135 * Check if the main file is optimized (by Imagify).
136 *
137 * @since 1.9
138 * @access public
139 * @author Grégory Viguier
140 *
141 * @return bool True if the media is optimized.
142 */
143 public function is_optimized() {
144 return 'success' === $this->get_optimization_status();
145 }
146
147 /**
148 * Check if the main file is optimized (NOT by Imagify).
149 *
150 * @since 1.9
151 * @access public
152 * @author Grégory Viguier
153 *
154 * @return bool True if the media is optimized.
155 */
156 public function is_already_optimized() {
157 return 'already_optimized' === $this->get_optimization_status();
158 }
159
160 /**
161 * Check if the main file is optimized (by Imagify).
162 *
163 * @since 1.9
164 * @access public
165 * @author Grégory Viguier
166 *
167 * @return bool True if the media is optimized.
168 */
169 public function is_error() {
170 return 'error' === $this->get_optimization_status();
171 }
172
173 /**
174 * Get the media's optimization level.
175 *
176 * @since 1.9
177 * @access public
178 * @author Grégory Viguier
179 *
180 * @return int|false The optimization level. False if not optimized.
181 */
182 public function get_optimization_level() {
183 if ( ! $this->is_valid() ) {
184 return false;
185 }
186
187 $data = $this->get_optimization_data();
188 return $data['level'];
189 }
190
191 /**
192 * Get the media's optimization status (success or error).
193 *
194 * @since 1.9
195 * @access public
196 * @author Grégory Viguier
197 *
198 * @return string The optimization status. An empty string if there is none.
199 */
200 public function get_optimization_status() {
201 if ( ! $this->is_valid() ) {
202 return '';
203 }
204
205 $data = $this->get_optimization_data();
206 return $data['status'];
207 }
208
209 /**
210 * Count number of optimized sizes.
211 *
212 * @since 1.9
213 * @access public
214 * @author Grégory Viguier
215 *
216 * @return int Number of optimized sizes.
217 */
218 public function get_optimized_sizes_count() {
219 $data = $this->get_optimization_data();
220 $count = 0;
221
222 if ( ! $data['sizes'] ) {
223 return 0;
224 }
225
226 $context_sizes = $this->get_media()->get_media_files();
227 $data['sizes'] = array_intersect_key( $data['sizes'], $context_sizes );
228
229 if ( ! $data['sizes'] ) {
230 return 0;
231 }
232
233 foreach ( $data['sizes'] as $size ) {
234 if ( ! empty( $size['success'] ) ) {
235 $count++;
236 }
237 }
238
239 return $count;
240 }
241
242 /**
243 * Get the original media's size (weight).
244 *
245 * @since 1.9
246 * @access public
247 * @author Grégory Viguier
248 *
249 * @param bool $human_format True to display the image human format size (1Mb).
250 * @param int $decimals Precision of number of decimal places.
251 * @return string|int
252 */
253 public function get_original_size( $human_format = true, $decimals = 2 ) {
254 if ( ! $this->is_valid() ) {
255 return $human_format ? imagify_size_format( 0, $decimals ) : 0;
256 }
257
258 $size = $this->get_optimization_data();
259 $size = ! empty( $size['sizes']['full']['original_size'] ) ? $size['sizes']['full']['original_size'] : 0;
260
261 // If nothing in the database, try to get the info from the file.
262 if ( ! $size ) {
263 // Check for the backup file first.
264 $filepath = $this->get_media()->get_backup_path();
265
266 if ( ! $filepath ) {
267 // Try the original file then.
268 $filepath = $this->get_media()->get_original_path();
269 }
270
271 $size = $filepath ? $this->filesystem->size( $filepath ) : 0;
272 }
273
274 if ( $human_format ) {
275 return imagify_size_format( (int) $size, $decimals );
276 }
277
278 return (int) $size;
279 }
280
281 /**
282 * Get the file size of the full size file.
283 * If the webp size is available, it is used.
284 *
285 * @since 1.9
286 * @access public
287 * @author Grégory Viguier
288 *
289 * @param bool $human_format True to display the image human format size (1Mb).
290 * @param int $decimals Precision of number of decimal places.
291 * @param bool $use_webp Use the webp size if available.
292 * @return string|int
293 */
294 public function get_optimized_size( $human_format = true, $decimals = 2, $use_webp = true ) {
295 if ( ! $this->is_valid() ) {
296 return $human_format ? imagify_size_format( 0, $decimals ) : 0;
297 }
298
299 $data = $this->get_optimization_data();
300 $media = $this->get_media();
301
302 if ( $use_webp ) {
303 $process_class_name = imagify_get_optimization_process_class_name( $media->get_context() );
304 $webp_size_name = 'full' . constant( $process_class_name . '::WEBP_SUFFIX' );
305 }
306
307 if ( $use_webp && ! empty( $data['sizes'][ $webp_size_name ]['optimized_size'] ) ) {
308 $size = (int) $data['sizes'][ $webp_size_name ]['optimized_size'];
309 } elseif ( ! empty( $data['sizes']['full']['optimized_size'] ) ) {
310 $size = (int) $data['sizes']['full']['optimized_size'];
311 } else {
312 $size = 0;
313 }
314
315 if ( $size ) {
316 return $human_format ? imagify_size_format( $size, $decimals ) : $size;
317 }
318
319 // If nothing in the database, try to get the info from the file.
320 $filepath = false;
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 ) ) {
328 $filepath = false;
329 }
330 }
331
332 if ( ! $filepath ) {
333 // No webp? The full size then.
334 $filepath = $media->get_fullsize_path();
335 }
336
337 if ( ! $filepath ) {
338 return $human_format ? imagify_size_format( 0, $decimals ) : 0;
339 }
340
341 $size = (int) $this->filesystem->size( $filepath );
342
343 return $human_format ? imagify_size_format( $size, $decimals ) : $size;
344 }
345
346
347 /** ----------------------------------------------------------------------------------------- */
348 /** OPTIMIZATION STATS ====================================================================== */
349 /** ----------------------------------------------------------------------------------------- */
350
351 /**
352 * Get one or all statistics of a specific size.
353 *
354 * @since 1.9
355 * @access public
356 * @author Grégory Viguier
357 *
358 * @param string $size The thumbnail slug.
359 * @param string $key The specific data slug.
360 * @return array|string
361 */
362 public function get_size_data( $size = 'full', $key = '' ) {
363 $data = $this->get_optimization_data();
364
365 if ( ! isset( $data['sizes'][ $size ] ) ) {
366 return $key ? '' : [];
367 }
368
369 if ( ! $key ) {
370 return $data['sizes'][ $size ];
371 }
372
373 if ( ! isset( $data['sizes'][ $size ][ $key ] ) ) {
374 return '';
375 }
376
377 return $data['sizes'][ $size ][ $key ];
378 }
379
380 /**
381 * Get the overall statistics data or a specific one.
382 *
383 * @since 1.9
384 * @access public
385 * @author Grégory Viguier
386 *
387 * @param string $key The specific data slug.
388 * @return array|string
389 */
390 public function get_stats_data( $key = '' ) {
391 $data = $this->get_optimization_data();
392 $stats = '';
393
394 if ( empty( $data['stats'] ) ) {
395 return $key ? '' : [];
396 }
397
398 if ( ! isset( $data['stats'][ $key ] ) ) {
399 return '';
400 }
401
402 return $data['stats'][ $key ];
403 }
404
405 /**
406 * Get the optimized/original saving of the original image in percent.
407 *
408 * @since 1.9
409 * @access public
410 * @author Grégory Viguier
411 *
412 * @return float A 2-decimals float.
413 */
414 public function get_saving_percent() {
415 if ( ! $this->is_valid() ) {
416 return round( (float) 0, 2 );
417 }
418
419 $process_class_name = imagify_get_optimization_process_class_name( $this->get_media()->get_context() );
420 $webp_size_name = 'full' . constant( $process_class_name . '::WEBP_SUFFIX' );
421
422 $percent = $this->get_size_data( $webp_size_name, 'percent' );
423
424 if ( ! $percent ) {
425 $percent = $this->get_size_data( 'full', 'percent' );
426 }
427
428 $percent = $percent ? $percent : 0;
429
430 return round( (float) $percent, 2 );
431 }
432
433 /**
434 * Get the overall optimized/original saving (original image + all thumbnails) in percent.
435 *
436 * @since 1.9
437 * @access public
438 * @author Grégory Viguier
439 *
440 * @return float A 2-decimals float.
441 */
442 public function get_overall_saving_percent() {
443 if ( ! $this->is_valid() ) {
444 return round( (float) 0, 2 );
445 }
446
447 $percent = $this->get_stats_data( 'percent' );
448
449 return round( (float) $percent, 2 );
450 }
451 }
452