PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / trunk
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF vtrunk
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 / CustomFolders.php

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

276 lines 7.2 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_Custom_Folders;
5 use Imagify_Files_Scan;
6 use Imagify_Files_DB;
7 use Imagify_Folders_DB;
8 use Imagify_DB;
9 use Imagify_Files_Stats;
10
11 /**
12 * Class to use for bulk for custom folders.
13 *
14 * @since 1.9
15 */
16 class CustomFolders extends AbstractBulk {
17 /**
18 * Context "short name".
19 *
20 * @var string
21 * @since 1.9
22 */
23 protected $context = 'custom-folders';
24
25 /**
26 * Get all unoptimized media ids.
27 *
28 * @since 1.9
29 *
30 * @param int $optimization_level The optimization level.
31 *
32 * @return array A list of unoptimized media IDs.
33 */
34 public function get_unoptimized_media_ids( $optimization_level ) {
35 $this->set_no_time_limit();
36
37 /**
38 * Get the folders from DB.
39 */
40 $folders = Imagify_Custom_Folders::get_folders(
41 [
42 'active' => true,
43 ]
44 );
45
46 if ( ! $folders ) {
47 return [];
48 }
49
50 /**
51 * Fires before getting file IDs.
52 *
53 * @since 1.7
54 *
55 * @param array $folders An array of folders data.
56 * @param int $optimization_level The optimization level that will be used for the optimization.
57 */
58 do_action( 'imagify_bulk_optimize_files_before_get_files', $folders, $optimization_level );
59
60 /**
61 * Get the files from DB, and from the folders.
62 */
63 $files = Imagify_Custom_Folders::get_files_from_folders(
64 $folders,
65 [
66 'optimization_level' => $optimization_level,
67 ]
68 );
69
70 if ( ! $files ) {
71 return [];
72 }
73
74 foreach ( $files as $k => $file ) {
75 $files[ $k ] = $file['file_id'];
76 }
77
78 return $files;
79 }
80
81 /**
82 * Get all optimized file IDs that have a backup file available for restore.
83 *
84 * @return array A list of file IDs.
85 */
86 public function get_optimized_media_ids(): array {
87 global $wpdb;
88
89 $this->set_no_time_limit();
90
91 $files_table = Imagify_Files_DB::get_instance()->get_table_name();
92 $folders_table = Imagify_Folders_DB::get_instance()->get_table_name();
93 $files = $wpdb->get_results(
94 $wpdb->prepare( // WPCS: unprepared SQL ok.
95 "
96 SELECT fi.file_id, fi.path
97 FROM $files_table AS fi
98 INNER JOIN $folders_table AS fo
99 ON ( fi.folder_id = fo.folder_id )
100 WHERE
101 fi.status IN ( 'success', 'already_optimized' )
102 ORDER BY fi.file_id DESC
103 LIMIT 0, %d",
104 imagify_get_unoptimized_attachment_limit()
105 )
106 );
107
108 $wpdb->flush();
109 unset( $files_table, $folders_table );
110
111 if ( ! $files ) {
112 return [];
113 }
114
115 $data = [];
116
117 foreach ( $files as $file ) {
118 $file_id = absint( $file->file_id );
119
120 if ( empty( $file->path ) ) {
121 // Problem.
122 continue;
123 }
124
125 $file_path = Imagify_Files_Scan::remove_placeholder( $file->path );
126 $backup_path = Imagify_Custom_Folders::get_file_backup_path( $file_path );
127
128 if ( ! $this->filesystem->exists( $backup_path ) ) {
129 // No backup, cannot restore.
130 continue;
131 }
132
133 $data[] = $file_id;
134 }
135
136 return $data;
137 }
138
139 /**
140 * Get ids of all optimized media without Next gen versions.
141 *
142 * @since 2.2
143 *
144 * @param string $format Format we are looking for. (webp|avif).
145 *
146 * @return array {
147 * @type array $ids A list of media IDs.
148 * @type array $errors {
149 * @type array $no_file_path A list of media IDs.
150 * @type array $no_backup A list of media IDs.
151 * }
152 * }
153 */
154 public function get_optimized_media_ids_without_format( $format ) {
155 global $wpdb;
156
157 $this->set_no_time_limit();
158
159 $files_table = Imagify_Files_DB::get_instance()->get_table_name();
160 $folders_table = Imagify_Folders_DB::get_instance()->get_table_name();
161 $mime_types = Imagify_DB::get_mime_types( 'image' );
162 // Remove single quotes and explode string into array.
163 $mime_types_array = explode( ',', str_replace( "'", '', $mime_types ) );
164
165 // Iterate over array and check if string contains input.
166 foreach ( $mime_types_array as $item ) {
167 if ( strpos( $item, $format ) !== false ) {
168 $mime = $item;
169 break;
170 }
171 }
172 if ( ! isset( $mime ) && empty( $mime ) ) {
173 $mime = 'image/webp';
174 }
175 $mime = trim( $mime );
176 $mime_types = str_replace( [ ", '" . $mime . "'", ",'" . $mime . "'" ], '', $mime_types );
177 $nextgen_suffix = constant( imagify_get_optimization_process_class_name( 'custom-folders' ) . '::' . strtoupper( $format ) . '_SUFFIX' );
178 $files = $wpdb->get_results(
179 $wpdb->prepare( // WPCS: unprepared SQL ok.
180 "
181 SELECT fi.file_id, fi.path
182 FROM $files_table as fi
183 INNER JOIN $folders_table AS fo
184 ON ( fi.folder_id = fo.folder_id AND fo.active = 1 )
185 WHERE
186 fi.mime_type IN ( $mime_types )
187 AND ( fi.status = 'success' OR fi.status = 'already_optimized' )
188 AND fi.data NOT LIKE %s
189 AND fi.data NOT LIKE %s
190 ORDER BY fi.file_id DESC",
191 '%' . $wpdb->esc_like( $nextgen_suffix . '";a:4:{s:7:"success";b:1;' ) . '%',
192 /**
193 * Second predicate: skip files the API permanently refused to convert (the next-gen file
194 * would be heavier than the original, or the file is already compressed). Those are stored
195 * as `<size><suffix>";a:3:{s:15:"permanent_error";b:1;s:7:"success";b:0;s:5:"error";…`.
196 * Transient failures serialize as a 2-element array without the `permanent_error` key, so
197 * they keep being retried. Matching serialized data with LIKE is fragile: the key order
198 * written in Optimization\Data\CustomFolders must not change.
199 */
200 '%' . $wpdb->esc_like( $nextgen_suffix . '";a:3:{s:15:"permanent_error";b:1;' ) . '%'
201 )
202 );
203
204 $wpdb->flush();
205 unset( $mime_types, $files_table, $folders_table, $nextgen_suffix, $mime );
206
207 $data = [
208 'ids' => [],
209 'errors' => [
210 'no_file_path' => [],
211 'no_backup' => [],
212 ],
213 ];
214
215 if ( ! $files ) {
216 return $data;
217 }
218
219 foreach ( $files as $file ) {
220 $file_id = absint( $file->file_id );
221
222 if ( empty( $file->path ) ) {
223 // Problem.
224 $data['errors']['no_file_path'][] = $file_id;
225 continue;
226 }
227
228 $file_path = Imagify_Files_Scan::remove_placeholder( $file->path );
229
230 // Skip files whose extension already matches the target format
231 // (e.g. a .webp file stored with incorrect post_mime_type).
232 if ( strtolower( pathinfo( $file_path, PATHINFO_EXTENSION ) ) === $format ) {
233 continue;
234 }
235
236 $backup_path = Imagify_Custom_Folders::get_file_backup_path( $file_path );
237
238 if ( ! $this->filesystem->exists( $backup_path ) ) {
239 // No backup, no WebP.
240 $data['errors']['no_backup'][] = $file_id;
241 continue;
242 }
243
244 $data['ids'][] = $file_id;
245 }
246
247 return $data;
248 }
249
250 /**
251 * Get the context data.
252 *
253 * @since 1.9
254 *
255 * @return array {
256 * The formated data.
257 *
258 * @type string $count-optimized Number of media optimized.
259 * @type string $count-errors Number of media having an optimization error, with a link to the page listing the optimization errors.
260 * @type string $optimized-size Optimized filesize.
261 * @type string $original-size Original filesize.
262 * }
263 */
264 public function get_context_data() {
265 $data = [
266 'count-optimized' => Imagify_Files_Stats::count_optimized_files(),
267 'count-errors' => Imagify_Files_Stats::count_error_files(),
268 'optimized-size' => Imagify_Files_Stats::get_optimized_size(),
269 'original-size' => Imagify_Files_Stats::get_original_size(),
270 'errors_url' => get_imagify_admin_url( 'folder-errors', $this->context ),
271 ];
272
273 return $this->format_context_data( $data );
274 }
275 }
276