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

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