PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / 1.9.8
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF v1.9.8
2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.9 2.2.8 trunk 1.10 1.3.3 1.3.4 1.3.5 1.3.5.1 1.3.5.2 1.3.6 1.3.6.1 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.5 All 103 releases
imagify / classes / Optimization / File.php

File.php in Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF 1.9.8, at classes/Optimization/File.php

880 lines 22.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Imagify\Optimization;
3
4 defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
5
6 /**
7 * A generic optimization class focussed on the file itself.
8 *
9 * @since 1.9
10 * @author Grégory Viguier
11 */
12 class File {
13
14 /**
15 * Absolute path to the file.
16 *
17 * @var string
18 * @since 1.9
19 * @access protected
20 * @author Grégory Viguier
21 */
22 protected $path;
23
24 /**
25 * Tell if the file is an image.
26 *
27 * @var bool
28 * @since 1.9
29 * @access protected
30 * @see $this->is_image()
31 * @author Grégory Viguier
32 */
33 protected $is_image;
34
35 /**
36 * Store the file mime type + file extension (if the file is supported).
37 *
38 * @var array
39 * @since 1.9
40 * @access protected
41 * @see $this->get_file_type()
42 * @author Grégory Viguier
43 */
44 protected $file_type;
45
46 /**
47 * Filesystem object.
48 *
49 * @var \Imagify_Filesystem
50 * @since 1.9
51 * @access protected
52 * @author Grégory Viguier
53 */
54 protected $filesystem;
55
56 /**
57 * The editor instance used to resize the file.
58 *
59 * @var \WP_Image_Editor_Imagick|\WP_Image_Editor_GD|WP_Error.
60 * @since 1.9
61 * @access protected
62 * @author Grégory Viguier
63 */
64 protected $editor;
65
66 /**
67 * Used to cache the plugin’s options.
68 *
69 * @var array
70 * @since 1.9
71 * @access protected
72 * @author Grégory Viguier
73 */
74 protected $options = [];
75
76 /**
77 * The constructor.
78 *
79 * @since 1.9
80 * @access public
81 * @author Grégory Viguier
82 *
83 * @param string $file_path Absolute path to the file.
84 */
85 public function __construct( $file_path ) {
86 $this->path = $file_path;
87 $this->filesystem = \Imagify_Filesystem::get_instance();
88 }
89
90 /**
91 * Tell if the file is valid.
92 *
93 * @since 1.9
94 * @access public
95 * @author Grégory Viguier
96 *
97 * @return bool
98 */
99 public function is_valid() {
100 return (bool) $this->path;
101 }
102
103 /**
104 * Tell if the file can be processed.
105 *
106 * @since 1.9
107 * @access public
108 * @author Grégory Viguier
109 *
110 * @return bool|WP_Error
111 */
112 public function can_be_processed() {
113 if ( ! $this->path ) {
114 return new \WP_Error( 'empty_path', __( 'File path is empty.', 'imagify' ) );
115 }
116
117 if ( ! empty( $this->filesystem->errors->errors ) ) {
118 return new \WP_Error( 'filesystem_error', __( 'Filesystem error.', 'imagify' ), $this->filesystem->errors );
119 }
120
121 if ( ! $this->filesystem->exists( $this->path ) ) {
122 return new \WP_Error(
123 'not_exists',
124 sprintf(
125 /* translators: %s is a file path. */
126 __( 'The file %s does not seem to exist.', 'imagify' ),
127 '<code>' . esc_html( $this->filesystem->make_path_relative( $this->path ) ) . '</code>'
128 )
129 );
130 }
131
132 if ( ! $this->filesystem->is_file( $this->path ) ) {
133 return new \WP_Error(
134 'not_a_file',
135 sprintf(
136 /* translators: %s is a file path. */
137 __( 'This does not seem to be a file: %s.', 'imagify' ),
138 '<code>' . esc_html( $this->filesystem->make_path_relative( $this->path ) ) . '</code>'
139 )
140 );
141 }
142
143 if ( ! $this->filesystem->is_writable( $this->path ) ) {
144 return new \WP_Error(
145 'not_writable',
146 sprintf(
147 /* translators: %s is a file path. */
148 __( 'The file %s does not seem to be writable.', 'imagify' ),
149 '<code>' . esc_html( $this->filesystem->make_path_relative( $this->path ) ) . '</code>'
150 )
151 );
152 }
153
154 $parent_folder = $this->filesystem->dir_path( $this->path );
155
156 if ( ! $this->filesystem->is_writable( $parent_folder ) ) {
157 return new \WP_Error(
158 'folder_not_writable',
159 sprintf(
160 /* translators: %s is a file path. */
161 __( 'The folder %s does not seem to be writable.', 'imagify' ),
162 '<code>' . esc_html( $this->filesystem->make_path_relative( $parent_folder ) ) . '</code>'
163 )
164 );
165 }
166
167 return true;
168 }
169
170
171 /** ----------------------------------------------------------------------------------------- */
172 /** EDITION ================================================================================= */
173 /** ----------------------------------------------------------------------------------------- */
174
175 /**
176 * Resize (and rotate) an image if it is bigger than the maximum width provided.
177 *
178 * @since 1.9
179 * @access public
180 * @author Grégory Viguier
181 * @author Remy Perona
182 *
183 * @param array $dimensions {
184 * Array of image dimensions.
185 *
186 * @type int $width The image width.
187 * @type int $height The image height.
188 * }
189 * @param int $max_width Maximum width to resize to.
190 * @return string|WP_Error Path the the resized image. A WP_Error object on failure.
191 */
192 public function resize( $dimensions = [], $max_width = 0 ) {
193 $can_be_processed = $this->can_be_processed();
194
195 if ( is_wp_error( $can_be_processed ) ) {
196 return $can_be_processed;
197 }
198
199 if ( ! $max_width ) {
200 return new \WP_Error(
201 'no_resizing_threshold',
202 __( 'No threshold provided for resizing.', 'imagify' )
203 );
204 }
205
206 if ( ! $this->is_image() ) {
207 return new \WP_Error(
208 'not_an_image',
209 sprintf(
210 /* translators: %s is a file path. */
211 __( 'The file %s does not seem to be an image, and cannot be resized.', 'imagify' ),
212 '<code>' . esc_html( $this->filesystem->make_path_relative( $this->path ) ) . '</code>'
213 )
214 );
215 }
216
217 $editor = $this->get_editor();
218
219 if ( is_wp_error( $editor ) ) {
220 return $editor;
221 }
222
223 // Try to correct the auto-rotation if the info is available.
224 if ( $this->filesystem->can_get_exif() && 'image/jpeg' === $this->get_mime_type() ) {
225 $exif = $this->filesystem->get_image_exif( $this->path );
226 $orientation = isset( $exif['Orientation'] ) ? (int) $exif['Orientation'] : 1;
227
228 switch ( $orientation ) {
229 case 2:
230 // Flip horizontally.
231 $editor->flip( true, false );
232 break;
233 case 3:
234 // Rotate 180 degrees or flip horizontally and vertically.
235 // Flipping seems faster/uses less resources.
236 $editor->flip( true, true );
237 break;
238 case 4:
239 // Flip vertically.
240 $editor->flip( false, true );
241 break;
242 case 5:
243 // Rotate 90 degrees counter-clockwise and flip vertically.
244 $result = $editor->rotate( 90 );
245
246 if ( ! is_wp_error( $result ) ) {
247 $editor->flip( false, true );
248 }
249 break;
250 case 6:
251 // Rotate 90 degrees clockwise (270 counter-clockwise).
252 $editor->rotate( 270 );
253 break;
254 case 7:
255 // Rotate 90 degrees counter-clockwise and flip horizontally.
256 $result = $editor->rotate( 90 );
257
258 if ( ! is_wp_error( $result ) ) {
259 $editor->flip( true, false );
260 }
261 break;
262 case 8:
263 // Rotate 90 degrees counter-clockwise.
264 $editor->rotate( 90 );
265 break;
266 }
267 }
268
269 if ( ! $dimensions ) {
270 $dimensions = $this->get_dimensions();
271 }
272
273 // Prevent removal of the exif data when resizing (only works with Imagick).
274 add_filter( 'image_strip_meta', '__return_false', 789 );
275
276 // Resize.
277 $new_sizes = wp_constrain_dimensions( $dimensions['width'], $dimensions['height'], $max_width );
278 $resized = $editor->resize( $new_sizes[0], $new_sizes[1], false );
279
280 // Remove the filter when we're done to prevent any conflict.
281 remove_filter( 'image_strip_meta', '__return_false', 789 );
282
283 if ( is_wp_error( $resized ) ) {
284 return $resized;
285 }
286
287 $resized_image_path = $editor->generate_filename( 'imagifyresized' );
288 $resized_image_saved = $editor->save( $resized_image_path );
289
290 if ( is_wp_error( $resized_image_saved ) ) {
291 return $resized_image_saved;
292 }
293
294 return $resized_image_path;
295 }
296
297 /**
298 * Create a thumbnail.
299 * Warning: If the destination file already exists, it will be overwritten.
300 *
301 * @since 1.9
302 * @access protected
303 * @author Grégory Viguier
304 *
305 * @param array $destination {
306 * The thumbnail data.
307 *
308 * @type string $path Path to the destination file.
309 * @type int $width The image width.
310 * @type int $height The image height.
311 * @type bool $crop True to crop, false to resize.
312 * @type bool $adjust_filename True to adjust the file name like what `$editor->multi_resize()` returns, like WP default behavior (default). False to prevent it, and use the file name from $path instead.
313 * }
314 * @return bool|array|WP_Error {
315 * A WP_Error object on error. True if the file exists.
316 * An array of thumbnail data if the file has just been created:
317 *
318 * @type string $file File name.
319 * @type int $width The image width.
320 * @type int $height The image height.
321 * @type string $mime-type The mime type.
322 * }
323 */
324 public function create_thumbnail( $destination ) {
325 $can_be_processed = $this->can_be_processed();
326
327 if ( is_wp_error( $can_be_processed ) ) {
328 return $can_be_processed;
329 }
330
331 if ( ! $this->is_image() ) {
332 return new \WP_Error(
333 'not_an_image',
334 sprintf(
335 /* translators: %s is a file path. */
336 __( 'The file %s does not seem to be an image, and cannot be resized.', 'imagify' ),
337 '<code>' . esc_html( $this->filesystem->make_path_relative( $this->path ) ) . '</code>'
338 )
339 );
340 }
341
342 $editor = $this->get_editor();
343
344 if ( is_wp_error( $editor ) ) {
345 return $editor;
346 }
347
348 // Create the file.
349 $result = $editor->multi_resize( [ $destination ] );
350
351 if ( ! $result ) {
352 return new \WP_Error( 'image_resize_error', __( 'The thumbnail could not be created.', 'imagify' ) );
353 }
354
355 $result = reset( $result );
356
357 $filename = $result['file'];
358 $source_thumb_path = $this->filesystem->dir_path( $this->path ) . $filename;
359
360 if ( ! isset( $destination['adjust_filename'] ) || $destination['adjust_filename'] ) {
361 // The file name can change from what we expected (1px wider, etc), let's use the resulting data to move the file to the right place.
362 $destination_thumb_path = $this->filesystem->dir_path( $destination['path'] ) . $filename;
363 } else {
364 // Respect what is set in $path.
365 $destination_thumb_path = $destination['path'];
366 $result['file'] = $this->filesystem->file_name( $destination['path'] );
367 }
368
369 if ( $source_thumb_path === $destination_thumb_path ) {
370 return $result;
371 }
372
373 $moved = $this->filesystem->move( $source_thumb_path, $destination_thumb_path, true );
374
375 if ( ! $moved ) {
376 return new \WP_Error( 'move_error', __( 'The file could not be moved to its final destination.', 'imagify' ) );
377 }
378
379 return $result;
380 }
381
382 /**
383 * Backup a file.
384 *
385 * @since 1.9
386 * @since 1.9.8 Added $backup_source argument.
387 * @access public
388 * @author Grégory Viguier
389 *
390 * @param string $backup_path The backup path.
391 * @param string $backup_source Path to the file to backup. This is useful in WP 5.3+ when we want to optimize the full size: in that case we need to backup the original file.
392 * @return bool|WP_Error True on success. False if the backup option is disabled. A WP_Error object on failure.
393 */
394 public function backup( $backup_path = null, $backup_source = null ) {
395 $can_be_processed = $this->can_be_processed();
396
397 if ( is_wp_error( $can_be_processed ) ) {
398 return $can_be_processed;
399 }
400
401 // Make sure the backups directory has no errors.
402 if ( ! $backup_path ) {
403 return new \WP_Error( 'wp_upload_error', __( 'Error while retrieving the backups directory path.', 'imagify' ) );
404 }
405
406 // Create sub-directories.
407 $created = $this->filesystem->make_dir( $this->filesystem->dir_path( $backup_path ) );
408
409 if ( ! $created ) {
410 return new \WP_Error( 'backup_dir_not_writable', __( 'The backup directory is not writable.', 'imagify' ) );
411 }
412
413 $path = $backup_source && $this->filesystem->exists( $backup_source ) ? $backup_source : $this->path;
414
415 /**
416 * Allow to overwrite the backup file if it already exists.
417 *
418 * @since 1.6.9
419 * @author Grégory Viguier
420 *
421 * @param bool $overwrite Whether to overwrite the backup file.
422 * @param string $path The file path.
423 * @param string $backup_path The backup path.
424 */
425 $overwrite = apply_filters( 'imagify_backup_overwrite_backup', false, $path, $backup_path );
426
427 // Copy the file.
428 $this->filesystem->copy( $path, $backup_path, $overwrite, FS_CHMOD_FILE );
429
430 // Make sure the backup copy exists.
431 if ( ! $this->filesystem->exists( $backup_path ) ) {
432 return new \WP_Error( 'backup_doesnt_exist', __( 'The file could not be saved.', 'imagify' ), array(
433 'file_path' => $this->filesystem->make_path_relative( $path ),
434 'backup_path' => $this->filesystem->make_path_relative( $backup_path ),
435 ) );
436 }
437
438 return true;
439 }
440
441 /**
442 * Optimize a file with Imagify.
443 *
444 * @since 1.9
445 * @access public
446 * @author Grégory Viguier
447 *
448 * @param array $args {
449 * Optional. An array of arguments.
450 *
451 * @type bool $backup False to prevent backup. True to follow the user's setting. A backup can't be forced.
452 * @type string $backup_path If a backup must be done, this is the path to use. Default is the backup path used for the WP Media Library.
453 * @type int $optimization_level The optimization level (2=ultra, 1=aggressive, 0=normal).
454 * @type bool $keep_exif To keep exif data or not.
455 * @type string $convert Set to 'webp' to convert the image to webp.
456 * @type string $context The context.
457 * @type int $original_size The file size, sent to the API.
458 * }
459 * @return \sdtClass|\WP_Error Optimized image data. A \WP_Error object on error.
460 */
461 public function optimize( $args = [] ) {
462 $args = array_merge( [
463 'backup' => true,
464 'backup_path' => null,
465 'backup_source' => null,
466 'optimization_level' => 0,
467 'keep_exif' => true,
468 'convert' => '',
469 'context' => 'wp',
470 'original_size' => 0,
471 ], $args );
472
473 $can_be_processed = $this->can_be_processed();
474
475 if ( is_wp_error( $can_be_processed ) ) {
476 return $can_be_processed;
477 }
478
479 // Check if external HTTP requests are blocked.
480 if ( \Imagify_Requirements::is_imagify_blocked() ) {
481 return new \WP_Error( 'http_block_external', __( 'External HTTP requests are blocked.', 'imagify' ) );
482 }
483
484 /**
485 * Fires before a media file optimization.
486 *
487 * @since 1.9
488 * @author Grégory Viguier
489 *
490 * @param string $path Absolute path to the media file.
491 * @param array $args Arguments passed to the method.
492 */
493 do_action( 'imagify_before_optimize_file', $this->path, $args );
494
495 /**
496 * Fires before to optimize the Image with Imagify.
497 *
498 * @since 1.0
499 * @deprecated
500 *
501 * @param string $path Absolute path to the image file.
502 * @param bool $backup True if a backup will be make.
503 */
504 do_action_deprecated( 'before_do_imagify', [ $this->path, $args['backup'] ], '1.9', 'imagify_before_optimize_file' );
505
506 if ( $args['backup'] ) {
507 $backup_result = $this->backup( $args['backup_path'], $args['backup_source'] );
508
509 if ( is_wp_error( $backup_result ) ) {
510 // Stop the process if we can't backup the file.
511 return $backup_result;
512 }
513 }
514
515 // Send file for optimization and fetch the response.
516 $data = [
517 'normal' => 0 === $args['optimization_level'],
518 'aggressive' => 1 === $args['optimization_level'],
519 'ultra' => 2 === $args['optimization_level'],
520 'keep_exif' => $args['keep_exif'],
521 'original_size' => $args['original_size'],
522 'context' => $args['context'],
523 ];
524
525 if ( $args['convert'] ) {
526 $data['convert'] = $args['convert'];
527 }
528
529 $response = upload_imagify_image( [
530 'image' => $this->path,
531 'data' => wp_json_encode( $data ),
532 ] );
533
534 if ( is_wp_error( $response ) ) {
535 return new \WP_Error( 'api_error', $response->get_error_message() );
536 }
537
538 if ( ! function_exists( 'download_url' ) ) {
539 require_once ABSPATH . 'wp-admin/includes/file.php';
540 }
541
542 $temp_file = download_url( $response->image );
543
544 if ( is_wp_error( $temp_file ) ) {
545 return new \WP_Error( 'temp_file_not_found', $temp_file->get_error_message() );
546 }
547
548 if ( 'webp' === $args['convert'] ) {
549 $destination_path = $this->get_path_to_webp();
550 $this->path = $destination_path;
551 $this->file_type = null;
552 $this->editor = null;
553 } else {
554 $destination_path = $this->path;
555 }
556
557 $moved = $this->filesystem->move( $temp_file, $destination_path, true );
558
559 if ( ! $moved ) {
560 return new \WP_Error( 'move_error', __( 'The file could not be moved to its final destination.', 'imagify' ) );
561 }
562
563 /**
564 * Fires after to optimize the Image with Imagify.
565 *
566 * @since 1.0
567 * @deprecated
568 *
569 * @param string $path Absolute path to the image file.
570 * @param bool $backup True if a backup has been made.
571 */
572 do_action_deprecated( 'after_do_imagify', [ $this->path, $args['backup'] ], '1.9', 'imagify_before_optimize_file' );
573
574 /**
575 * Fires after a media file optimization.
576 *
577 * @since 1.9
578 * @author Grégory Viguier
579 *
580 * @param string $path Absolute path to the media file.
581 * @param array $args Arguments passed to the method.
582 */
583 do_action( 'imagify_after_optimize_file', $this->path, $args );
584
585 return $response;
586 }
587
588
589 /** ----------------------------------------------------------------------------------------- */
590 /** IMAGE EDITOR (GD/IMAGEMAGICK) =========================================================== */
591 /** ----------------------------------------------------------------------------------------- */
592
593 /**
594 * Get an image editor instance (WP_Image_Editor_Imagick, WP_Image_Editor_GD).
595 *
596 * @since 1.9
597 * @access protected
598 * @author Grégory Viguier
599 *
600 * @return WP_Image_Editor_Imagick|WP_Image_Editor_GD|WP_Error
601 */
602 protected function get_editor() {
603 if ( isset( $this->editor ) ) {
604 return $this->editor;
605 }
606
607 $this->editor = wp_get_image_editor( $this->path, [
608 'methods' => $this->get_editor_methods(),
609 ] );
610
611 if ( ! is_wp_error( $this->editor ) ) {
612 return $this->editor;
613 }
614
615 $this->editor = new \WP_Error(
616 'image_editor',
617 sprintf(
618 /* translators: %1$s is an error message, %2$s is a "More info?" link. */
619 __( 'No php extensions are available to edit images on the server. ImageMagick or GD is required. The internal error is: %1$s. %2$s', 'imagify' ),
620 $this->editor->get_error_message(),
621 '<a href="' . esc_url( imagify_get_external_url( 'documentation-imagick-gd' ) ) . '" target="_blank">' . __( 'More info?', 'imagify' ) . '</a>'
622 )
623 );
624
625 return $this->editor;
626 }
627
628 /**
629 * Get the image editor methods we will use.
630 *
631 * @since 1.9
632 * @access protected
633 * @author Grégory Viguier
634 *
635 * @return array
636 */
637 protected function get_editor_methods() {
638 static $methods;
639
640 if ( isset( $methods ) ) {
641 return $methods;
642 }
643
644 $methods = [
645 'resize',
646 'multi_resize',
647 'generate_filename',
648 'save',
649 ];
650
651 if ( $this->filesystem->can_get_exif() ) {
652 $methods[] = 'rotate';
653 }
654
655 return $methods;
656 }
657
658
659 /** ----------------------------------------------------------------------------------------- */
660 /** VARIOUS TOOLS =========================================================================== */
661 /** ----------------------------------------------------------------------------------------- */
662
663 /**
664 * Check if a file exceeds the weight limit (> 5mo).
665 *
666 * @since 1.9
667 * @access public
668 * @author Grégory Viguier
669 *
670 * @return bool
671 */
672 public function is_exceeded() {
673 if ( ! $this->is_valid() ) {
674 return false;
675 }
676
677 $size = $this->filesystem->size( $this->path );
678
679 return $size > IMAGIFY_MAX_BYTES;
680 }
681
682 /**
683 * Tell if the current file is supported for a given context.
684 *
685 * @since 1.9
686 * @access public
687 * @see imagify_get_mime_types()
688 * @author Grégory Viguier
689 *
690 * @param array $allowed_mime_types A list of allowed mime types.
691 * @return bool
692 */
693 public function is_supported( $allowed_mime_types ) {
694 return in_array( $this->get_mime_type(), $allowed_mime_types, true );
695 }
696
697 /**
698 * Tell if the file is an image.
699 *
700 * @since 1.9
701 * @access public
702 * @author Grégory Viguier
703 *
704 * @return bool
705 */
706 public function is_image() {
707 if ( isset( $this->is_image ) ) {
708 return $this->is_image;
709 }
710
711 $this->is_image = strpos( $this->get_mime_type(), 'image/' ) === 0;
712
713 return $this->is_image;
714 }
715
716 /**
717 * Tell if the file is a pdf.
718 *
719 * @since 1.9
720 * @access public
721 * @author Grégory Viguier
722 *
723 * @return bool
724 */
725 public function is_pdf() {
726 return 'application/pdf' === $this->get_mime_type();
727 }
728
729 /**
730 * Get the file mime type.
731 *
732 * @since 1.9
733 * @access public
734 * @author Grégory Viguier
735 *
736 * @return string
737 */
738 public function get_mime_type() {
739 return $this->get_file_type()->type;
740 }
741
742 /**
743 * Get the file extension.
744 *
745 * @since 1.9
746 * @access public
747 * @author Grégory Viguier
748 *
749 * @return string|null
750 */
751 public function get_extension() {
752 return $this->get_file_type()->ext;
753 }
754
755 /**
756 * Get the file path.
757 *
758 * @since 1.9
759 * @access public
760 * @author Grégory Viguier
761 *
762 * @return string
763 */
764 public function get_path() {
765 return $this->path;
766 }
767
768 /**
769 * Replace the file extension by webp.
770 *
771 * @since 1.9
772 * @access public
773 * @author Grégory Viguier
774 *
775 * @return string|bool The file path on success. False if not an image or on failure.
776 */
777 public function get_path_to_webp() {
778 if ( ! $this->is_image() ) {
779 return false;
780 }
781
782 if ( $this->is_webp() ) {
783 return false;
784 }
785
786 return imagify_path_to_webp( $this->path );
787 }
788
789 /**
790 * Tell if the file is a webp image.
791 * Rejects "path/to/.webp" files.
792 *
793 * @since 1.9
794 * @access public
795 * @author Grégory Viguier
796 *
797 * @return bool
798 */
799 public function is_webp() {
800 return preg_match( '@(?!^|/|\\\)\.webp$@i', $this->path );
801 }
802
803 /**
804 * Get the file mime type + file extension.
805 *
806 * @since 1.9
807 * @access protected
808 * @see wp_check_filetype()
809 * @author Grégory Viguier
810 *
811 * @return object {
812 * @type string $ext The file extension.
813 * @type string $type The mime type.
814 * }
815 */
816 protected function get_file_type() {
817 if ( isset( $this->file_type ) ) {
818 return $this->file_type;
819 }
820
821 $this->file_type = (object) [
822 'ext' => '',
823 'type' => '',
824 ];
825
826 if ( ! $this->is_valid() ) {
827 return $this->file_type;
828 }
829
830 $this->file_type = (object) wp_check_filetype( $this->path );
831
832 return $this->file_type;
833 }
834
835 /**
836 * If the media is an image, get its width and height.
837 *
838 * @since 1.9
839 * @access public
840 * @author Grégory Viguier
841 *
842 * @return array
843 */
844 public function get_dimensions() {
845 if ( ! $this->is_image() ) {
846 return [
847 'width' => 0,
848 'height' => 0,
849 ];
850 }
851
852 $values = $this->filesystem->get_image_size( $this->path );
853
854 return [
855 'width' => $values['width'],
856 'height' => $values['height'],
857 ];
858 }
859
860 /**
861 * Get a plugin’s option.
862 *
863 * @since 1.9
864 * @access protected
865 * @author Grégory Viguier
866 *
867 * @param string $option_name The option nme.
868 * @return mixed
869 */
870 protected function get_option( $option_name ) {
871 if ( isset( $this->options[ $option_name ] ) ) {
872 return $this->options[ $option_name ];
873 }
874
875 $this->options[ $option_name ] = get_imagify_option( $option_name );
876
877 return $this->options[ $option_name ];
878 }
879 }
880