1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
|
<?php namespace Imagify\Bulk;
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
/** * Class to use for bulk for WP attachments. * * @since 1.9 * @author Grégory Viguier */ class WP extends AbstractBulk {
/** * Context "short name". * * @var string * @since 1.9 * @access protected * @author Grégory Viguier */ protected $context = 'wp';
/** * Get all unoptimized media ids. * * @since 1.9 * @access public * @author Grégory Viguier * * @param int $optimization_level The optimization level. * @return array A list of unoptimized media. Array keys are media IDs prefixed with an underscore character, array values are the main file’s URL. */ public function get_unoptimized_media_ids( $optimization_level ) { global $wpdb;
@set_time_limit( 0 );
$mime_types = \Imagify_DB::get_mime_types(); $statuses = \Imagify_DB::get_post_statuses(); $nodata_join = \Imagify_DB::get_required_wp_metadata_join_clause(); $nodata_where = \Imagify_DB::get_required_wp_metadata_where_clause( [ 'prepared' => true, ] ); $ids = $wpdb->get_col( $wpdb->prepare( // WPCS: unprepared SQL ok. " SELECT DISTINCT p.ID FROM $wpdb->posts AS p $nodata_join LEFT JOIN $wpdb->postmeta AS mt1 ON ( p.ID = mt1.post_id AND mt1.meta_key = '_imagify_status' ) LEFT JOIN $wpdb->postmeta AS mt2 ON ( p.ID = mt2.post_id AND mt2.meta_key = '_imagify_optimization_level' ) WHERE p.post_mime_type IN ( $mime_types ) AND ( mt1.meta_value = 'error' OR mt2.meta_value != %d OR mt2.post_id IS NULL ) AND p.post_type = 'attachment' AND p.post_status IN ( $statuses ) $nodata_where ORDER BY CASE mt1.meta_value WHEN 'already_optimized' THEN 2 ELSE 1 END ASC, p.ID DESC LIMIT 0, %d", $optimization_level, imagify_get_unoptimized_attachment_limit() ) );
$wpdb->flush(); unset( $mime_types ); $ids = array_filter( array_map( 'absint', $ids ) );
if ( ! $ids ) { return []; }
$metas = \Imagify_DB::get_metas( [ // Get attachments filename. 'filenames' => '_wp_attached_file', // Get attachments data. 'data' => '_imagify_data', // Get attachments optimization level. 'optimization_levels' => '_imagify_optimization_level', // Get attachments status. 'statuses' => '_imagify_status', ], $ids );
// First run. foreach ( $ids as $i => $id ) { $attachment_status = isset( $metas['statuses'][ $id ] ) ? $metas['statuses'][ $id ] : false; $attachment_optimization_level = isset( $metas['optimization_levels'][ $id ] ) ? $metas['optimization_levels'][ $id ] : false; $attachment_error = '';
if ( isset( $metas['data'][ $id ]['sizes']['full']['error'] ) ) { $attachment_error = $metas['data'][ $id ]['sizes']['full']['error']; }
// Don't try to re-optimize if the optimization level is still the same. if ( $optimization_level === $attachment_optimization_level && is_string( $attachment_error ) ) { unset( $ids[ $i ] ); continue; }
// Don't try to re-optimize images already compressed. if ( 'already_optimized' === $attachment_status && $attachment_optimization_level >= $optimization_level ) { unset( $ids[ $i ] ); continue; }
$attachment_error = trim( $attachment_error );
// Don't try to re-optimize images with an empty error message. if ( 'error' === $attachment_status && empty( $attachment_error ) ) { unset( $ids[ $i ] ); } }
if ( ! $ids ) { return []; }
$ids = array_values( $ids );
/** * Triggered before testing for file existence. * * @since 1.6.7 * @author Grégory Viguier * * @param array $ids An array of attachment IDs. * @param array $metas An array of the data fetched from the database. * @param int $optimization_level The optimization level that will be used for the optimization. */ do_action( 'imagify_bulk_optimize_before_file_existence_tests', $ids, $metas, $optimization_level );
$data = [];
foreach ( $ids as $i => $id ) { if ( empty( $metas['filenames'][ $id ] ) ) { // Problem. continue; }
$file_path = get_imagify_attached_file( $metas['filenames'][ $id ] );
if ( ! $file_path || ! $this->filesystem->exists( $file_path ) ) { continue; }
$attachment_backup_path = get_imagify_attachment_backup_path( $file_path ); $attachment_status = isset( $metas['statuses'][ $id ] ) ? $metas['statuses'][ $id ] : false; $attachment_optimization_level = isset( $metas['optimization_levels'][ $id ] ) ? $metas['optimization_levels'][ $id ] : false;
// Don't try to re-optimize if there is no backup file. if ( 'success' === $attachment_status && $optimization_level !== $attachment_optimization_level && ! $this->filesystem->exists( $attachment_backup_path ) ) { continue; }
$data[ '_' . $id ] = esc_url( get_imagify_attachment_url( $metas['filenames'][ $id ] ) ); } // End foreach().
return $data; }
/** * Get ids of all optimized media without webp versions. * * @since 1.9 * @since 1.9.5 The method doesn't return the IDs directly anymore. * @access public * @author Grégory Viguier * * @return array { * @type array $ids A list of media IDs. * @type array $errors { * @type array $no_file_path A list of media IDs. * @type array $no_backup A list of media IDs. * } * } */ public function get_optimized_media_ids_without_webp() { global $wpdb;
@set_time_limit( 0 );
$mime_types = \Imagify_DB::get_mime_types( 'image' ); $statuses = \Imagify_DB::get_post_statuses(); $nodata_join = \Imagify_DB::get_required_wp_metadata_join_clause(); $nodata_where = \Imagify_DB::get_required_wp_metadata_where_clause( [ 'prepared' => true, ] ); $webp_suffix = constant( imagify_get_optimization_process_class_name( 'wp' ) . '::WEBP_SUFFIX' ); $ids = $wpdb->get_col( $wpdb->prepare( // WPCS: unprepared SQL ok. " SELECT p.ID FROM $wpdb->posts AS p $nodata_join LEFT JOIN $wpdb->postmeta AS mt1 ON ( p.ID = mt1.post_id AND mt1.meta_key = '_imagify_status' ) LEFT JOIN $wpdb->postmeta AS mt2 ON ( p.ID = mt2.post_id AND mt2.meta_key = '_imagify_data' ) WHERE p.post_mime_type IN ( $mime_types ) AND ( mt1.meta_value = 'success' OR mt1.meta_value = 'already_optimized' ) AND mt2.meta_value NOT LIKE %s AND p.post_type = 'attachment' AND p.post_status IN ( $statuses ) $nodata_where ORDER BY p.ID DESC LIMIT 0, %d", '%' . $wpdb->esc_like( $webp_suffix . '";a:4:{s:7:"success";b:1;' ) . '%', imagify_get_unoptimized_attachment_limit() ) );
$wpdb->flush(); unset( $mime_types, $statuses, $webp_suffix );
$ids = array_filter( array_map( 'absint', $ids ) ); $data = [ 'ids' => [], 'errors' => [ 'no_file_path' => [], 'no_backup' => [], ], ];
if ( ! $ids ) { return $data; }
$metas = \Imagify_DB::get_metas( [ // Get attachments filename. 'filenames' => '_wp_attached_file', ], $ids );
/** * Triggered before testing for file existence. * * @since 1.9 * @author Grégory Viguier * * @param array $ids An array of attachment IDs. * @param array $metas An array of the data fetched from the database. * @param string $context The context. */ do_action( 'imagify_bulk_generate_webp_before_file_existence_tests', $ids, $metas, 'wp' );
foreach ( $ids as $i => $id ) { if ( empty( $metas['filenames'][ $id ] ) ) { // Problem. Should not happen, thanks to the wpdb query. $data['errors']['no_file_path'][] = $id; continue; }
$file_path = get_imagify_attached_file( $metas['filenames'][ $id ] );
if ( ! $file_path ) { // Main file not found. $data['errors']['no_file_path'][] = $id; continue; }
$backup_path = get_imagify_attachment_backup_path( $file_path );
if ( ! $this->filesystem->exists( $backup_path ) ) { // No backup, no webp. $data['errors']['no_backup'][] = $id; continue; }
$data['ids'][] = $id; } // End foreach().
return $data; }
/** * Tell if there are optimized media without webp versions. * * @since 1.9 * @access public * @author Grégory Viguier * * @return int The number of media. */ public function has_optimized_media_without_webp() { global $wpdb;
$mime_types = \Imagify_DB::get_mime_types( 'image' ); $statuses = \Imagify_DB::get_post_statuses(); $nodata_join = \Imagify_DB::get_required_wp_metadata_join_clause(); $nodata_where = \Imagify_DB::get_required_wp_metadata_where_clause( [ 'prepared' => true, ] ); $webp_suffix = constant( imagify_get_optimization_process_class_name( 'wp' ) . '::WEBP_SUFFIX' );
return (int) $wpdb->get_var( $wpdb->prepare( // WPCS: unprepared SQL ok. " SELECT COUNT(p.ID) FROM $wpdb->posts AS p $nodata_join LEFT JOIN $wpdb->postmeta AS mt1 ON ( p.ID = mt1.post_id AND mt1.meta_key = '_imagify_status' ) LEFT JOIN $wpdb->postmeta AS mt2 ON ( p.ID = mt2.post_id AND mt2.meta_key = '_imagify_data' ) WHERE p.post_mime_type IN ( $mime_types ) AND ( mt1.meta_value = 'success' OR mt1.meta_value = 'already_optimized' ) AND mt2.meta_value NOT LIKE %s AND p.post_type = 'attachment' AND p.post_status IN ( $statuses ) $nodata_where", '%' . $wpdb->esc_like( $webp_suffix . '";a:4:{s:7:"success";b:1;' ) . '%' ) ); }
/** * Get the context data. * * @since 1.9 * @access public * @author Grégory Viguier * * @return array { * The formated data. * * @type string $count-optimized Number of media optimized. * @type string $count-errors Number of media having an optimization error, with a link to the page listing the optimization errors. * @type string $optimized-size Optimized filesize. * @type string $original-size Original filesize. * } */ public function get_context_data() { $total_saving_data = imagify_count_saving_data(); $data = [ 'count-optimized' => imagify_count_optimized_attachments(), 'count-errors' => imagify_count_error_attachments(), 'optimized-size' => $total_saving_data['optimized_size'], 'original-size' => $total_saving_data['original_size'], 'errors_url' => get_imagify_admin_url( 'folder-errors', $this->context ), ];
return $this->format_context_data( $data ); } }
|