PluginProbe
Image Optimization – Compress Images and Convert to WebP or AVIF / 1.1.0
Image Optimization – Compress Images and Convert to WebP or AVIF v1.1.0
1.7.6 1.7.5 1.7.4 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.2.0 1.2.1 1.3.0 1.4.0 1.4.1 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 All 32 releases
image-optimization / modules / optimization / components / media-control.php

media-control.php in Image Optimization – Compress Images and Convert to WebP or AVIF 1.1.0, at modules/optimization/components/media-control.php

287 lines 8.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace ImageOptimization\Modules\Optimization\Components;
4
5 use ImageOptimization\Classes\Image\{
6 Exceptions\Invalid_Image_Exception,
7 Image,
8 Image_Meta,
9 Image_Optimization_Error_Type,
10 Image_Status
11 };
12 use ImageOptimization\Modules\Oauth\Components\{
13 Connect,
14 Exceptions\Auth_Error,
15 };
16 use ImageOptimization\Modules\Optimization\{
17 Classes\Exceptions\Image_Validation_Error,
18 Classes\Optimization_Error_Message,
19 Classes\Validate_Image,
20 Module,
21 };
22 use ImageOptimization\Classes\File_Utils;
23 use ImageOptimization\Modules\Oauth\Classes\Data;
24 use ImageOptimization\Modules\Settings\Classes\Settings;
25 use ImageOptimization\Modules\Stats\Classes\Optimization_Stats;
26
27 use Throwable;
28
29 if ( ! defined( 'ABSPATH' ) ) {
30 exit; // Exit if accessed directly.
31 }
32
33 /**
34 * The class is responsible for rendering optimization control in all views.
35 */
36 class Media_Control {
37 const COLUMN_ID = 'image_optimization';
38 const META_BOX_ID = 'image_optimization_meta_box';
39 const DETAILS_MODAL_FIELD_ID = 'image_optimization_modal';
40
41 /**
42 * Adds a new optimization column to the library list view.
43 *
44 * @param array $columns
45 * @return array
46 */
47 public function add_optimization_column( array $columns ): array {
48 if ( empty( $columns ) ) {
49 return $columns;
50 }
51
52 $columns[ self::COLUMN_ID ] = esc_html__( 'Image optimization', 'image-optimization' );
53
54 return $columns;
55 }
56
57 /**
58 * Renders optimization controls in the library list view.
59 *
60 * @param string $column_name
61 * @param int $attachment_id
62 * @return void
63 */
64 public function render_optimization_column( string $column_name, int $attachment_id ) {
65 if ( self::COLUMN_ID !== $column_name ) {
66 return;
67 }
68
69 $this->render_optimization_control( 'list-view', $attachment_id );
70 }
71
72 /**
73 * Adds optimization control as media meta box.
74 *
75 * @return void
76 */
77 public function add_optimization_meta_box() {
78 add_meta_box(
79 self::META_BOX_ID,
80 __( 'Image optimization', 'image-optimization' ),
81 function( $post ) {
82 $this->render_optimization_control( 'meta-box', $post->ID );
83 },
84 'attachment',
85 'side',
86 );
87 }
88
89 /**
90 * Adds optimization control to media modals.
91 *
92 * @param array $form_fields
93 * @param \WP_Post $post
94 *
95 * @return array
96 */
97 public function add_media_modal_details( array $form_fields, \WP_Post $post ): array {
98 $form_fields[ self::DETAILS_MODAL_FIELD_ID ] = [
99 'label' => '',
100 'input' => 'hidden',
101 'value' => $this->get_optimization_control_html( 'details-view', $post->ID ),
102 'required' => false,
103 ];
104
105 return $form_fields;
106 }
107
108 /**
109 * Returns optimization control as an HTML string.
110 *
111 * @param string $context Control placement context. One of ['list-view', 'meta-box', 'details-view'].
112 * @param int $image_id Attachment id.
113 * @return false|string
114 */
115 public function get_optimization_control_html( string $context, int $image_id ) {
116 ob_start();
117
118 $this->render_optimization_control( $context, $image_id );
119
120 $html = ob_get_contents();
121 ob_end_clean();
122
123 return $html;
124 }
125
126 /**
127 * Renders the optimization control for the current image in the current context.
128 *
129 * @param string $context Control placement context. One of ['list-view', 'meta-box', 'details-view'].
130 * @param int $image_id Attachment id.
131 * @return void Renders the control.
132 */
133 public function render_optimization_control( string $context, int $image_id ) {
134 $global_context = [
135 'image_id' => $image_id,
136 'can_be_restored' => false,
137 ];
138
139 try {
140 if ( ! Connect::is_connected() || ! Connect::is_activated() ) {
141 throw new Auth_Error( 'You have to activate your license to use Image Optimizer' );
142 }
143
144 Validate_Image::is_valid( $image_id );
145
146 $image = new Image( $image_id );
147 $meta = new Image_Meta( $image->get_id() );
148
149 if ( Image_Status::OPTIMIZED === $meta->get_status() ) {
150 $global_context['can_be_restored'] = $image->can_be_restored();
151 } else {
152 $path = $image->get_file_path( Image::SIZE_FULL );
153 $is_webp = strtolower( File_Utils::get_extension( $path ) ) === 'webp';
154 $backups_enabled = Settings::get( Settings::BACKUP_ORIGINAL_IMAGES_OPTION_NAME );
155 $webp_conversion_enabled = Settings::get( Settings::CONVERT_TO_WEBP_OPTION_NAME );
156
157 $global_context['can_be_restored'] = ( ! $is_webp && $webp_conversion_enabled ) || $backups_enabled;
158 }
159
160 switch ( $meta->get_status() ) {
161 case Image_Status::OPTIMIZATION_IN_PROGRESS:
162 Module::load_template( $context, 'loading', array_merge(
163 $global_context, [
164 'action' => 'optimize',
165 ]
166 ) );
167
168 break;
169
170 case Image_Status::REOPTIMIZING_IN_PROGRESS:
171 Module::load_template( $context, 'loading', array_merge(
172 $global_context, [
173 'action' => 'reoptimize',
174 ]
175 ) );
176
177 break;
178
179 case Image_Status::RESTORING_IN_PROGRESS:
180 Module::load_template( $context, 'loading', array_merge(
181 $global_context, [
182 'action' => 'restore',
183 ]
184 ) );
185
186 break;
187
188 case Image_Status::OPTIMIZED:
189 $stats = Optimization_Stats::get_image_stats( $image_id );
190 $saved = [
191 'relative' => round( $stats['current_image_size'] / $stats['initial_image_size'] * 100 ),
192 'absolute' => $stats['initial_image_size'] - $stats['current_image_size'],
193 ];
194
195 Module::load_template( $context, 'optimized', array_merge(
196 $global_context, [
197 'sizes_optimized_count' => $stats['optimized_image_count'],
198 'saved' => $saved,
199 ]
200 ) );
201
202 break;
203
204 case Image_Status::OPTIMIZATION_FAILED:
205 $error_type = $meta->get_error_type() ?? Image_Optimization_Error_Type::GENERIC;
206 $error_message = Optimization_Error_Message::get_optimization_error_message( $error_type );
207 $images_left = Data::images_left();
208
209 Module::load_template( $context, 'error', array_merge(
210 $global_context, [
211 'message' => $error_message,
212 'optimization_error_type' => $error_type,
213 'images_left' => $images_left,
214 'allow_retry' => true,
215 'action' => 'optimize',
216 ]
217 ) );
218
219 break;
220
221 case Image_Status::REOPTIMIZING_FAILED:
222 $error_type = $meta->get_error_type() ?? Image_Optimization_Error_Type::GENERIC;
223 $error_message = Optimization_Error_Message::get_reoptimization_error_message( $error_type );
224 $images_left = Data::images_left();
225
226 Module::load_template( $context, 'error', array_merge(
227 $global_context, [
228 'message' => $error_message,
229 'optimization_error_type' => $error_type,
230 'images_left' => $images_left,
231 'allow_retry' => true,
232 'action' => 'reoptimize',
233 ]
234 ) );
235
236 break;
237
238 case Image_Status::RESTORING_FAILED:
239 Module::load_template( $context, 'error', array_merge(
240 $global_context, [
241 'message' => esc_html__( 'Image restoring error', 'image-optimization' ),
242 'allow_retry' => true,
243 'action' => 'restore',
244 ]
245 ) );
246
247 break;
248
249 default:
250 Module::load_template( $context, 'not-optimized', $global_context );
251 }
252 } catch ( Invalid_Image_Exception |Image_Validation_Error $iie ) {
253 Module::load_template( $context, 'error', array_merge(
254 $global_context, [
255 'action' => 'error',
256 'message' => $iie->getMessage(),
257 'allow_retry' => false,
258 ]
259 ) );
260 } catch ( Auth_Error $ae ) {
261 Module::load_template( $context, 'error', array_merge(
262 $global_context, [
263 'action' => 'error',
264 'message' => esc_html__( 'N/A', 'image-optimization' ),
265 'allow_retry' => false,
266 ]
267 ) );
268 } catch ( Throwable $t ) {
269 Module::load_template( $context, 'error', array_merge(
270 $global_context, [
271 'action' => 'error',
272 'message' => esc_html__( 'Internal server error', 'image-optimization' ),
273 'allow_retry' => false,
274 ]
275 ) );
276 }
277 }
278
279 public function __construct() {
280 add_filter( 'manage_upload_columns', [ $this, 'add_optimization_column' ] );
281 add_action( 'manage_media_custom_column', [ $this, 'render_optimization_column' ], 10, 2 );
282
283 add_action( 'add_meta_boxes_attachment', [ $this, 'add_optimization_meta_box' ] );
284 add_filter( 'attachment_fields_to_edit', [ $this, 'add_media_modal_details' ], 10, 2 );
285 }
286 }
287