PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / 2.0
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF v2.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.0, at classes/Bulk/WP.php

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