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 / Optimization / Data / CustomFolders.php

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

317 lines 8.7 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 ( ! $data['success'] ) {
163 /**
164 * Error.
165 */
166 $old_data['error'] = $data['error'];
167 } else {
168 /**
169 * Success.
170 */
171 $old_data['original_size'] = $data['original_size'];
172 $old_data['optimized_size'] = $data['optimized_size'];
173 $old_data['percent'] = $data['original_size'] - $data['optimized_size'];
174 $old_data['percent'] = round( ( $old_data['percent'] / $data['original_size'] ) * 100, 2 );
175 }
176 } else {
177 /**
178 * WebP version or any other size.
179 */
180 $old_data['data'] = ! empty( $old_data['data'] ) && is_array( $old_data['data'] ) ? $old_data['data'] : [];
181 $old_data['data']['sizes'] = ! empty( $old_data['data']['sizes'] ) && is_array( $old_data['data']['sizes'] ) ? $old_data['data']['sizes'] : [];
182
183 if ( ! $data['success'] ) {
184 /**
185 * Error.
186 */
187 $old_data['data']['sizes'][ $size ] = [
188 'success' => false,
189 'error' => $data['error'],
190 ];
191 } else {
192 /**
193 * Success.
194 */
195 $old_data['data']['sizes'][ $size ] = [
196 'success' => true,
197 'original_size' => $data['original_size'],
198 'optimized_size' => $data['optimized_size'],
199 'percent' => round( ( ( $data['original_size'] - $data['optimized_size'] ) / $data['original_size'] ) * 100, 2 ),
200 ];
201 }
202 }
203
204 if ( isset( $old_data['data']['sizes'] ) && ( ! $old_data['data']['sizes'] || ! is_array( $old_data['data']['sizes'] ) ) ) {
205 unset( $old_data['data']['sizes'] );
206 }
207
208 $this->update_row( $old_data );
209 }
210
211 /**
212 * Delete the media optimization data, level, and status.
213 *
214 * @since 1.9
215 * @access public
216 * @author Grégory Viguier
217 */
218 public function delete_optimization_data() {
219 if ( ! $this->is_valid() ) {
220 return;
221 }
222
223 $this->update_row( $this->get_reset_data() );
224 }
225
226 /**
227 * Delete the optimization data for the given sizes.
228 * If all sizes are removed, all optimization data is deleted.
229 * Status and level are not modified nor removed if the "full" size is removed. This leaves the media in a Schrödinger state.
230 *
231 * @since 1.9.8
232 * @access public
233 * @author Grégory Viguier
234 *
235 * @param array $sizes A list of sizes to remove.
236 */
237 public function delete_sizes_optimization_data( array $sizes ) {
238 if ( ! $sizes || ! $this->is_valid() ) {
239 return;
240 }
241
242 $data = array_merge( $this->get_reset_data(), $this->get_row() );
243
244 $data['data']['sizes'] = ! empty( $data['data']['sizes'] ) && is_array( $data['data']['sizes'] ) ? $data['data']['sizes'] : [];
245
246 if ( ! $data['data']['sizes'] ) {
247 return;
248 }
249
250 $remaining_sizes_data = array_diff_key( $data['data']['sizes'], array_flip( $sizes ) );
251
252 if ( ! $remaining_sizes_data ) {
253 // All sizes have been removed: delete everything.
254 $this->delete_optimization_data();
255 return;
256 }
257
258 if ( count( $remaining_sizes_data ) === count( $data['data']['sizes'] ) ) {
259 // Nothing has been removed.
260 return;
261 }
262
263 $data['data']['sizes'] = $remaining_sizes_data;
264
265 $this->update_row( $data );
266 }
267
268 /**
269 * Get default values used to reset optimization data.
270 *
271 * @since 1.9
272 * @access protected
273 * @author Grégory Viguier
274 *
275 * @return array {
276 * The default values related to the optimization.
277 *
278 * @type string $hash The file hash.
279 * @type int $modified 0 to tell that the file has not been modified
280 * @type int $optimized_size File size after optimization.
281 * @type int $percent Saving optimized/original in percent.
282 * @type int $optimization_level The optimization level.
283 * @type string $status The status: success, already_optimized, error.
284 * @type string $error An error message.
285 * }
286 */
287 protected function get_reset_data() {
288 static $column_defaults;
289
290 if ( ! isset( $column_defaults ) ) {
291 $column_defaults = $this->get_row_db_instance()->get_column_defaults();
292
293 // All DB columns that have `null` as default value, are Imagify data.
294 foreach ( $column_defaults as $column_name => $value ) {
295 if ( 'hash' === $column_name || 'modified' === $column_name || 'data' === $column_name ) {
296 continue;
297 }
298
299 if ( isset( $value ) ) {
300 unset( $column_defaults[ $column_name ] );
301 }
302 }
303 }
304
305 $imagify_columns = $column_defaults;
306
307 // Also set the new file hash.
308 $file_path = $this->get_media()->get_fullsize_path();
309
310 if ( $file_path ) {
311 $imagify_columns['hash'] = md5_file( $file_path );
312 }
313
314 return $imagify_columns;
315 }
316 }
317