PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / 2.2.9
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF v2.2.9
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 / inc / functions / admin-stats.php

admin-stats.php in Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF 2.2.9, at inc/functions/admin-stats.php

841 lines 25.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 defined( 'ABSPATH' ) || exit;
3
4 /**
5 * Count number of attachments.
6 *
7 * @since 1.0
8 * @author Jonathan Buttigieg
9 *
10 * @return int The number of attachments.
11 */
12 function imagify_count_attachments() {
13 global $wpdb;
14 static $count;
15
16 /**
17 * Filter the number of attachments.
18 * 3rd party will be able to override the result.
19 *
20 * @since 1.5
21 *
22 * @param int|bool $pre_count Default is false. Provide an integer.
23 */
24 $pre_count = apply_filters( 'imagify_count_attachments', false );
25
26 if ( false !== $pre_count ) {
27 return (int) $pre_count;
28 }
29
30 if ( isset( $count ) ) {
31 return $count;
32 }
33
34 $mime_types = Imagify_DB::get_mime_types();
35 $statuses = Imagify_DB::get_post_statuses();
36 $nodata_join = '';
37 $nodata_where = '';
38
39 if ( ! imagify_has_attachments_without_required_metadata() ) {
40 $nodata_join = Imagify_DB::get_required_wp_metadata_join_clause(
41 'p.ID',
42 true,
43 true,
44 "AND p.post_mime_type IN ( $mime_types )
45 AND p.post_type = 'attachment'
46 AND p.post_status IN ( $statuses )"
47 );
48 $nodata_where = Imagify_DB::get_required_wp_metadata_where_clause();
49 }
50
51 $count = (int) $wpdb->get_var( // WPCS: unprepared SQL ok.
52 "
53 SELECT COUNT( p.ID )
54 FROM $wpdb->posts AS p
55 $nodata_join
56 WHERE p.post_mime_type IN ( $mime_types )
57 AND p.post_type = 'attachment'
58 AND p.post_status IN ( $statuses )
59 $nodata_where"
60 );
61
62 if ( $count > imagify_get_unoptimized_attachment_limit() ) {
63 set_transient( 'imagify_large_library', 1 );
64 } elseif ( get_transient( 'imagify_large_library' ) ) {
65 // In case the number is decreasing under our limit.
66 delete_transient( 'imagify_large_library' );
67 }
68
69 return $count;
70 }
71
72 /**
73 * Count number of optimized attachments with an error.
74 *
75 * @since 1.0
76 * @author Jonathan Buttigieg
77 *
78 * @return int The number of attachments.
79 */
80 function imagify_count_error_attachments() {
81 global $wpdb;
82 static $count;
83
84 /**
85 * Filter the number of optimized attachments with an error.
86 * 3rd party will be able to override the result.
87 *
88 * @since 1.5
89 *
90 * @param int|bool $pre_count Default is false. Provide an integer.
91 */
92 $pre_count = apply_filters( 'imagify_count_error_attachments', false );
93
94 if ( false !== $pre_count ) {
95 return (int) $pre_count;
96 }
97
98 if ( isset( $count ) ) {
99 return $count;
100 }
101
102 $mime_types = Imagify_DB::get_mime_types();
103 $statuses = Imagify_DB::get_post_statuses();
104 $nodata_join = '';
105 $nodata_where = '';
106
107 if ( ! imagify_has_attachments_without_required_metadata() ) {
108 $nodata_join = Imagify_DB::get_required_wp_metadata_join_clause();
109 $nodata_where = Imagify_DB::get_required_wp_metadata_where_clause();
110 }
111
112 $count = (int) $wpdb->get_var( // WPCS: unprepared SQL ok.
113 "
114 SELECT COUNT(*)
115 FROM (
116 SELECT p.ID
117 FROM $wpdb->posts AS p
118 $nodata_join
119 INNER JOIN $wpdb->postmeta AS mt1
120 ON ( p.ID = mt1.post_id AND mt1.meta_key = '_imagify_status' )
121 WHERE p.post_mime_type IN ( $mime_types )
122 AND p.post_type = 'attachment'
123 AND p.post_status IN ( $statuses )
124 AND mt1.meta_value = 'error'
125 $nodata_where GROUP BY p.ID
126 ) AS imagify_count_error"
127 );
128
129 return $count;
130 }
131
132 /**
133 * Count number of optimized attachments (by Imagify or an other tool before).
134 *
135 * @since 1.0
136 * @author Jonathan Buttigieg
137 *
138 * @return int The number of attachments.
139 */
140 function imagify_count_optimized_attachments() {
141 global $wpdb;
142 static $count;
143
144 /**
145 * Filter the number of optimized attachments.
146 * 3rd party will be able to override the result.
147 *
148 * @since 1.5
149 *
150 * @param int|bool $pre_count Default is false. Provide an integer.
151 */
152 $pre_count = apply_filters( 'imagify_count_optimized_attachments', false );
153
154 if ( false !== $pre_count ) {
155 return (int) $pre_count;
156 }
157
158 if ( isset( $count ) ) {
159 return $count;
160 }
161
162 $mime_types = Imagify_DB::get_mime_types();
163 $statuses = Imagify_DB::get_post_statuses();
164 $nodata_join = '';
165 $nodata_where = '';
166
167 if ( ! imagify_has_attachments_without_required_metadata() ) {
168 $nodata_join = Imagify_DB::get_required_wp_metadata_join_clause();
169 $nodata_where = Imagify_DB::get_required_wp_metadata_where_clause();
170 }
171
172 $count = (int) $wpdb->get_var( // WPCS: unprepared SQL ok.
173 "
174 SELECT COUNT( DISTINCT p.ID )
175 FROM $wpdb->posts AS p
176 $nodata_join
177 INNER JOIN $wpdb->postmeta AS mt1
178 ON ( p.ID = mt1.post_id AND mt1.meta_key = '_imagify_status' )
179 WHERE p.post_mime_type IN ( $mime_types )
180 AND p.post_type = 'attachment'
181 AND p.post_status IN ( $statuses )
182 AND mt1.meta_value IN ( 'success', 'already_optimized' )
183 $nodata_where"
184 );
185
186 return $count;
187 }
188
189 /**
190 * Count number of unoptimized attachments.
191 *
192 * @since 1.0
193 * @author Jonathan Buttigieg
194 *
195 * @return int The number of attachments.
196 */
197 function imagify_count_unoptimized_attachments() {
198 /**
199 * Filter the number of unoptimized attachments.
200 * 3rd party will be able to override the result.
201 *
202 * @since 1.5
203 *
204 * @param int|bool $pre_count Default is false. Provide an integer.
205 */
206 $pre_count = apply_filters( 'imagify_count_unoptimized_attachments', false );
207
208 if ( false !== $pre_count ) {
209 return (int) $pre_count;
210 }
211
212 return imagify_count_attachments() - imagify_count_optimized_attachments() - imagify_count_error_attachments();
213 }
214
215 /**
216 * Count percent of optimized attachments.
217 *
218 * @since 1.0
219 * @author Jonathan Buttigieg
220 *
221 * @return int The percent of optimized attachments.
222 */
223 function imagify_percent_optimized_attachments() {
224 /**
225 * Filter the percent of optimized attachments.
226 * 3rd party will be able to override the result.
227 *
228 * @since 1.5
229 *
230 * @param int|bool $percent Default is false. Provide an integer.
231 */
232 $percent = apply_filters( 'imagify_percent_optimized_attachments', false );
233
234 if ( false !== $percent ) {
235 return (int) $percent;
236 }
237
238 $total_attachments = imagify_count_attachments();
239 $total_optimized_attachments = imagify_count_optimized_attachments();
240
241 if ( ! $total_attachments || ! $total_optimized_attachments ) {
242 return 0;
243 }
244
245 return min( round( 100 * $total_optimized_attachments / $total_attachments ), 100 );
246 }
247
248 /**
249 * Count percent, original & optimized size of all images optimized by Imagify.
250 *
251 * @since 1.0
252 * @since 1.6.7 Revamped to handle huge libraries.
253 * @author Jonathan Buttigieg
254 *
255 * @param string $key What data to return. Choices are between 'count', 'original_size', 'optimized_size', and 'percent'. If left empty, the whole array is returned.
256 * @return array|int An array containing the optimization data. A single data if $key is provided.
257 */
258 function imagify_count_saving_data( $key = '' ) {
259 global $wpdb;
260
261 /**
262 * Filter the query to get all optimized attachments.
263 * 3rd party will be able to override the result.
264 *
265 * @since 1.5
266 * @since 1.6.7 This filter should return an array containing the following keys: 'count', 'original_size', and 'optimized_size'.
267 *
268 * @param bool|array $attachments An array containing the keys ('count', 'original_size', and 'optimized_size'), or an array of attachments (back compat', deprecated), or false.
269 */
270 $attachments = apply_filters( 'imagify_count_saving_data', false );
271
272 $original_size = 0;
273 $optimized_size = 0;
274 $count = 0;
275
276 if ( is_array( $attachments ) ) {
277 /**
278 * Bypass.
279 */
280 if ( isset( $attachments['count'], $attachments['original_size'], $attachments['optimized_size'] ) ) {
281 /**
282 * We have the results we need.
283 */
284 $attachments['percent'] = $attachments['optimized_size'] && $attachments['original_size'] ? ceil( ( ( $attachments['original_size'] - $attachments['optimized_size'] ) / $attachments['original_size'] ) * 100 ) : 0;
285
286 return $attachments;
287 }
288
289 /**
290 * Back compat'.
291 * The following shouldn't be used. Sites with a huge library won't like it.
292 */
293 $attachments = array_map( 'maybe_unserialize', (array) $attachments );
294
295 if ( $attachments ) {
296 foreach ( $attachments as $attachment_data ) {
297 if ( ! $attachment_data ) {
298 continue;
299 }
300
301 ++$count;
302 $original_data = $attachment_data['sizes']['full'];
303
304 // Increment the original sizes.
305 $original_size += $original_data['original_size'] ? $original_data['original_size'] : 0;
306 $optimized_size += $original_data['optimized_size'] ? $original_data['optimized_size'] : 0;
307
308 unset( $attachment_data['sizes']['full'] );
309
310 // Increment the thumbnails sizes.
311 if ( $attachment_data['sizes'] ) {
312 foreach ( $attachment_data['sizes'] as $size_data ) {
313 if ( ! empty( $size_data['success'] ) ) {
314 $original_size += $size_data['original_size'] ? $size_data['original_size'] : 0;
315 $optimized_size += $size_data['optimized_size'] ? $size_data['optimized_size'] : 0;
316 }
317 }
318 }
319 }
320 }
321 } else {
322 /**
323 * Filter the chunk size of the requests fetching the data.
324 * 15,000 seems to be a good balance between memory used, speed, and number of DB hits.
325 *
326 * @param int $limit The maximum number of elements per chunk.
327 */
328 $limit = apply_filters( 'imagify_count_saving_data_limit', 15000 );
329 $limit = absint( $limit );
330
331 $mime_types = Imagify_DB::get_mime_types();
332 $statuses = Imagify_DB::get_post_statuses();
333 $nodata_join = '';
334 $nodata_where = '';
335
336 if ( ! imagify_has_attachments_without_required_metadata() ) {
337 $nodata_join = Imagify_DB::get_required_wp_metadata_join_clause();
338 $nodata_where = Imagify_DB::get_required_wp_metadata_where_clause();
339 }
340
341 $attachment_ids = $wpdb->get_col( // WPCS: unprepared SQL ok.
342 "
343 SELECT p.ID
344 FROM $wpdb->posts AS p
345 $nodata_join
346 INNER JOIN $wpdb->postmeta AS mt1
347 ON ( p.ID = mt1.post_id AND mt1.meta_key = '_imagify_status' )
348 WHERE p.post_mime_type IN ( $mime_types )
349 AND p.post_type = 'attachment'
350 AND p.post_status IN ( $statuses )
351 AND mt1.meta_value = 'success'
352 $nodata_where
353 ORDER BY CAST( p.ID AS UNSIGNED )"
354 );
355 $wpdb->flush();
356
357 $attachment_ids = array_map( 'absint', array_unique( $attachment_ids ) );
358 $attachment_ids = array_chunk( $attachment_ids, $limit );
359
360 while ( $attachment_ids ) {
361 $limit_ids = array_shift( $attachment_ids );
362 $limit_ids = implode( ',', $limit_ids );
363
364 $attachments = $wpdb->get_col( // WPCS: unprepared SQL ok.
365 "
366 SELECT meta_value
367 FROM $wpdb->postmeta
368 WHERE post_id IN ( $limit_ids )
369 AND meta_key = '_imagify_data'"
370 );
371 $wpdb->flush();
372
373 unset( $limit_ids );
374
375 if ( ! $attachments ) {
376 continue;
377 }
378
379 $attachments = array_map( 'maybe_unserialize', $attachments );
380
381 foreach ( $attachments as $attachment_data ) {
382 if ( ! $attachment_data ) {
383 continue;
384 }
385
386 if ( empty( $attachment_data['sizes']['full']['success'] ) ) {
387 /**
388 * - Case where this attachment has multiple '_imagify_status' metas, and is fetched (in the above query) as a "success" while the '_imagify_data' says otherwise.
389 * - Case where this meta has no "full" entry.
390 * Don't ask how it's possible, I don't know ¯\(°_o)/¯
391 */
392 continue;
393 }
394
395 $original_data = $attachment_data['sizes']['full'];
396
397 ++$count;
398
399 // Increment the original sizes.
400 $original_size += ! empty( $original_data['original_size'] ) ? $original_data['original_size'] : 0;
401 $optimized_size += ! empty( $original_data['optimized_size'] ) ? $original_data['optimized_size'] : 0;
402
403 unset( $attachment_data['sizes']['full'], $original_data );
404
405 // Increment the thumbnails sizes.
406 if ( $attachment_data['sizes'] ) {
407 foreach ( $attachment_data['sizes'] as $size_data ) {
408 if ( ! empty( $size_data['success'] ) ) {
409 $original_size += ! empty( $size_data['original_size'] ) ? $size_data['original_size'] : 0;
410 $optimized_size += ! empty( $size_data['optimized_size'] ) ? $size_data['optimized_size'] : 0;
411 }
412 }
413 }
414
415 unset( $size_data );
416 }
417
418 unset( $attachments, $attachment_data );
419 }
420 }
421
422 $data = [
423 'count' => $count,
424 'original_size' => $original_size,
425 'optimized_size' => $optimized_size,
426 'percent' => $original_size && $optimized_size ? ceil( ( ( $original_size - $optimized_size ) / $original_size ) * 100 ) : 0,
427 ];
428
429 if ( ! empty( $key ) ) {
430 return isset( $data[ $key ] ) ? $data[ $key ] : 0;
431 }
432
433 return $data;
434 }
435
436 /**
437 * Returns the estimated total size of the images not optimized.
438 *
439 * We estimate the total size of the images in the library by getting the latest 250 images and their thumbnails
440 * add up their filesizes, and doing some maths to get the total size.
441 *
442 * @since 1.6
443 * @author Remy Perona
444 *
445 * @return int The current estimated total size of images not optimized.
446 */
447 function imagify_calculate_total_size_images_library() {
448 global $wpdb;
449
450 $mime_types = Imagify_DB::get_mime_types();
451 $statuses = Imagify_DB::get_post_statuses();
452 $nodata_join = Imagify_DB::get_required_wp_metadata_join_clause();
453 $nodata_where = Imagify_DB::get_required_wp_metadata_where_clause();
454 $image_ids = $wpdb->get_col( // WPCS: unprepared SQL ok.
455 "
456 SELECT p.ID
457 FROM $wpdb->posts AS p
458 $nodata_join
459 WHERE p.post_mime_type IN ( $mime_types )
460 AND p.post_type = 'attachment'
461 AND p.post_status IN ( $statuses )
462 $nodata_where
463 LIMIT 250
464 "
465 );
466
467 if ( ! $image_ids ) {
468 return 0;
469 }
470
471 $count_latest_images = count( $image_ids );
472 $count_total_images = imagify_count_attachments();
473
474 return imagify_calculate_total_image_size( $image_ids, $count_latest_images, $count_total_images );
475 }
476
477 /**
478 * Returns the estimated average size of the images uploaded per month.
479 *
480 * We estimate the average size of the images uploaded in the library per month by getting the latest 250 images and their thumbnails
481 * for the 3 latest months, add up their filesizes, and doing some maths to get the total average size.
482 *
483 * @since 1.6
484 * @since 1.7 Use wpdb instead of WP_Query.
485 * @author Remy Perona
486 *
487 * @return int The current estimated average size of images uploaded per month.
488 */
489 function imagify_calculate_average_size_images_per_month() {
490 global $wpdb;
491
492 $mime_types = Imagify_DB::get_mime_types();
493 $statuses = Imagify_DB::get_post_statuses();
494 $nodata_join = Imagify_DB::get_required_wp_metadata_join_clause( "$wpdb->posts.ID" );
495 $nodata_where = Imagify_DB::get_required_wp_metadata_where_clause();
496 $limit = ' LIMIT 0, 250';
497 $query = "
498 SELECT $wpdb->posts.ID
499 FROM $wpdb->posts
500 $nodata_join
501 WHERE $wpdb->posts.post_mime_type IN ( $mime_types )
502 AND $wpdb->posts.post_type = 'attachment'
503 AND $wpdb->posts.post_status IN ( $statuses )
504 $nodata_where
505 %date_query%";
506
507 // Queries per month.
508 $date_query = new WP_Date_Query(
509 [
510 [
511 'before' => 'now',
512 'after' => '1 month ago',
513 ],
514 ]
515 );
516
517 $partial_images_uploaded_last_month = $wpdb->get_col( str_replace( '%date_query%', $date_query->get_sql(), $query . $limit ) ); // WPCS: unprepared SQL ok.
518
519 $date_query = new WP_Date_Query(
520 [
521 [
522 'before' => '1 month ago',
523 'after' => '2 months ago',
524 ],
525 ]
526 );
527
528 $partial_images_uploaded_two_months_ago = $wpdb->get_col( str_replace( '%date_query%', $date_query->get_sql(), $query . $limit ) ); // WPCS: unprepared SQL ok.
529
530 $date_query = new WP_Date_Query(
531 [
532 [
533 'before' => '2 month ago',
534 'after' => '3 months ago',
535 ],
536 ]
537 );
538
539 $partial_images_uploaded_three_months_ago = $wpdb->get_col( str_replace( '%date_query%', $date_query->get_sql(), $query . $limit ) ); // WPCS: unprepared SQL ok.
540
541 // Total for the 3 months.
542 $partial_images_uploaded_id = array_merge( $partial_images_uploaded_last_month, $partial_images_uploaded_two_months_ago, $partial_images_uploaded_three_months_ago );
543
544 if ( ! $partial_images_uploaded_id ) {
545 return 0;
546 }
547
548 // Total for the 3 months, without the "250" limit.
549 $date_query = new WP_Date_Query(
550 [
551 [
552 'before' => 'now',
553 'after' => '3 month ago',
554 ],
555 ]
556 );
557
558 $images_uploaded_id = $wpdb->get_col( str_replace( '%date_query%', $date_query->get_sql(), $query ) ); // WPCS: unprepared SQL ok.
559
560 if ( ! $images_uploaded_id ) {
561 return 0;
562 }
563
564 // Number of image attachments uploaded for the 3 latest months, limited to 250 per month.
565 $partial_total_images_uploaded = count( $partial_images_uploaded_id );
566 // Total number of image attachments uploaded for the 3 latest months.
567 $total_images_uploaded = count( $images_uploaded_id );
568
569 return imagify_calculate_total_image_size( $partial_images_uploaded_id, $partial_total_images_uploaded, $total_images_uploaded ) / 3;
570 }
571
572 /**
573 * Returns the estimated total size of images.
574 *
575 * @since 1.6
576 * @author Remy Perona
577 *
578 * @param array $image_ids Array of image IDs.
579 * @param int $partial_total_images The number of image attachments we're doing the calculation with.
580 * @param int $total_images The total number of image attachments.
581 * @return int The estimated total size of images.
582 */
583 function imagify_calculate_total_image_size( $image_ids, $partial_total_images, $total_images ) {
584 global $wpdb;
585
586 $image_ids = array_filter( array_map( 'absint', $image_ids ) );
587
588 if ( ! $image_ids ) {
589 return 0;
590 }
591
592 $results = Imagify_DB::get_metas(
593 [
594 // Get attachments filename.
595 'filenames' => '_wp_attached_file',
596 // Get attachments data.
597 'data' => '_wp_attachment_metadata',
598 // Get Imagify data.
599 'imagify_data' => '_imagify_data',
600 // Get attachments status.
601 'statuses' => '_imagify_status',
602 ],
603 $image_ids
604 );
605
606 // Number of image attachments we're doing the calculation with. In case array_filter() removed results.
607 $partial_total_images = count( $image_ids );
608 // Total size of unoptimized size.
609 $partial_size_images = 0;
610 // Total number of thumbnails.
611 $partial_total_intermediate_images = 0;
612
613 $filesystem = imagify_get_filesystem();
614 $is_active_for_network = imagify_is_active_for_network();
615 $disallowed_sizes = get_imagify_option( 'disallowed-sizes' );
616
617 foreach ( $image_ids as $i => $image_id ) {
618 $attachment_status = isset( $results['statuses'][ $image_id ] ) ? $results['statuses'][ $image_id ] : false;
619
620 if ( 'success' === $attachment_status ) {
621 /**
622 * The image files have been optimized.
623 */
624 // Original size.
625 $partial_size_images += isset( $results['imagify_data'][ $image_id ]['stats']['original_size'] ) ? $results['imagify_data'][ $image_id ]['stats']['original_size'] : 0;
626 // Number of thumbnails.
627 $partial_total_intermediate_images += count( $results['imagify_data'][ $image_id ]['sizes'] );
628 unset(
629 $image_ids[ $i ],
630 $results['filenames'][ $image_id ],
631 $results['data'][ $image_id ],
632 $results['imagify_data'][ $image_id ],
633 $results['statuses'][ $image_id ]
634 );
635 continue;
636 }
637
638 /**
639 * The image files are not optimized.
640 */
641 // Create an array containing all this attachment files.
642 $files = [
643 'full' => get_imagify_attached_file( $results['filenames'][ $image_id ] ),
644 ];
645
646 $sizes = isset( $results['data'][ $image_id ]['sizes'] ) ? $results['data'][ $image_id ]['sizes'] : [];
647
648 if ( $sizes && is_array( $sizes ) ) {
649 if ( ! $is_active_for_network ) {
650 $sizes = array_diff_key( $sizes, $disallowed_sizes );
651 }
652
653 if ( $sizes ) {
654 $full_dirname = $filesystem->dir_path( $files['full'] );
655
656 foreach ( $sizes as $size_key => $size_data ) {
657 $files[ $size_key ] = $full_dirname . '/' . $size_data['file'];
658 }
659 }
660 }
661
662 /**
663 * Allow to provide all files size and the number of thumbnails.
664 *
665 * @since 1.6.7
666 * @author Grégory Viguier
667 *
668 * @param bool $size_and_count False by default.
669 * @param int $image_id The attachment ID.
670 * @param array $files An array of file paths with thumbnail sizes as keys.
671 * @param array $image_ids An array of all attachment IDs.
672 * @return bool|array False by default. Provide an array with the keys 'filesize' (containing the total filesize) and 'thumbnails' (containing the number of thumbnails).
673 */
674 $size_and_count = apply_filters( 'imagify_total_attachment_filesize', false, $image_id, $files, $image_ids );
675
676 if ( is_array( $size_and_count ) ) {
677 $partial_size_images += $size_and_count['filesize'];
678 $partial_total_intermediate_images += $size_and_count['thumbnails'];
679 } else {
680 foreach ( $files as $file ) {
681 if ( $filesystem->exists( $file ) ) {
682 $partial_size_images += $filesystem->size( $file );
683 }
684 }
685
686 unset( $files['full'] );
687 $partial_total_intermediate_images += count( $files );
688 }
689
690 unset(
691 $image_ids[ $i ],
692 $results['filenames'][ $image_id ],
693 $results['data'][ $image_id ],
694 $results['imagify_data'][ $image_id ],
695 $results['statuses'][ $image_id ]
696 );
697 }
698
699 // Number of thumbnails per attachment = Number of thumbnails / Number of attachments.
700 $intermediate_images_per_image = $partial_total_intermediate_images / $partial_total_images;
701 /**
702 * Note: Number of attachments ($partial_total_images) === Number of full sizes.
703 * Average image size = Size of the images / ( Number of full sizes + Number of thumbnails ).
704 * Average image size = Size of the images / Number of images.
705 */
706 $average_size_images = $partial_size_images / ( $partial_total_images + $partial_total_intermediate_images );
707 /**
708 * Note: Total number of attachments ($total_images) === Total number of full sizes.
709 * Total images size = Average image size * ( Total number of full sizes + ( Number of thumbnails per attachment * Total number of attachments ) ).
710 * Total images size = Average image size * ( Total number of full sizes + Total number of thumbnails ).
711 */
712 $total_size_images = $average_size_images * ( $total_images + ( $intermediate_images_per_image * $total_images ) );
713
714 return $total_size_images;
715 }
716
717 /**
718 * Get all generic stats to be used in the bulk optimization page.
719 *
720 * @since 1.7.1
721 * @author Grégory Viguier
722 *
723 * @param array $types The folder types. If a folder type is "library", the context should be suffixed after a pipe character. They are passed as array keys.
724 * @param array $args {
725 * Optional. An array of arguments.
726 *
727 * @type bool $fullset True to return the full set of data. False to return only the main data.
728 * @type bool $formatting Some of the data is returned formatted.
729 * }
730 * @return array
731 */
732 function imagify_get_bulk_stats( $types, $args = [] ) {
733 $types = $types && is_array( $types ) ? $types : [];
734 $args = array_merge(
735 [
736 'fullset' => false,
737 'formatting' => true,
738 ],
739 (array) $args
740 );
741
742 $data = [
743 // Global chart.
744 'total_attachments' => 0,
745 'unoptimized_attachments' => 0,
746 'optimized_attachments' => 0,
747 'errors_attachments' => 0,
748 // Stats block.
749 'already_optimized_attachments' => 0,
750 'original_human' => 0,
751 'optimized_human' => 0,
752 ];
753
754 if ( isset( $types['library|wp'] ) ) {
755 /**
756 * Library.
757 */
758 $saving_data = imagify_count_saving_data();
759
760 // Global chart.
761 $data['total_attachments'] += imagify_count_attachments();
762 $data['unoptimized_attachments'] += imagify_count_unoptimized_attachments();
763 $data['optimized_attachments'] += imagify_count_optimized_attachments();
764 $data['errors_attachments'] += imagify_count_error_attachments();
765 // Stats block.
766 $data['already_optimized_attachments'] += $saving_data['count'];
767 $data['original_human'] += $saving_data['original_size'];
768 $data['optimized_human'] += $saving_data['optimized_size'];
769 }
770
771 if ( isset( $types['custom-folders|custom-folders'] ) ) {
772 /**
773 * Custom folders.
774 */
775 // Global chart.
776 $data['total_attachments'] += Imagify_Files_Stats::count_all_files();
777 $data['unoptimized_attachments'] += Imagify_Files_Stats::count_no_status_files();
778 $data['optimized_attachments'] += Imagify_Files_Stats::count_optimized_files();
779 $data['errors_attachments'] += Imagify_Files_Stats::count_error_files();
780 // Stats block.
781 $data['already_optimized_attachments'] += Imagify_Files_Stats::count_success_files();
782 $data['original_human'] += Imagify_Files_Stats::get_original_size();
783 $data['optimized_human'] += Imagify_Files_Stats::get_optimized_size();
784 }
785
786 /**
787 * Full set of data.
788 */
789 if ( $args['fullset'] ) {
790 // User account.
791 $views = Imagify_Views::get_instance();
792
793 $data['unconsumed_quota'] = $views->get_quota_percent();
794 $data['quota_class'] = $views->get_quota_class();
795 $data['quota_icon'] = $views->get_quota_icon();
796 }
797
798 /**
799 * Filter the generic stats used in the bulk optimization page.
800 *
801 * @since 1.7.1
802 * @author Grégory Viguier
803 *
804 * @param array $data The data.
805 * @param array $types The folder types. They are passed as array keys.
806 * @param array $args {
807 * Optional. An array of arguments.
808 *
809 * @type bool $fullset True to return the full set of data. False to return only the main data.
810 * @type bool $formatting Some of the data is returned formatted.
811 * }
812 */
813 $data = apply_filters( 'imagify_bulk_stats', $data, $types, $args );
814
815 /**
816 * Percentages.
817 */
818 if ( $data['total_attachments'] && $data['optimized_attachments'] ) {
819 $data['optimized_attachments_percent'] = round( 100 * $data['optimized_attachments'] / $data['total_attachments'] );
820 } else {
821 $data['optimized_attachments_percent'] = 0;
822 }
823
824 if ( $data['original_human'] && $data['optimized_human'] ) {
825 $data['optimized_percent'] = ceil( 100 - ( 100 * $data['optimized_human'] / $data['original_human'] ) );
826 } else {
827 $data['optimized_percent'] = 0;
828 }
829
830 /**
831 * Formating.
832 */
833 if ( $args['formatting'] ) {
834 $data['already_optimized_attachments'] = number_format_i18n( $data['already_optimized_attachments'] );
835 $data['original_human'] = imagify_size_format( $data['original_human'], 1 );
836 $data['optimized_human'] = imagify_size_format( $data['optimized_human'], 1 );
837 }
838
839 return $data;
840 }
841