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 / inc / 3rd-party / nextgen-gallery / classes / Optimization / Data / NGG.php

NGG.php in Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF trunk, at inc/3rd-party/nextgen-gallery/classes/Optimization/Data/NGG.php

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