PluginProbe
QuickWebP – WebP & AVIF Image Optimizer, Compression & SEO for WordPress / 3.2.0
QuickWebP – WebP & AVIF Image Optimizer, Compression & SEO for WordPress v3.2.0
4.1.1 4.1.0 4.0.1 4.0.0 3.3.1 3.3.0 trunk 1.0.0 2.0.0 2.1.0 3.0.0 3.1.0 3.2.0 3.2.1 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.2.8
quickwebp / admin / class-image-optimizer.php

class-image-optimizer.php in QuickWebP – WebP & AVIF Image Optimizer, Compression & SEO for WordPress 3.2.0, at admin/class-image-optimizer.php

621 lines 18.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 use Intervention\Image\ImageManager;
4
5 /**
6 * The core functionality for image optimizing.
7 *
8 * @link http://webdeclic.com
9 * @since 1.0.0
10 *
11 * @package Quickwebp
12 * @subpackage Quickwebp/admin
13 */
14 class Quickwebp_Image_Optimizer {
15
16 /**
17 * The ID of this plugin.
18 *
19 * @since 1.0.0
20 * @access private
21 * @var string $plugin_name The ID of this plugin.
22 */
23 private $plugin_name;
24
25 /**
26 * The version of this plugin.
27 *
28 * @since 1.0.0
29 * @access private
30 * @var string $version The current version of this plugin.
31 */
32 private $version;
33
34 /**
35 * Allowed mime types for the optimazation
36 */
37 public $allowed_mime_types;
38
39 /**
40 * Initialize the class and set its properties.
41 *
42 * @since 1.0.0
43 * @param string $plugin_name The name of this plugin.
44 * @param string $version The version of this plugin.
45 */
46 public function __construct( $plugin_name, $version ) {
47
48 $this->plugin_name = $plugin_name;
49 $this->version = $version;
50 $this->allowed_mime_types = array( 'image/jpeg', 'image/png', 'image/webp' );
51
52 }
53
54 /**
55 * Optimize an image added in wp_media
56 */
57 public function image_optimizition( $file ) {
58
59 $settings = $this->get_settings();
60
61 $image_file = $this->file_is_image( $file, $settings );
62 if ( ! $image_file ) {
63 return $file;
64 }
65
66 if ( $settings['quickwebp_settings_conversion'] != '1' ) {
67 return $image_file;
68 }
69
70 $extension_to_use = $this->image_extension_loaded( $settings );
71 if ( ! $extension_to_use ) {
72 return $image_file;
73 }
74
75 $manager = new ImageManager(array('driver'=>$extension_to_use));
76 $image = $manager->make($image_file['tmp_name']);
77 $quality = $this->get_quality( $image_file['tmp_name'], $settings );
78
79 $image->sharpen($settings['quickwebp_settings_conversion_sharpen']);
80 $image->save( $image_file['tmp_name'], $quality, 'webp' );
81
82 $size_after = $image->filesize();
83 $mime = $image->mime();
84
85 $image_file['size'] = $size_after;
86 $image_file['type'] = $mime;
87
88 return $image_file;
89 }
90
91 /**
92 * Get the package used by the server
93 *
94 */
95 public function image_extension_loaded( $settings ) {
96
97 $accepted_librarys = array( 'gd', 'imagick' );
98 $library_to_use = $settings['quickwebp_settings_library'];
99
100 if ( in_array( $library_to_use, $accepted_librarys ) ) {
101
102 return $library_to_use;
103 }
104
105 return false;
106 }
107
108 /**
109 * Check if the file is an image
110 *
111 */
112 public function file_is_image( $file, $settings ) {
113
114 $file_name = isset($file['name']) ? $file['name'] : '';
115 $file_type = isset($file['type']) ? $file['type'] : '';
116 $file_tmp_name = isset($file['tmp_name']) ? $file['tmp_name'] : '';
117 $file_error = isset($file['error']) ? $file['error'] : '';
118 $file_size = isset($file['size']) ? $file['size'] : '';
119
120 if ( empty($file_tmp_name) ) {
121 return false;
122 }
123
124 $allowed_mime_types = apply_filters( 'quickwebp_mime_types_allowed', $this->allowed_mime_types );
125 $is_image = wp_getimagesize($file_tmp_name);
126 $mime_type = wp_get_image_mime($file_tmp_name);
127 if ( ! $is_image || ! in_array( $mime_type, $allowed_mime_types ) ) {
128 return false;
129 }
130
131 $name = $file_name;
132
133 if ( $settings['quickwebp_settings_cleanup'] == '1' ) {
134 $name = quickwebp_sanitize_name($file_name);
135 }
136
137 return array(
138 'original_name' => $file_name,
139 'name' => $name,
140 'type' => $file_type,
141 'tmp_name' => $file_tmp_name,
142 'error' => $file_error,
143 'size' => $file_size
144 );
145 }
146
147 /**
148 * Get the optimization settings
149 */
150 public function get_settings() {
151
152 return array(
153 'quickwebp_settings_conversion' => get_option('quickwebp_settings_conversion', quickwebp_settings_default('quickwebp_settings_conversion') ),
154 'quickwebp_settings_conversion_quality' => get_option('quickwebp_settings_conversion_quality', quickwebp_settings_default('quickwebp_settings_conversion_quality') ),
155 'quickwebp_settings_conversion_sharpen' => get_option('quickwebp_settings_conversion_sharpen', quickwebp_settings_default('quickwebp_settings_conversion_sharpen') ),
156 'quickwebp_settings_conversion_ignore_webp' => get_option('quickwebp_settings_conversion_ignore_webp', quickwebp_settings_default('quickwebp_settings_conversion_ignore_webp') ),
157 'quickwebp_settings_resize' => get_option('quickwebp_settings_resize', quickwebp_settings_default('quickwebp_settings_resize') ),
158 'quickwebp_settings_resize_value' => get_option('quickwebp_settings_resize_value', quickwebp_settings_default('quickwebp_settings_resize_value') ),
159 'quickwebp_settings_completion' => get_option('quickwebp_settings_completion', quickwebp_settings_default('quickwebp_settings_completion') ),
160 'quickwebp_settings_completion_options' => get_option('quickwebp_settings_completion_options', quickwebp_settings_default('quickwebp_settings_completion_options') ),
161 'quickwebp_settings_cleanup' => get_option('quickwebp_settings_cleanup', quickwebp_settings_default('quickwebp_settings_cleanup') ),
162 'quickwebp_settings_library' => get_option( 'quickwebp_settings_library', quickwebp_settings_default('quickwebp_settings_library') )
163 );
164 }
165
166 /**
167 * Get the optimization settings
168 */
169 public function get_ajax_settings() {
170
171 $settings = isset($_POST['settings']) ? sanitize_text_field($_POST['settings']) : array();
172 $settings = json_decode( stripslashes( $settings ), true );
173
174 return array(
175 'quickwebp_settings_conversion' => isset( $settings['quickwebp_settings_conversion'] ) ? $settings['quickwebp_settings_conversion'] : '',
176 'quickwebp_settings_conversion_quality' => isset( $settings['quickwebp_settings_conversion_quality'] ) ? $settings['quickwebp_settings_conversion_quality'] : '',
177 'quickwebp_settings_conversion_sharpen' => isset( $settings['quickwebp_settings_conversion_sharpen'] ) ? $settings['quickwebp_settings_conversion_sharpen'] : '',
178 'quickwebp_settings_conversion_ignore_webp' => isset( $settings['quickwebp_settings_conversion_ignore_webp'] ) ? $settings['quickwebp_settings_conversion_ignore_webp'] : array(),
179 'quickwebp_settings_resize' => isset( $settings['quickwebp_settings_resize'] ) ? $settings['quickwebp_settings_resize'] : '',
180 'quickwebp_settings_resize_value' => isset( $settings['quickwebp_settings_resize_value'] ) ? $settings['quickwebp_settings_resize_value'] : '',
181 'quickwebp_settings_completion' => isset( $settings['quickwebp_settings_completion'] ) ? $settings['quickwebp_settings_completion'] : '',
182 'quickwebp_settings_completion_options' => isset( $settings['quickwebp_settings_completion_options'] ) ? $settings['quickwebp_settings_completion_options'] : array(),
183 'quickwebp_settings_cleanup' => isset( $settings['quickwebp_settings_cleanup'] ) ? $settings['quickwebp_settings_cleanup'] : '',
184 'quickwebp_settings_library' => isset( $settings['quickwebp_settings_library'] ) ? $settings['quickwebp_settings_library'] : ''
185 );
186 }
187
188 /**
189 * Add data to the attachment
190 */
191 public function add_data_to_attachment( $metadata, $attachment_id, $context ) {
192
193 $settings = $this->get_settings();
194 if ( $settings['quickwebp_settings_completion'] != '1' ) {
195 return $metadata;
196 }
197
198 if ( $context != 'create' ) {
199 return $metadata;
200 }
201
202 if ( isset($_FILES['async-upload']['original_name']) ) {
203
204 $original_name = sanitize_text_field( $_FILES['async-upload']['original_name'] );
205 $original_name = pathinfo( $original_name, PATHINFO_FILENAME );
206
207 $post_arr = array(
208 'ID' => $attachment_id,
209 'meta_input' => array()
210 );
211
212 $completion_options = is_array($settings['quickwebp_settings_completion_options']) ? $settings['quickwebp_settings_completion_options'] : array();
213
214 if ( in_array( 'title', $completion_options ) ) {
215 $post_arr['post_title'] = $original_name;
216 }
217
218 if ( in_array( 'caption', $completion_options ) ) {
219 $post_arr['post_excerpt'] = $original_name;
220 }
221
222 if ( in_array( 'alt', $completion_options ) ) {
223 $post_arr['meta_input']['_wp_attachment_image_alt'] = $original_name;
224 }
225
226 if ( in_array( 'description', $completion_options ) ) {
227 $post_arr['post_content'] = $original_name;
228 }
229
230 wp_update_post( $post_arr );
231 }
232
233 return $metadata;
234 }
235
236 /**
237 * Get the quality
238 */
239 public function get_quality( $file, $settings ) {
240
241 $ignore_webp = is_array( $settings['quickwebp_settings_conversion_ignore_webp'] ) ? $settings['quickwebp_settings_conversion_ignore_webp'] : array();
242 $quality = $settings['quickwebp_settings_conversion_quality'];
243 $mime_type = wp_get_image_mime($file);
244
245 switch ( $mime_type ) {
246
247 case 'image/webp':
248 if ( in_array( 'checked', $ignore_webp ) ){
249 $quality = 100;
250 }
251 break;
252 }
253
254 return $quality;
255 }
256
257 /**
258 * Change the default size of wp editor
259 */
260 public function change_wp_max_size( $max_size, $imagesize, $file, $attachment_id ) {
261
262 $settings = $this->get_settings();
263 $resize_active = $settings['quickwebp_settings_resize'];
264 $resize_value = $settings['quickwebp_settings_resize_value'];
265
266 if ( $resize_active == '1' ) {
267
268 $max_size = $resize_value;
269 }
270
271 return $max_size;
272 }
273
274 /**
275 * Change the default quality of wp editor
276 */
277 public function change_wp_quality( $default_quality, $mime_type ) {
278
279 $default_quality = 100;
280
281 return $default_quality;
282 }
283
284 /**
285 * Optimize image through ajax
286 */
287 public function image_optimizition_ajax() {
288
289 // verify the nonce.
290 $nonce = isset($_POST['nonce']) ? $_POST['nonce'] : '';
291 if( !wp_verify_nonce( $nonce, 'image_optimize_nonce' ) ) {
292 wp_send_json_error( __( 'Refresh the page and try again.', QUICKWEBP_TEXT_DOMAIN ) );
293 }
294
295 // Get settings
296 $settings = $this->get_ajax_settings();
297
298 // Get the file
299 $file = count($_FILES) > 0 ? array_shift($_FILES) : array();
300 if ( empty($file) ) {
301 wp_send_json_error( __( 'No image uploaded, try again.', QUICKWEBP_TEXT_DOMAIN ) );
302 }
303
304
305 $image_file = $this->file_is_image( $file, $settings );
306 if ( ! $image_file ) {
307 wp_send_json_error( __( 'No image uploaded, try again.', QUICKWEBP_TEXT_DOMAIN ) );
308 }
309
310 if ( $settings['quickwebp_settings_conversion'] != '1' ) {
311
312 $image_file['new_size'] = $image_file['size'];
313 $image_file['new_type'] = $image_file['type'];
314 $this->return_ajax_data( $image_file );
315 }
316
317 $extension_to_use = $this->image_extension_loaded( $settings );
318 if ( ! $extension_to_use ) {
319
320 $image_file['new_size'] = $image_file['size'];
321 $image_file['new_type'] = $image_file['type'];
322 $this->return_ajax_data( $image_file );
323 }
324
325 $manager = new ImageManager(array('driver'=>$extension_to_use));
326 $image = $manager->make($image_file['tmp_name']);
327 $quality = $this->get_quality( $image_file['tmp_name'], $settings );
328
329 $image->sharpen( $settings['quickwebp_settings_conversion_sharpen'] );
330 $image->save( $image_file['tmp_name'], $quality, 'webp' );
331
332 $image_file['new_size'] = $image->filesize();
333 $image_file['new_type'] = $image->mime();
334 $this->return_ajax_data( $image_file );
335 }
336
337 /**
338 * Return ajax data
339 */
340 public function return_ajax_data( $data ) {
341
342 $return = array(
343 'original_name' => $data['original_name'],
344 'size' => $data['size'],
345 'type' => $this->type_from_mime_type( $data['type'] ),
346 'mime_type' => $data['type'],
347 'image' => 'data:'.$data['new_type'].';base64,' . base64_encode( file_get_contents( $data['tmp_name'] ) ),
348 'name' => $data['name'],
349 'new_size' => $data['new_size'],
350 'new_type' => $this->type_from_mime_type( $data['new_type'] ),
351 'new_mime_type' => $data['new_type']
352 );
353
354 wp_send_json_success( $return );
355 }
356
357 /**
358 * Get the type from the mime type
359 */
360 public function type_from_mime_type( $mime_type ) {
361
362 $array = array(
363 'image/jpeg' => 'JPEG',
364 'image/png' => 'PNG',
365 'image/webp' => 'WebP'
366 );
367
368 return $array[$mime_type] ?? '';
369 }
370
371 /**
372 * Get the unoptimized media ids
373 */
374 public function get_unoptimized_media_ids() {
375
376 $statuses = array(
377 'inherit' => 'inherit',
378 'private' => 'private',
379 );
380 $custom_statuses = get_post_stati( array( 'public' => true ) );
381 unset( $custom_statuses['publish'] );
382 if ( $custom_statuses ) {
383 $statuses = array_merge( $statuses, $custom_statuses );
384 }
385
386 $mime_types = $this->allowed_mime_types;
387 $index = array_search( 'image/webp', $mime_types );
388 unset( $mime_types[$index] );
389
390 $media_ids = get_posts( array(
391 'post_type' => 'attachment',
392 'post_mime_type' => $mime_types,
393 'post_status' => array_keys( $statuses ),
394 'posts_per_page' => -1,
395 'fields' => 'ids',
396 'meta_query' => array(
397 'relation' => 'OR',
398 array(
399 'key' => 'quickwebp_already_optimized',
400 'compare' => 'NOT EXISTS'
401 ),
402 array(
403 'key' => 'quickwebp_already_optimized',
404 'compare' => '=',
405 'value' => '0'
406 )
407 ),
408 ) );
409
410 return $media_ids;
411
412 }
413
414 /**
415 * Get the list of media files
416 */
417 public function get_media_files( $media_id ) {
418
419 $fullsize_path = get_attached_file( $media_id );
420
421 if ( ! $fullsize_path ) {
422 return array();
423 }
424
425 $media_data = wp_get_attachment_image_src( $media_id, 'full' );
426 $file_type = wp_check_filetype( $fullsize_path );
427
428 $all_sizes = [
429 'full' => [
430 'size' => 'full',
431 'path' => $fullsize_path,
432 'width' => $media_data[1],
433 'height' => $media_data[2],
434 'mime-type' => $file_type['type'],
435 'disabled' => false,
436 ],
437 ];
438
439 $sizes = wp_get_attachment_metadata( $media_id, true );
440 $sizes = ! empty( $sizes['sizes'] ) && is_array( $sizes['sizes'] ) ? $sizes['sizes'] : [];
441
442 $dir_path = trailingslashit( dirname( $fullsize_path ) );
443
444 foreach ( $sizes as $size => $size_data ) {
445 $all_sizes[ $size ] = [
446 'size' => $size,
447 'path' => $dir_path . $size_data['file'],
448 'width' => $size_data['width'],
449 'height' => $size_data['height'],
450 'mime-type' => $size_data['mime-type'],
451 'disabled' => false
452 ];
453 }
454
455 return $all_sizes;
456 }
457
458 /**
459 * Optimize a local file
460 */
461 public function optimize_local_file( $size ) {
462
463 $settings = $this->get_settings();
464
465 $extension_to_use = $this->image_extension_loaded( $settings );
466 if ( ! $extension_to_use ) {
467 return false;
468 }
469
470 $size_before = filesize( $size['path'] );
471 $manager = new ImageManager(array('driver'=>$extension_to_use));
472 $image = $manager->make($size['path']);
473 $quality = $this->get_quality( $size['path'], $settings );
474 $webp_path = $size['path'].'.webp';
475
476 $image->sharpen($settings['quickwebp_settings_conversion_sharpen']);
477 $image->save( $webp_path, $quality, 'webp' );
478 $size_after = $image->filesize();
479 $image->destroy();
480
481 $deference = $size_before - $size_after;
482 $percent = $deference / $size_before * 100;
483
484 return array(
485 'success' => 1,
486 'original_size' => $size_before,
487 'optimized_size' => $size_after,
488 'percent' => round( $percent, 2 ),
489 'path' => $webp_path
490 );
491
492 }
493
494 /**
495 * Optimize a single media
496 */
497 public function single_optimizition_ajax() {
498
499 // verify the nonce.
500 $nonce = isset($_POST['nonce']) ? $_POST['nonce'] : '';
501 if( !wp_verify_nonce( $nonce, 'quickwebp_admin_attachment' ) ) {
502 wp_send_json_error( __( 'Refresh the page and try again.', QUICKWEBP_TEXT_DOMAIN ) );
503 }
504
505 // Sanitize data
506 $attachment_id = isset( $_POST['attachment_id'] ) ? sanitize_text_field( $_POST['attachment_id'] ) : false;
507
508 if ( ! $attachment_id ) {
509 wp_send_json_error( __( 'No attachment id.', QUICKWEBP_TEXT_DOMAIN ) );
510 }
511
512 $already_optimized = get_post_meta( $attachment_id, 'quickwebp_already_optimized', true );
513 if ( $already_optimized === '1' ) {
514 wp_send_json_error( __( 'Already optimized.', QUICKWEBP_TEXT_DOMAIN ) );
515 }
516
517 // check the mime type
518 $mime_types = $this->allowed_mime_types;
519 $index = array_search( 'image/webp', $mime_types );
520 unset( $mime_types[$index] );
521 $mime_type = get_post_mime_type( $attachment_id );
522
523 if ( ! in_array( $mime_type, $mime_types ) ) {
524 wp_send_json_error( __( 'Not a valid image.', QUICKWEBP_TEXT_DOMAIN ) );
525 }
526
527 $sizes = $this->get_media_files( $attachment_id );
528 $new_sizes = array();
529
530 foreach ( $sizes as $key => $size ) {
531
532 $result = $this->optimize_local_file( $size );
533
534 if ( $result ) {
535 $new_sizes[$key] = $result;
536 }
537 }
538
539 if ( ! empty( $new_sizes ) ) {
540
541 update_post_meta( $attachment_id, 'quickwebp_already_optimized', '1' );
542 update_post_meta( $attachment_id, 'quickwebp_data', $new_sizes );
543 }
544
545 $wp_media_extend = new Quickwebp_Wp_Media_Extends( $this->plugin_name, $this->version );
546 $html = $wp_media_extend->attachment_data( $new_sizes, $attachment_id );
547
548 wp_send_json_success( $html );
549 }
550
551 /**
552 * Undo a single media optimization
553 */
554 public function undo_single_optimizition_ajax() {
555
556 // verify the nonce.
557 $nonce = isset($_POST['nonce']) ? $_POST['nonce'] : '';
558 if( !wp_verify_nonce( $nonce, 'quickwebp_admin_attachment' ) ) {
559 wp_send_json_error( __( 'Refresh the page and try again.', QUICKWEBP_TEXT_DOMAIN ) );
560 }
561
562 // Sanitize data
563 $attachment_id = isset( $_POST['attachment_id'] ) ? sanitize_text_field( $_POST['attachment_id'] ) : false;
564
565 if ( ! $attachment_id ) {
566 wp_send_json_error( __( 'No attachment id.', QUICKWEBP_TEXT_DOMAIN ) );
567 }
568
569 $already_optimized = get_post_meta( $attachment_id, 'quickwebp_already_optimized', true );
570 if ( $already_optimized === '1' ) {
571
572 $this->remove_related_files( $attachment_id );
573 delete_post_meta( $attachment_id, 'quickwebp_already_optimized' );
574 delete_post_meta( $attachment_id, 'quickwebp_data' );
575
576 $wp_media_extend = new Quickwebp_Wp_Media_Extends( $this->plugin_name, $this->version );
577 $html = $wp_media_extend->optimize_btn( $attachment_id );
578
579 wp_send_json_success( $html );
580
581 } else {
582 wp_send_json_error( __( 'Not optimized.', QUICKWEBP_TEXT_DOMAIN ) );
583 }
584
585 }
586
587 /**
588 * Remove the related files of an optimized attachment
589 */
590 public function remove_related_files( $id ) {
591
592 $data = get_post_meta( $id, 'quickwebp_data', true );
593
594 if ( ! empty( $data ) ) {
595
596 foreach ( $data as $key => $value ) {
597
598 $path = $value['path'] ?? '';
599
600 if ( !empty($path) && file_exists( $path ) ) {
601 wp_delete_file($path);
602 }
603 }
604 }
605
606 }
607
608 /**
609 * Trigger before delete attachment
610 */
611 public function before_delete_attachment( $post_id, $post ) {
612
613 $already_optimized = get_post_meta( $post_id, 'quickwebp_already_optimized', true );
614 if ( $already_optimized === '1' ) {
615
616 $this->remove_related_files( $post_id );
617 }
618
619 }
620
621 }