PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / 2.3.0
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF v2.3.0
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 / Bulk / WP.php

WP.php in Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF 2.3.0, at classes/Bulk/WP.php

421 lines 11.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Imagify\Bulk;
3
4 use Imagify_DB;
5
6 /**
7 * Class to use for bulk for WP attachments.
8 *
9 * @since 1.9
10 */
11 class WP extends AbstractBulk {
12 /**
13 * Context "short name".
14 *
15 * @var string
16 * @since 1.9
17 */
18 protected $context = 'wp';
19
20 /**
21 * Get all unoptimized media ids.
22 *
23 * @since 1.9
24 *
25 * @param int $optimization_level The optimization level.
26 *
27 * @return array A list of unoptimized media IDs.
28 */
29 public function get_unoptimized_media_ids( $optimization_level ) {
30 global $wpdb;
31
32 $this->set_no_time_limit();
33
34 $mime_types = Imagify_DB::get_mime_types();
35 $statuses = Imagify_DB::get_post_statuses();
36 $nodata_join = Imagify_DB::get_required_wp_metadata_join_clause();
37 $nodata_where = Imagify_DB::get_required_wp_metadata_where_clause(
38 [
39 'prepared' => true,
40 ]
41 );
42 $ids = $wpdb->get_col(
43 $wpdb->prepare( // WPCS: unprepared SQL ok.
44 "
45 SELECT DISTINCT p.ID
46 FROM $wpdb->posts AS p
47 $nodata_join
48 LEFT JOIN $wpdb->postmeta AS mt1
49 ON ( p.ID = mt1.post_id AND mt1.meta_key = '_imagify_status' )
50 LEFT JOIN $wpdb->postmeta AS mt2
51 ON ( p.ID = mt2.post_id AND mt2.meta_key = '_imagify_optimization_level' )
52 WHERE
53 p.post_mime_type IN ( $mime_types )
54 AND (
55 mt1.meta_value = 'error'
56 OR
57 mt2.meta_value != %d
58 OR
59 mt2.post_id IS NULL
60 )
61 AND p.post_type = 'attachment'
62 AND p.post_status IN ( $statuses )
63 $nodata_where
64 ORDER BY
65 CASE mt1.meta_value
66 WHEN 'already_optimized' THEN 2
67 ELSE 1
68 END ASC,
69 p.ID DESC
70 LIMIT 0, %d",
71 $optimization_level,
72 imagify_get_unoptimized_attachment_limit()
73 )
74 );
75
76 $wpdb->flush();
77 unset( $mime_types );
78 $ids = array_filter( array_map( 'absint', $ids ) );
79
80 if ( ! $ids ) {
81 return [];
82 }
83
84 $metas = Imagify_DB::get_metas(
85 [
86 // Get attachments filename.
87 'filenames' => '_wp_attached_file',
88 // Get attachments data.
89 'data' => '_imagify_data',
90 // Get attachments optimization level.
91 'optimization_levels' => '_imagify_optimization_level',
92 // Get attachments status.
93 'statuses' => '_imagify_status',
94 ],
95 $ids
96 );
97
98 // First run.
99 foreach ( $ids as $i => $id ) {
100 $attachment_status = isset( $metas['statuses'][ $id ] ) ? $metas['statuses'][ $id ] : false;
101 $attachment_optimization_level = isset( $metas['optimization_levels'][ $id ] ) ? $metas['optimization_levels'][ $id ] : false;
102 $attachment_error = '';
103
104 if ( isset( $metas['data'][ $id ]['sizes']['full']['error'] ) ) {
105 $attachment_error = $metas['data'][ $id ]['sizes']['full']['error'];
106 }
107
108 // Don't try to re-optimize if the optimization level is still the same.
109 if ( $optimization_level === $attachment_optimization_level && is_string( $attachment_error ) ) {
110 unset( $ids[ $i ] );
111 continue;
112 }
113
114 // Don't try to re-optimize images already compressed.
115 if ( 'already_optimized' === $attachment_status && $attachment_optimization_level >= $optimization_level ) {
116 unset( $ids[ $i ] );
117 continue;
118 }
119
120 $attachment_error = trim( $attachment_error );
121
122 // Don't try to re-optimize images with an empty error message.
123 if ( 'error' === $attachment_status && empty( $attachment_error ) ) {
124 unset( $ids[ $i ] );
125 }
126 }
127
128 if ( ! $ids ) {
129 return [];
130 }
131
132 $ids = array_values( $ids );
133
134 /**
135 * Fires before testing for file existence.
136 *
137 * @since 1.6.7
138 *
139 * @param array $ids An array of attachment IDs.
140 * @param array $metas An array of the data fetched from the database.
141 * @param int $optimization_level The optimization level that will be used for the optimization.
142 */
143 do_action( 'imagify_bulk_optimize_before_file_existence_tests', $ids, $metas, $optimization_level );
144
145 $data = [];
146
147 foreach ( $ids as $i => $id ) {
148 if ( empty( $metas['filenames'][ $id ] ) ) {
149 // Problem.
150 continue;
151 }
152
153 $file_path = get_imagify_attached_file( $metas['filenames'][ $id ] );
154
155 if ( ! $file_path || ! $this->filesystem->exists( $file_path ) ) {
156 continue;
157 }
158
159 $attachment_backup_path = get_imagify_attachment_backup_path( $file_path );
160 $attachment_status = isset( $metas['statuses'][ $id ] ) ? $metas['statuses'][ $id ] : false;
161 $attachment_optimization_level = isset( $metas['optimization_levels'][ $id ] ) ? $metas['optimization_levels'][ $id ] : false;
162
163 // Don't try to re-optimize if there is no backup file.
164 if ( 'success' === $attachment_status && $optimization_level !== $attachment_optimization_level && ! $this->filesystem->exists( $attachment_backup_path ) ) {
165 continue;
166 }
167
168 $data[] = $id;
169 }
170
171 return $data;
172 }
173
174 /**
175 * Get all optimized media IDs that have a backup file available for restore.
176 *
177 * @return array A list of media IDs.
178 */
179 public function get_optimized_media_ids(): array {
180 global $wpdb;
181
182 $this->set_no_time_limit();
183
184 $mime_types = Imagify_DB::get_mime_types();
185 $statuses = Imagify_DB::get_post_statuses();
186 $nodata_join = Imagify_DB::get_required_wp_metadata_join_clause();
187 $nodata_where = Imagify_DB::get_required_wp_metadata_where_clause(
188 [
189 'prepared' => true,
190 ]
191 );
192 $ids = $wpdb->get_col(
193 $wpdb->prepare( // WPCS: unprepared SQL ok.
194 "
195 SELECT DISTINCT p.ID
196 FROM $wpdb->posts AS p
197 $nodata_join
198 INNER JOIN $wpdb->postmeta AS mt1
199 ON ( p.ID = mt1.post_id AND mt1.meta_key = '_imagify_status' )
200 WHERE
201 p.post_mime_type IN ( $mime_types )
202 AND mt1.meta_value IN ( 'success', 'already_optimized' )
203 AND p.post_type = 'attachment'
204 AND p.post_status IN ( $statuses )
205 $nodata_where
206 ORDER BY p.ID DESC
207 LIMIT 0, %d",
208 imagify_get_unoptimized_attachment_limit()
209 )
210 );
211
212 $wpdb->flush();
213 unset( $mime_types, $statuses );
214 $ids = array_filter( array_map( 'absint', $ids ) );
215
216 if ( ! $ids ) {
217 return [];
218 }
219
220 $metas = Imagify_DB::get_metas(
221 [
222 // Get attachments filename.
223 'filenames' => '_wp_attached_file',
224 ],
225 $ids
226 );
227
228 $data = [];
229
230 foreach ( $ids as $id ) {
231 if ( empty( $metas['filenames'][ $id ] ) ) {
232 // Problem.
233 continue;
234 }
235
236 $file_path = get_imagify_attached_file( $metas['filenames'][ $id ] );
237
238 if ( ! $file_path ) {
239 continue;
240 }
241
242 $attachment_backup_path = get_imagify_attachment_backup_path( $file_path );
243
244 if ( ! $this->filesystem->exists( $attachment_backup_path ) ) {
245 // No backup, cannot restore.
246 continue;
247 }
248
249 $data[] = $id;
250 }
251
252 return $data;
253 }
254
255 /**
256 * Get ids of all optimized media without Next gen versions.
257 *
258 * @since 2.2
259 *
260 * @param string $format Format we are looking for. (webp|avif).
261 *
262 * @return array {
263 * @type array $ids A list of media IDs.
264 * @type array $errors {
265 * @type array $no_file_path A list of media IDs.
266 * @type array $no_backup A list of media IDs.
267 * }
268 * }
269 */
270 public function get_optimized_media_ids_without_format( $format ) {
271 global $wpdb;
272
273 $this->set_no_time_limit();
274
275 $mime_types = Imagify_DB::get_mime_types( 'image' );
276
277 // Remove single quotes and explode string into array.
278 $mime_types_array = explode( ',', str_replace( "'", '', $mime_types ) );
279
280 // Iterate over array and check if string contains input.
281 foreach ( $mime_types_array as $item ) {
282 if ( strpos( $item, $format ) !== false ) {
283 $mime = $item;
284 break;
285 }
286 }
287 if ( ! isset( $mime ) && empty( $mime ) ) {
288 $mime = 'image/webp';
289 }
290 $mime_types = str_replace( ",'" . $mime . "'", '', $mime_types );
291 $statuses = Imagify_DB::get_post_statuses();
292 $nodata_join = '';
293 $nodata_where = '';
294 if ( ! imagify_has_attachments_without_required_metadata() ) {
295 $nodata_join = Imagify_DB::get_required_wp_metadata_join_clause();
296 $nodata_where = Imagify_DB::get_required_wp_metadata_where_clause(
297 [
298 'prepared' => true,
299 ]
300 );
301 }
302
303 $nextgen_suffix = constant( imagify_get_optimization_process_class_name( 'wp' ) . '::' . strtoupper( $format ) . '_SUFFIX' );
304
305 $ids = $wpdb->get_col(
306 $wpdb->prepare( // WPCS: unprepared SQL ok.
307 "
308 SELECT p.ID
309 FROM $wpdb->posts AS p
310 $nodata_join
311 LEFT JOIN $wpdb->postmeta AS mt1
312 ON ( p.ID = mt1.post_id AND mt1.meta_key = '_imagify_status' )
313 LEFT JOIN $wpdb->postmeta AS mt2
314 ON ( p.ID = mt2.post_id AND mt2.meta_key = '_imagify_data' )
315 WHERE
316 p.post_mime_type IN ( $mime_types )
317 AND (mt1.meta_key IS NULL OR mt1.meta_value = 'success' OR mt1.meta_value = 'already_optimized' )
318 AND mt2.meta_value NOT LIKE %s
319 AND p.post_type = 'attachment'
320 AND p.post_status IN ( $statuses )
321 $nodata_where
322 ORDER BY p.ID DESC
323 LIMIT 0, %d",
324 '%' . $wpdb->esc_like( $nextgen_suffix . '";a:4:{s:7:"success";b:1;' ) . '%',
325 imagify_get_unoptimized_attachment_limit()
326 )
327 );
328
329 $wpdb->flush();
330 unset( $mime_types, $statuses, $nextgen_suffix, $mime );
331
332 $ids = array_filter( array_map( 'absint', $ids ) );
333
334 $data = [
335 'ids' => [],
336 'errors' => [
337 'no_file_path' => [],
338 'no_backup' => [],
339 ],
340 ];
341
342 if ( ! $ids ) {
343 return $data;
344 }
345
346 $metas = Imagify_DB::get_metas(
347 [
348 // Get attachments filename.
349 'filenames' => '_wp_attached_file',
350 ],
351 $ids
352 );
353
354 /**
355 * Fires before testing for file existence.
356 *
357 * @since 1.9
358 *
359 * @param array $ids An array of attachment IDs.
360 * @param array $metas An array of the data fetched from the database.
361 * @param string $context The context.
362 */
363 do_action( 'imagify_bulk_generate_nextgen_before_file_existence_tests', $ids, $metas, 'wp' );
364
365 foreach ( $ids as $i => $id ) {
366 if ( empty( $metas['filenames'][ $id ] ) ) {
367 // Problem. Should not happen, thanks to the wpdb query.
368 $data['errors']['no_file_path'][] = $id;
369 continue;
370 }
371
372 $file_path = get_imagify_attached_file( $metas['filenames'][ $id ] );
373
374 if ( ! $file_path ) {
375 // Main file not found.
376 $data['errors']['no_file_path'][] = $id;
377 continue;
378 }
379
380 $backup_path = get_imagify_attachment_backup_path( $file_path );
381
382 if ( ! $this->filesystem->exists( $backup_path ) ) {
383 // No backup, no WebP.
384 $data['errors']['no_backup'][] = $id;
385 continue;
386 }
387
388 $data['ids'][] = $id;
389 }
390
391 return $data;
392 }
393
394 /**
395 * Get the context data.
396 *
397 * @since 1.9
398 *
399 * @return array {
400 * The formated data.
401 *
402 * @type string $count-optimized Number of media optimized.
403 * @type string $count-errors Number of media having an optimization error, with a link to the page listing the optimization errors.
404 * @type string $optimized-size Optimized filesize.
405 * @type string $original-size Original filesize.
406 * }
407 */
408 public function get_context_data() {
409 $total_saving_data = imagify_count_saving_data();
410 $data = [
411 'count-optimized' => imagify_count_optimized_attachments(),
412 'count-errors' => imagify_count_error_attachments(),
413 'optimized-size' => $total_saving_data['optimized_size'],
414 'original-size' => $total_saving_data['original_size'],
415 'errors_url' => get_imagify_admin_url( 'folder-errors', $this->context ),
416 ];
417
418 return $this->format_context_data( $data );
419 }
420 }
421