PluginProbe
QuickWebP – WebP & AVIF Image Optimizer, Compression & SEO for WordPress / 3.2.6
QuickWebP – WebP & AVIF Image Optimizer, Compression & SEO for WordPress v3.2.6
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.6, at admin/class-image-optimizer.php

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