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

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

321 lines 8.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Imagify\Optimization\Data;
3
4 defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
5
6 /**
7 * Optimization data class for the custom folders.
8 * This class constructor accepts:
9 * - A media ID (int).
10 * - An array of data coming from the files DB table /!\
11 * - An object of data coming from the files DB table /!\
12 * - A \Imagify\Media\MediaInterface object.
13 *
14 * @since 1.9
15 * @see Imagify\Media\CustomFolders
16 * @author Grégory Viguier
17 */
18 class CustomFolders extends AbstractData {
19 use \Imagify\Traits\MediaRowTrait;
20
21 /**
22 * The attachment SQL DB class.
23 *
24 * @var string
25 * @since 1.9
26 * @access protected
27 * @author Grégory Viguier
28 */
29 protected $db_class_name = 'Imagify_Files_DB';
30
31 /**
32 * The constructor.
33 *
34 * @since 1.9
35 * @access public
36 * @author Grégory Viguier
37 *
38 * @param mixed $id An ID, or whatever type the "Media" class constructor accepts.
39 */
40 public function __construct( $id ) {
41 parent::__construct( $id );
42
43 if ( ! $this->is_valid() ) {
44 return;
45 }
46
47 // This is required by MediaRowTrait.
48 $this->id = $this->get_media()->get_id();
49
50 // In this context, the media data and the optimization data are stored in the same DB table, so, no need to request twice the DB.
51 $this->row = $this->get_media()->get_row();
52 }
53
54 /**
55 * Get the whole media optimization data.
56 *
57 * @since 1.9
58 * @access public
59 * @author Grégory Viguier
60 *
61 * @return array The data. See parent method for details.
62 */
63 public function get_optimization_data() {
64 if ( ! $this->is_valid() ) {
65 return $this->default_optimization_data;
66 }
67
68 $row = array_merge( $this->get_row_db_instance()->get_column_defaults(), $this->get_row() );
69 $data = $this->default_optimization_data;
70
71 $data['status'] = $row['status'];
72 $data['level'] = $row['optimization_level'];
73 $data['level'] = is_numeric( $data['level'] ) ? (int) $data['level'] : false;
74
75 if ( 'success' === $row['status'] ) {
76 /**
77 * Success.
78 */
79 $data['sizes']['full'] = [
80 'success' => true,
81 'original_size' => $row['original_size'],
82 'optimized_size' => $row['optimized_size'],
83 'percent' => $row['percent'],
84 ];
85 } elseif ( ! empty( $row['status'] ) ) {
86 /**
87 * Error.
88 */
89 $data['sizes']['full'] = [
90 'success' => false,
91 'error' => $row['error'],
92 ];
93 }
94
95 if ( ! empty( $row['data']['sizes'] ) && is_array( $row['data']['sizes'] ) ) {
96 unset( $row['data']['sizes']['full'] );
97 $data['sizes'] = array_merge( $data['sizes'], $row['data']['sizes'] );
98 $data['sizes'] = array_filter( $data['sizes'], 'is_array' );
99 }
100
101 if ( empty( $data['sizes'] ) ) {
102 return $data;
103 }
104
105 foreach ( $data['sizes'] as $size_data ) {
106 // Cast.
107 if ( isset( $size_data['original_size'] ) ) {
108 $size_data['original_size'] = (int) $size_data['original_size'];
109 }
110 if ( isset( $size_data['optimized_size'] ) ) {
111 $size_data['optimized_size'] = (int) $size_data['optimized_size'];
112 }
113 if ( isset( $size_data['percent'] ) ) {
114 $size_data['percent'] = round( $size_data['percent'], 2 );
115 }
116 // Stats.
117 if ( ! empty( $size_data['original_size'] ) && ! empty( $size_data['optimized_size'] ) ) {
118 $data['stats']['original_size'] += $size_data['original_size'];
119 $data['stats']['optimized_size'] += $size_data['optimized_size'];
120 }
121 }
122
123 if ( $data['stats']['original_size'] && $data['stats']['optimized_size'] ) {
124 $data['stats']['percent'] = $data['stats']['original_size'] - $data['stats']['optimized_size'];
125 $data['stats']['percent'] = round( $data['stats']['percent'] / $data['stats']['original_size'] * 100, 2 );
126 }
127
128 return $data;
129 }
130
131 /**
132 * Update the optimization data, level, and status for a size.
133 *
134 * @since 1.9
135 * @access public
136 * @author Grégory Viguier
137 *
138 * @param string $size The size name.
139 * @param array $data The optimization data. See parent method for details.
140 */
141 public function update_size_optimization_data( $size, array $data ) {
142 if ( ! $this->is_valid() ) {
143 return;
144 }
145
146 $old_data = array_merge( $this->get_reset_data(), $this->get_row() );
147
148 if ( 'full' === $size ) {
149 /**
150 * Original file.
151 */
152 $old_data['optimization_level'] = $data['level'];
153 $old_data['status'] = $data['status'];
154 $old_data['modified'] = 0;
155
156 $file_path = $this->get_media()->get_fullsize_path();
157
158 if ( $file_path ) {
159 $old_data['hash'] = md5_file( $file_path );
160 }
161
162 if ( key_exists( 'message', $data ) ) {
163 $old_data['message'] = $data['message'];
164 }
165
166 if ( ! $data['success'] ) {
167 /**
168 * Error.
169 */
170 $old_data['error'] = $data['error'];
171 } else {
172 /**
173 * Success.
174 */
175 $old_data['original_size'] = $data['original_size'];
176 $old_data['optimized_size'] = $data['optimized_size'];
177 $old_data['percent'] = $data['original_size'] - $data['optimized_size'];
178 $old_data['percent'] = round( ( $old_data['percent'] / $data['original_size'] ) * 100, 2 );
179 }
180 } else {
181 /**
182 * WebP version or any other size.
183 */
184 $old_data['data'] = ! empty( $old_data['data'] ) && is_array( $old_data['data'] ) ? $old_data['data'] : [];
185 $old_data['data']['sizes'] = ! empty( $old_data['data']['sizes'] ) && is_array( $old_data['data']['sizes'] ) ? $old_data['data']['sizes'] : [];
186
187 if ( ! $data['success'] ) {
188 /**
189 * Error.
190 */
191 $old_data['data']['sizes'][ $size ] = [
192 'success' => false,
193 'error' => $data['error'],
194 ];
195 } else {
196 /**
197 * Success.
198 */
199 $old_data['data']['sizes'][ $size ] = [
200 'success' => true,
201 'original_size' => $data['original_size'],
202 'optimized_size' => $data['optimized_size'],
203 'percent' => round( ( ( $data['original_size'] - $data['optimized_size'] ) / $data['original_size'] ) * 100, 2 ),
204 ];
205 }
206 }
207
208 if ( isset( $old_data['data']['sizes'] ) && ( ! $old_data['data']['sizes'] || ! is_array( $old_data['data']['sizes'] ) ) ) {
209 unset( $old_data['data']['sizes'] );
210 }
211
212 $this->update_row( $old_data );
213 }
214
215 /**
216 * Delete the media optimization data, level, and status.
217 *
218 * @since 1.9
219 * @access public
220 * @author Grégory Viguier
221 */
222 public function delete_optimization_data() {
223 if ( ! $this->is_valid() ) {
224 return;
225 }
226
227 $this->update_row( $this->get_reset_data() );
228 }
229
230 /**
231 * Delete the optimization data for the given sizes.
232 * If all sizes are removed, all optimization data is deleted.
233 * Status and level are not modified nor removed if the "full" size is removed. This leaves the media in a Schrödinger state.
234 *
235 * @since 1.9.8
236 * @access public
237 * @author Grégory Viguier
238 *
239 * @param array $sizes A list of sizes to remove.
240 */
241 public function delete_sizes_optimization_data( array $sizes ) {
242 if ( ! $sizes || ! $this->is_valid() ) {
243 return;
244 }
245
246 $data = array_merge( $this->get_reset_data(), $this->get_row() );
247
248 $data['data']['sizes'] = ! empty( $data['data']['sizes'] ) && is_array( $data['data']['sizes'] ) ? $data['data']['sizes'] : [];
249
250 if ( ! $data['data']['sizes'] ) {
251 return;
252 }
253
254 $remaining_sizes_data = array_diff_key( $data['data']['sizes'], array_flip( $sizes ) );
255
256 if ( ! $remaining_sizes_data ) {
257 // All sizes have been removed: delete everything.
258 $this->delete_optimization_data();
259 return;
260 }
261
262 if ( count( $remaining_sizes_data ) === count( $data['data']['sizes'] ) ) {
263 // Nothing has been removed.
264 return;
265 }
266
267 $data['data']['sizes'] = $remaining_sizes_data;
268
269 $this->update_row( $data );
270 }
271
272 /**
273 * Get default values used to reset optimization data.
274 *
275 * @since 1.9
276 * @access protected
277 * @author Grégory Viguier
278 *
279 * @return array {
280 * The default values related to the optimization.
281 *
282 * @type string $hash The file hash.
283 * @type int $modified 0 to tell that the file has not been modified
284 * @type int $optimized_size File size after optimization.
285 * @type int $percent Saving optimized/original in percent.
286 * @type int $optimization_level The optimization level.
287 * @type string $status The status: success, already_optimized, error.
288 * @type string $error An error message.
289 * }
290 */
291 protected function get_reset_data() {
292 static $column_defaults;
293
294 if ( ! isset( $column_defaults ) ) {
295 $column_defaults = $this->get_row_db_instance()->get_column_defaults();
296
297 // All DB columns that have `null` as default value, are Imagify data.
298 foreach ( $column_defaults as $column_name => $value ) {
299 if ( 'hash' === $column_name || 'modified' === $column_name || 'data' === $column_name ) {
300 continue;
301 }
302
303 if ( isset( $value ) ) {
304 unset( $column_defaults[ $column_name ] );
305 }
306 }
307 }
308
309 $imagify_columns = $column_defaults;
310
311 // Also set the new file hash.
312 $file_path = $this->get_media()->get_fullsize_path();
313
314 if ( $file_path ) {
315 $imagify_columns['hash'] = md5_file( $file_path );
316 }
317
318 return $imagify_columns;
319 }
320 }
321