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

671 lines 20.5 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 = 100;
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, $imagesize, $file, $attachment_id ) {
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
297 $max_size = $resize_value;
298 }
299
300 return $max_size;
301 }
302
303 /**
304 * Change the default quality of wp editor
305 */
306 public function change_wp_quality( $default_quality, $mime_type ) {
307
308 $default_quality = 100;
309
310 return $default_quality;
311 }
312
313 /**
314 * Optimize image through ajax
315 */
316 public function image_optimizition_ajax() {
317
318 // verify the nonce.
319 $nonce = isset($_POST['nonce']) ? $_POST['nonce'] : '';
320 if( !wp_verify_nonce( $nonce, 'image_optimize_nonce' ) ) {
321 wp_send_json_error( __( 'Refresh the page and try again.', QUICKWEBP_TEXT_DOMAIN ) );
322 }
323
324 // Get settings
325 $settings = $this->get_ajax_settings();
326
327 // Get the file
328 $file = count($_FILES) > 0 ? array_shift($_FILES) : array();
329 if ( empty($file) ) {
330 wp_send_json_error( __( 'No image uploaded, try again.', QUICKWEBP_TEXT_DOMAIN ) );
331 }
332
333
334 $image_file = $this->file_is_image( $file, $settings );
335 if ( ! $image_file ) {
336 wp_send_json_error( __( 'No image uploaded, try again.', QUICKWEBP_TEXT_DOMAIN ) );
337 }
338
339 if ( $settings['quickwebp_settings_conversion'] != '1' ) {
340
341 $image_file['new_size'] = $image_file['size'];
342 $image_file['new_type'] = $image_file['type'];
343 $this->return_ajax_data( $image_file );
344 }
345
346 $extension_to_use = $this->image_extension_loaded( $settings );
347 if ( ! $extension_to_use ) {
348
349 $image_file['new_size'] = $image_file['size'];
350 $image_file['new_type'] = $image_file['type'];
351 $this->return_ajax_data( $image_file );
352 }
353
354 $manager = new ImageManager(array('driver'=>$extension_to_use));
355 $image = $manager->make($image_file['tmp_name']);
356 $quality = $this->get_quality( $image_file['tmp_name'], $settings );
357
358 $image->sharpen( $settings['quickwebp_settings_conversion_sharpen'] );
359 $image->save( $image_file['tmp_name'], $quality, 'webp' );
360
361 $image_file['new_size'] = $image->filesize();
362 $image_file['new_type'] = $image->mime();
363 $this->return_ajax_data( $image_file );
364 }
365
366 /**
367 * Return ajax data
368 */
369 public function return_ajax_data( $data ) {
370
371 $return = array(
372 'original_name' => $data['original_name'],
373 'size' => $data['size'],
374 'type' => $this->type_from_mime_type( $data['type'] ),
375 'mime_type' => $data['type'],
376 'image' => 'data:'.$data['new_type'].';base64,' . base64_encode( file_get_contents( $data['tmp_name'] ) ),
377 'name' => $data['name'],
378 'new_size' => $data['new_size'],
379 'new_type' => $this->type_from_mime_type( $data['new_type'] ),
380 'new_mime_type' => $data['new_type']
381 );
382
383 wp_send_json_success( $return );
384 }
385
386 /**
387 * Get the type from the mime type
388 */
389 public function type_from_mime_type( $mime_type ) {
390
391 $array = array(
392 'image/jpeg' => 'JPEG',
393 'image/png' => 'PNG',
394 'image/webp' => 'WebP'
395 );
396
397 return $array[$mime_type] ?? '';
398 }
399
400 /**
401 * Get the unoptimized media ids
402 */
403 public function get_unoptimized_media_ids() {
404
405 $statuses = array(
406 'inherit' => 'inherit',
407 'private' => 'private',
408 );
409 $custom_statuses = get_post_stati( array( 'public' => true ) );
410 unset( $custom_statuses['publish'] );
411 if ( $custom_statuses ) {
412 $statuses = array_merge( $statuses, $custom_statuses );
413 }
414
415 $mime_types = $this->allowed_mime_types;
416 $index = array_search( 'image/webp', $mime_types );
417 unset( $mime_types[$index] );
418
419 $media_ids = get_posts( array(
420 'post_type' => 'attachment',
421 'post_mime_type' => $mime_types,
422 'post_status' => array_keys( $statuses ),
423 'posts_per_page' => -1,
424 'fields' => 'ids',
425 'meta_query' => array(
426 'relation' => 'AND',
427 array(
428 'key' => 'quickwebp_has_error',
429 'compare' => 'NOT EXISTS'
430 ),
431 array(
432 'relation' => 'OR',
433 array(
434 'key' => 'quickwebp_already_optimized',
435 'compare' => 'NOT EXISTS'
436 ),
437 array(
438 'key' => 'quickwebp_already_optimized',
439 'compare' => '=',
440 'value' => '0'
441 )
442 ),
443 ),
444 ) );
445
446 return $media_ids;
447
448 }
449
450 /**
451 * Get the list of media files
452 */
453 public function get_media_files( $media_id ) {
454
455 $fullsize_path = get_attached_file( $media_id );
456
457 if ( ! $fullsize_path ) {
458 return array();
459 }
460
461 $media_data = wp_get_attachment_image_src( $media_id, 'full' );
462 $file_type = wp_check_filetype( $fullsize_path );
463
464 $all_sizes = [
465 'full' => [
466 'size' => 'full',
467 'path' => $fullsize_path,
468 'width' => $media_data[1],
469 'height' => $media_data[2],
470 'mime-type' => $file_type['type'],
471 'disabled' => false,
472 ],
473 ];
474
475 $sizes = wp_get_attachment_metadata( $media_id, true );
476 $sizes = ! empty( $sizes['sizes'] ) && is_array( $sizes['sizes'] ) ? $sizes['sizes'] : [];
477
478 $dir_path = trailingslashit( dirname( $fullsize_path ) );
479
480 foreach ( $sizes as $size => $size_data ) {
481 $all_sizes[ $size ] = [
482 'size' => $size,
483 'path' => $dir_path . $size_data['file'],
484 'width' => $size_data['width'],
485 'height' => $size_data['height'],
486 'mime-type' => $size_data['mime-type'],
487 'disabled' => false
488 ];
489 }
490
491 return $all_sizes;
492 }
493
494 /**
495 * Optimize a local file
496 */
497 public function optimize_local_file( $size ) {
498
499 $settings = $this->get_settings();
500
501 $extension_to_use = $this->image_extension_loaded( $settings );
502 if ( ! $extension_to_use ) {
503 return false;
504 }
505
506 if ( !is_file($size['path']) ) {
507 return false;
508 }
509
510 $real_type = mime_content_type( $size['path']);
511 if ( !in_array( $real_type, $this->allowed_mime_types ) ) {
512 return false;
513 }
514
515 try {
516 $size_before = filesize( $size['path'] );
517 $manager = new ImageManager(array('driver'=>$extension_to_use));
518 $image = $manager->make($size['path']);
519 $quality = $this->get_quality( $size['path'], $settings );
520 $webp_path = $size['path'].'.webp';
521
522 $image->sharpen($settings['quickwebp_settings_conversion_sharpen']);
523 $image->save( $webp_path, $quality, 'webp' );
524 $size_after = $image->filesize();
525 $image->destroy();
526
527 $deference = $size_before - $size_after;
528 $percent = $deference / $size_before * 100;
529
530 return array(
531 'success' => 1,
532 'original_size' => $size_before,
533 'optimized_size' => $size_after,
534 'percent' => round( $percent, 2 ),
535 'path' => $webp_path
536 );
537 } catch (\Throwable $th) {
538 return false;
539 }
540 }
541
542 /**
543 * Optimize a single media
544 */
545 public function single_optimizition_ajax() {
546
547 // verify the nonce.
548 $nonce = isset($_POST['nonce']) ? $_POST['nonce'] : '';
549 if( !wp_verify_nonce( $nonce, 'quickwebp_admin_attachment' ) ) {
550 wp_send_json_error( __( 'Refresh the page and try again.', QUICKWEBP_TEXT_DOMAIN ) );
551 }
552
553 // Sanitize data
554 $attachment_id = isset( $_POST['attachment_id'] ) ? sanitize_text_field( $_POST['attachment_id'] ) : false;
555
556 if ( ! $attachment_id ) {
557 wp_send_json_error( __( 'No attachment id.', QUICKWEBP_TEXT_DOMAIN ) );
558 }
559
560 $already_optimized = get_post_meta( $attachment_id, 'quickwebp_already_optimized', true );
561 if ( $already_optimized === '1' ) {
562 wp_send_json_error( __( 'Already optimized.', QUICKWEBP_TEXT_DOMAIN ) );
563 }
564
565 // check the mime type
566 $mime_types = $this->allowed_mime_types;
567 $index = array_search( 'image/webp', $mime_types );
568 unset( $mime_types[$index] );
569 $mime_type = get_post_mime_type( $attachment_id );
570
571 if ( ! in_array( $mime_type, $mime_types ) ) {
572 wp_send_json_error( __( 'Not a valid image.', QUICKWEBP_TEXT_DOMAIN ) );
573 }
574
575 $sizes = $this->get_media_files( $attachment_id );
576 $new_sizes = array();
577
578 foreach ( $sizes as $key => $size ) {
579
580 $result = $this->optimize_local_file( $size );
581
582 if ( $result ) {
583 $new_sizes[$key] = $result;
584 }
585 }
586
587 if ( ! empty( $new_sizes ) ) {
588 update_post_meta( $attachment_id, 'quickwebp_already_optimized', '1' );
589 update_post_meta( $attachment_id, 'quickwebp_data', $new_sizes );
590 delete_post_meta( $attachment_id, 'quickwebp_has_error' );
591 } else {
592 update_post_meta( $attachment_id, 'quickwebp_has_error', '1' );
593 }
594
595 $wp_media_extend = new Quickwebp_Wp_Media_Extends( $this->plugin_name, $this->version );
596 $html = $wp_media_extend->attachment_data( $new_sizes, $attachment_id );
597
598 wp_send_json_success( $html );
599 }
600
601 /**
602 * Undo a single media optimization
603 */
604 public function undo_single_optimizition_ajax() {
605
606 // verify the nonce.
607 $nonce = isset($_POST['nonce']) ? $_POST['nonce'] : '';
608 if( !wp_verify_nonce( $nonce, 'quickwebp_admin_attachment' ) ) {
609 wp_send_json_error( __( 'Refresh the page and try again.', QUICKWEBP_TEXT_DOMAIN ) );
610 }
611
612 // Sanitize data
613 $attachment_id = isset( $_POST['attachment_id'] ) ? sanitize_text_field( $_POST['attachment_id'] ) : false;
614
615 if ( ! $attachment_id ) {
616 wp_send_json_error( __( 'No attachment id.', QUICKWEBP_TEXT_DOMAIN ) );
617 }
618
619 $already_optimized = get_post_meta( $attachment_id, 'quickwebp_already_optimized', true );
620 if ( $already_optimized === '1' ) {
621
622 $this->remove_related_files( $attachment_id );
623 delete_post_meta( $attachment_id, 'quickwebp_already_optimized' );
624 delete_post_meta( $attachment_id, 'quickwebp_data' );
625
626 $wp_media_extend = new Quickwebp_Wp_Media_Extends( $this->plugin_name, $this->version );
627 $html = $wp_media_extend->optimize_btn( $attachment_id );
628
629 wp_send_json_success( $html );
630
631 } else {
632 wp_send_json_error( __( 'Not optimized.', QUICKWEBP_TEXT_DOMAIN ) );
633 }
634
635 }
636
637 /**
638 * Remove the related files of an optimized attachment
639 */
640 public function remove_related_files( $id ) {
641
642 $data = get_post_meta( $id, 'quickwebp_data', true );
643
644 if ( ! empty( $data ) ) {
645
646 foreach ( $data as $key => $value ) {
647
648 $path = $value['path'] ?? '';
649
650 if ( !empty($path) && file_exists( $path ) ) {
651 wp_delete_file($path);
652 }
653 }
654 }
655
656 }
657
658 /**
659 * Trigger before delete attachment
660 */
661 public function before_delete_attachment( $post_id, $post ) {
662
663 $already_optimized = get_post_meta( $post_id, 'quickwebp_already_optimized', true );
664 if ( $already_optimized === '1' ) {
665
666 $this->remove_related_files( $post_id );
667 }
668
669 }
670
671 }