PluginProbe
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization / trunk
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization vtrunk
4.2.14 4.2.13 4.2.12 4.2.11 4.2.10 4.2.9 4.2.8 4.2.7 4.2.6 4.2.5 2.5.5 2.5.6 2.5.7 3.0.0 3.0.1 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.11.0 3.11.1 3.11.2 3.11.3 3.12.0 All 135 releases
← All changes | inc/dam.php +86 -266 3.10.0 → trunk View file →
@@ -8,12 +8,17 @@
8 8 * @package \Optimole\Inc
9 9 * @author Optimole <[email protected]>
10 10 */
11 11
12 +use Optimole\Sdk\Resource\ImageProperty\GravityProperty;
13 +use Optimole\Sdk\Resource\ImageProperty\ResizeTypeProperty;
14 +use Optimole\Sdk\ValueObject\Position;
15 +
12 16 /**
13 17 * Class Optml_Dam
14 18 */
15 19 class Optml_Dam {
20 + use Optml_Dam_Offload_Utils;
16 21 use Optml_Normalizer;
17 22
18 23 /**
19 24 * Hold the settings object.
@@ -45,25 +50,24 @@
45 50
46 51 if ( $this->settings->get( 'cloud_images' ) === 'enabled' ) {
47 52 add_action( 'admin_menu', [ $this, 'add_menu' ] );
48 53 add_action( 'print_media_templates', [ $this, 'print_media_template' ] );
49 - add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_media_scripts' ] );
54 + add_action( 'wp_enqueue_media', [ $this, 'enqueue_media_scripts' ] );
50 55 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_page_scripts' ] );
51 -
52 - // Needed for this to work with elementor.
53 - add_action( 'elementor/editor/after_enqueue_scripts', [ $this, 'enqueue_media_scripts' ] );
54 56 }
55 57
56 - if ( defined( 'OPTML_DAM_ENDPOINT' ) && constant( 'OPTML_DAM_ENDPOINT' ) ) {
58 + if ( defined( 'OPTML_DAM_ENDPOINT' ) ) {
57 59 $this->dam_endpoint = constant( 'OPTML_DAM_ENDPOINT' );
58 60 }
59 -
61 + if ( $this->settings->get( 'retina_images' ) === 'enabled' ) {
62 + add_filter( 'wp_get_attachment_image_attributes', [ Optml_Tag_Replacer::instance(), 'filter_attachment_image_attributes' ], 99, 3 );
63 + }
60 64 add_filter( 'wp_get_attachment_image_src', [ $this, 'alter_attachment_image_src' ], 10, 4 );
61 65 add_filter( 'wp_get_attachment_metadata', [ $this, 'alter_attachment_metadata' ], 10, 2 );
62 66 add_filter( 'image_downsize', [ $this, 'catch_downsize' ], 10, 3 );
63 - add_filter( 'wp_prepare_attachment_for_js', [$this, 'alter_attachment_for_js'], 10, 3 );
64 - add_filter( 'wp_image_src_get_dimensions', [$this, 'alter_img_tag_w_h'], 10, 4 );
65 - add_filter( 'get_attached_file', [$this, 'alter_attached_file_response'], 10, 2 );
67 + add_filter( 'wp_prepare_attachment_for_js', [ $this, 'alter_attachment_for_js' ], 10, 3 );
68 + add_filter( 'get_attached_file', [ $this, 'alter_attached_file_response' ], 10, 2 );
69 + add_filter( 'wp_calculate_image_srcset', [ $this, 'disable_dam_images_srcset' ], 1, 5 );
66 70
67 71 add_filter(
68 72 'elementor/image_size/get_attachment_image_html',
69 73 [
@@ -174,9 +178,9 @@
174 178 return $id;
175 179 }
176 180
177 181 /**
178 - * Catch image downsize for the DAM imported images.
182 + * Alter attachment image src for DAM imported images.
179 183 *
180 184 * @param array|false $image {
181 185 * Array of image data.
182 186 *
@@ -192,32 +196,29 @@
192 196 *
193 197 * @return array $image.
194 198 */
195 199 public function alter_attachment_image_src( $image, $attachment_id, $size, $icon ) {
200 +
196 201 // Skip if not DAM image.
197 202 if ( ! $this->is_dam_imported_image( $attachment_id ) ) {
198 203 return $image;
199 204 }
200 -
201 205 $image_url = wp_get_attachment_url( $attachment_id );
202 - $incoming_size = Optml_Media_Offload::parse_dimension_from_optimized_url( $image_url );
203 - $width = $incoming_size[0];
204 - $height = $incoming_size[1];
206 + list($width, $height) = $this->parse_dimension_from_optimized_url( $image_url );
205 207
206 208 // Skip resize in single attachment view on backend.
207 209 if ( $this->is_attachment_edit_page( $attachment_id ) ) {
208 210 return [
209 211 $image_url,
210 - $width,
211 - $height,
212 + $width === 'auto' ? false : $width,
213 + $height === 'auto' ? false : $height,
212 214 false,
213 215 ];
214 216 }
215 217
218 + $metadata = wp_get_attachment_metadata( $attachment_id );
216 219 // Use the original size if the requested size is full.
217 220 if ( $size === 'full' ) {
218 - $metadata = wp_get_attachment_metadata( $attachment_id );
219 -
220 221 $image_url = $this->replace_dam_url_args(
221 222 [
222 223 'width' => $metadata['width'],
223 224 'height' => $metadata['height'],
@@ -232,131 +233,27 @@
232 233 $metadata['height'],
233 234 false,
234 235 ];
235 236 }
237 + $sizes = $this->size_to_dimension( $size, $metadata );
236 238
237 - $crop = false;
238 -
239 - // Size can be int [] containing width and height.
240 - if ( is_array( $size ) ) {
241 - $width = $size[0];
242 - $height = $size[1];
243 - $crop = true;
244 - } else {
245 - $sizes = $this->get_all_image_sizes();
246 -
247 - if ( ! isset( $sizes[ $size ] ) ) {
248 - return [
249 - $image_url,
250 - $width,
251 - $height,
252 - false,
253 - ];
254 - }
255 -
256 - $width = $sizes[ $size ]['width'];
257 - $height = $sizes[ $size ]['height'];
258 - $crop = (bool) $sizes[ $size ]['crop'];
259 - }
260 -
261 239 $image_url = $this->replace_dam_url_args(
262 240 [
263 - 'width' => $width,
264 - 'height' => $height,
265 - 'crop' => $crop,
241 + 'width' => $sizes['width'],
242 + 'height' => $sizes['height'],
243 + 'crop' => $sizes['resize'] ?? false,
266 244 ],
267 245 $image_url
268 246 );
269 -
270 247 return [
271 248 $image_url,
272 - $width,
273 - $height,
274 - $crop,
249 + $sizes['width'],
250 + $sizes['height'],
251 + $size === 'full', // @phpstan-ignore-line
275 252 ];
276 253 }
277 254
278 255 /**
279 - * Get all registered image sizes.
280 - *
281 - * @return array
282 - */
283 - private function get_all_image_sizes() {
284 - $additional_sizes = wp_get_additional_image_sizes();
285 - $intermediate = get_intermediate_image_sizes();
286 - $all = [];
287 -
288 - foreach ( $intermediate as $size ) {
289 - if ( isset( $additional_sizes[ $size ] ) ) {
290 - $all[ $size ] = [
291 - 'width' => $additional_sizes[ $size ]['width'],
292 - 'height' => $additional_sizes[ $size ]['height'],
293 - 'crop' => isset( $additional_sizes[ $size ]['crop'] ) ? $additional_sizes[ $size ]['crop'] : false,
294 - ];
295 - } else {
296 - $all[ $size ] = [
297 - 'width' => (int) get_option( $size . '_size_w' ),
298 - 'height' => (int) get_option( $size . '_size_h' ),
299 - 'crop' => (bool) get_option( $size . '_crop' ),
300 - ];
301 - }
302 -
303 - if ( ! empty( $additional_sizes[ $size ]['crop'] ) ) {
304 - $all[ $size ]['crop'] = $additional_sizes[ $size ]['crop'];
305 - } else {
306 - $all[ $size ]['crop'] = (bool) get_option( $size . '_crop' );
307 - }
308 - }
309 -
310 - return $all;
311 - }
312 -
313 - /**
314 - * Check if we're in the attachment edit page.
315 - *
316 - * /wp-admin/post.php?post=<id>&action=edit
317 - *
318 - * Send whatever comes from the DAM.
319 - *
320 - * @param int $attachment_id attachment id.
321 - *
322 - * @return bool
323 - */
324 - private function is_attachment_edit_page( $attachment_id ) {
325 - if ( ! is_admin() ) {
326 - return false;
327 - }
328 -
329 - $screen = get_current_screen();
330 -
331 - if ( ! isset( $screen->base ) ) {
332 - return false;
333 - }
334 -
335 - if ( $screen->base !== 'post' ) {
336 - return false;
337 - }
338 -
339 - if ( $screen->post_type !== 'attachment' ) {
340 - return false;
341 - }
342 -
343 - if ( $screen->id !== 'attachment' ) {
344 - return false;
345 - }
346 -
347 - if ( ! isset( $_GET['post'] ) ) {
348 - return false;
349 - }
350 -
351 - if ( (int) sanitize_text_field( $_GET['post'] ) !== $attachment_id ) {
352 - return false;
353 - }
354 -
355 - return true;
356 - }
357 -
358 - /**
359 256 * Alter the attachment metadata.
360 257 *
361 258 * @param array $metadata attachment metadata.
362 259 * @param int $id attachment ID.
@@ -367,51 +264,9 @@
367 264 if ( ! $this->is_dam_imported_image( $id ) ) {
368 265 return $metadata;
369 266 }
370 267
371 - $sizes = $this->get_all_image_sizes();
372 -
373 - $post = get_post( $id );
374 -
375 - $sizes_meta = [];
376 -
377 - // SVG files don't have a width/height so we add a dummy one. These are vector images so it doesn't matter.
378 - $is_svg = ( $post->post_mime_type === Optml_Config::$image_extensions['svg'] );
379 -
380 - if ( $is_svg ) {
381 - $metadata['width'] = 150;
382 - $metadata['height'] = 150;
383 - }
384 -
385 - if ( ! isset( $metadata['height'] ) || ! isset( $metadata['width'] ) ) {
386 - return $metadata;
387 - }
388 -
389 - foreach ( $sizes as $size => $args ) {
390 -
391 - // check if the image is portrait or landscape using attachment metadata.
392 - $is_portrait = $metadata['height'] > $metadata['width'];
393 -
394 - // proportionally set the width/height based on this if image is uncropped.
395 - if ( ! (bool) $args['crop'] ) {
396 - if ( $is_portrait ) {
397 - $args['width'] = (int) ( $args['height'] * round( $metadata['width'] / $metadata['height'] ) );
398 - } else {
399 - $args['height'] = (int) ( $args['width'] * round( $metadata['height'] / $metadata['width'] ) );
400 - }
401 - }
402 -
403 - $sizes_meta[ $size ] = [
404 - 'file' => $metadata['file'],
405 - 'width' => $args['width'],
406 - 'height' => $args['height'],
407 - 'mime-type' => $post->post_mime_type,
408 - ];
409 - }
410 -
411 - $metadata['sizes'] = $sizes_meta;
412 -
413 - return $metadata;
268 + return $this->get_altered_metadata_for_remote_images( $metadata, $id );
414 269 }
415 270
416 271 /**
417 272 * Check if the images are already imported.
@@ -529,25 +384,8 @@
529 384 return $map;
530 385 }
531 386
532 387 /**
533 - * Checks that the attachment is a DAM image.
534 - *
535 - * @param int $post_id The attachment ID.
536 - *
537 - * @return bool
538 - */
539 - private function is_dam_imported_image( $post_id ) {
540 - $meta = get_post_meta( $post_id, self::OM_DAM_IMPORTED_FLAG, true );
541 -
542 - if ( empty( $meta ) ) {
543 - return false;
544 - }
545 -
546 - return true;
547 - }
548 -
549 - /**
550 388 * Adds menu item for DAM.
551 389 *
552 390 * @return void
553 391 */
@@ -585,12 +423,17 @@
585 423 * @return void
586 424 */
587 425 public function render_dashboard_page() {
588 426 ?>
589 - <iframe id="om-dam" style="display: none;" src="<?php echo( $this->build_iframe_url() ); ?>"></iframe>
427 + <style>
428 + .notice:not(.optml-notice-optin){
429 + display: none !important;
430 + }
431 + </style>
432 + <iframe id="om-dam" style="display: none;" src="<?php echo( $this->build_iframe_url() ); ?>" allow="clipboard-read; clipboard-write"></iframe>
590 433 <div class="om-dam-loader">
591 434 <img src="<?php echo esc_url( OPTML_URL . 'assets/img/logo.png' ); ?>" alt="Optimole Logo"
592 - class="om-dam-logo">
435 + class="om-dam-logo">
593 436 <p><?php echo esc_html__( 'Loading', 'optimole-wp' ); ?>...</p>
594 437 </div>
595 438 <?php
596 439 }
@@ -626,13 +469,16 @@
626 469
627 470 $data = json_encode( $data );
628 471 $data = rtrim( base64_encode( $data ), '=' );
629 472
630 - return add_query_arg(
631 - [
632 - 'data' => $data,
633 - ],
634 - $this->dam_endpoint
473 + return tsdk_translate_link(
474 + add_query_arg(
475 + [
476 + 'data' => $data,
477 + ],
478 + $this->dam_endpoint
479 + ),
480 + 'query'
635 481 );
636 482 }
637 483
638 484 /**
@@ -688,8 +534,10 @@
688 534
689 535 wp_enqueue_script( OPTML_NAMESPACE . '-admin-page' );
690 536
691 537 wp_enqueue_style( OPTML_NAMESPACE . '-admin-page', OPTML_URL . 'assets/build/media/admin-page.css' );
538 +
539 + do_action( 'themeisle_internal_page', OPTML_PRODUCT_SLUG, 'dam' );
692 540 }
693 541
694 542 /**
695 543 * Get localized variables for the media modal.
@@ -754,15 +602,15 @@
754 602
755 603 return $this->replace_dam_url_args( $custom_dimensions, $html );
756 604 }
757 605
758 - $all_sizes = $this->get_all_image_sizes();
606 + $all_sizes = Optml_App_Replacer::image_sizes();
759 607
760 - if ( ! isset( $all_sizes[ $settings['image_size'] ] ) ) {
608 + if ( ! isset( $all_sizes[ $image_size_key ] ) ) {
761 609 return $html;
762 610 }
763 611
764 - return $this->replace_dam_url_args( $all_sizes[ $settings['image_size'] ], $html );
612 + return $this->replace_dam_url_args( $all_sizes[ $image_size_key ], $html );
765 613 }
766 614
767 615 /**
768 616 * Needed as some blocks might use the image sizes.
@@ -777,21 +625,23 @@
777 625 if ( ! $this->is_dam_imported_image( $attachment->ID ) ) {
778 626 return $response;
779 627 }
780 628
781 - $sizes = $this->get_all_image_sizes();
629 + $sizes = Optml_App_Replacer::image_sizes();
782 630
631 + $meta = [];
632 + if ( isset( $response['width'] ) ) {
633 + $meta['width'] = $response['width'];
634 + }
635 + if ( isset( $response['height'] ) ) {
636 + $meta['height'] = $response['height'];
637 + }
783 638 foreach ( $sizes as $size => $args ) {
784 639 if ( isset( $response['sizes'][ $size ] ) ) {
785 640 continue;
786 641 }
642 + $args = $this->size_to_dimension( $size, $meta );
787 643
788 - $args = [
789 - 'height' => $args['height'],
790 - 'width' => $args['width'],
791 - 'crop' => true,
792 - ];
793 -
794 644 $response['sizes'][ $size ] = array_merge(
795 645 $args,
796 646 [
797 647 'url' => $this->replace_dam_url_args( $args, $response['url'] ),
@@ -798,68 +648,14 @@
798 648 'orientation' => ( $args['height'] > $args['width'] ) ? 'portrait' : 'landscape',
799 649 ]
800 650 );
801 651 }
652 + $response['url'] = $this->replace_dam_url_args( $meta, $response['url'] );
802 653
803 - $url_args = [
804 - 'height' => $response['height'],
805 - 'width' => $response['width'],
806 - 'crop' => false,
807 - ];
808 -
809 - $response['url'] = $this->replace_dam_url_args( $url_args, $response['url'] );
810 -
811 654 return $response;
812 655 }
813 656
814 657 /**
815 - * We have to short-circuit the logic that adds width and height to the img tag.
816 - * It compares the URL basename, and the `file` param for each image.
817 - * This happens for any image that gets its size set non-explicitly
818 - * e.g. an image block with its size set from the sidebar to `thumbnail`).
819 - *
820 - * Optimole has a single basename for all image resizes in its URL.
821 - *
822 - * @param array|false $dimensions Array with first element being the width
823 - * and second element being the height, or
824 - * false if dimensions could not be determined.
825 - * @param string $image_src The image URL (will be Optimole URL).
826 - * @param array $image_meta The image metadata.
827 - * @param int $attachment_id The image attachment ID. Default 0.
828 - */
829 - public function alter_img_tag_w_h( $dimensions, $image_src, $image_meta, $attachment_id ) {
830 - if ( ! $this->is_dam_imported_image( $attachment_id ) ) {
831 - return $dimensions;
832 - }
833 -
834 - // Get the dimensions from the optimized URL.
835 - $incoming_size = Optml_Media_Offload::parse_dimension_from_optimized_url( $image_src );
836 - $width = $incoming_size[0];
837 - $height = $incoming_size[1];
838 -
839 - $sizes = $this->get_all_image_sizes();
840 -
841 - // If this is an image size. Return its dimensions.
842 - foreach ( $sizes as $size => $args ) {
843 - if ( (int) $args['width'] !== (int) $width ) {
844 - continue;
845 - }
846 -
847 - if ( (int) $args['height'] !== (int) $height ) {
848 - continue;
849 - }
850 -
851 - return [
852 - $args['width'],
853 - $args['height'],
854 - ];
855 - }
856 -
857 - // Fall-through with the original dimensions.
858 - return $dimensions;
859 - }
860 -
861 - /**
862 658 * Replace the image size params in DAM URLs inside a string.
863 659 *
864 660 * @param array $args The arguments to replace.
865 661 * - width: The width of the image.
@@ -869,18 +665,18 @@
869 665 *
870 666 * @return string
871 667 */
872 668 public function replace_dam_url_args( $args, $subject ) {
873 - $args = wp_parse_args( $args, [ 'width' => 'auto', 'height' => 'auto', 'crop' => false, 'dam' => true] );
669 + $args = wp_parse_args( $args, [ 'width' => 'auto', 'height' => 'auto', 'dam' => true ] );
874 670
875 671 $width = $args['width'];
876 672 $height = $args['height'];
877 - $crop = (bool) $args['crop'];
673 + $crop = $args['crop'] ?? $args['resize'] ?? false;
878 674
879 - $gravity = Optml_Resize::GRAVITY_CENTER;
675 + $gravity = Position::CENTER;
880 676
881 677 if ( $this->settings->get( 'resize_smart' ) === 'enabled' ) {
882 - $gravity = Optml_Resize::GRAVITY_SMART;
678 + $gravity = GravityProperty::SMART;
883 679 }
884 680
885 681 if ( $width === 0 ) {
886 682 $width = 'auto';
@@ -892,10 +688,15 @@
892 688
893 689 // Use the proper replacement for the image size.
894 690 $replacement = '/w:' . $width . '/h:' . $height;
895 691
896 - if ( $crop ) {
692 + if ( $crop === true ) {
897 693 $replacement .= '/g:' . $gravity . '/rt:fill';
694 + } elseif ( is_array( $crop ) && ! empty( $crop ) ) {
695 +
696 + $replacement .= '/' . ( new GravityProperty( $crop['gravity'] ) ) .
697 + '/' . new ResizeTypeProperty( $crop['type'] ) .
698 + ( $crop['enlarge'] ? '/el:1' : '' );
898 699 }
899 700
900 701 $replacement .= '/q:';
901 702
@@ -931,6 +732,25 @@
931 732 return $uploads['basedir'] . '/' . $metadata['file'];
932 733 }
933 734
934 735 return true;
736 + }
737 +
738 + /**
739 + * Alter the srcSet for DAM images.
740 + *
741 + * @param array $sources Initial source array.
742 + * @param array $size_array Requested size.
743 + * @param string $image_src Image source URL.
744 + * @param array $image_meta Image meta data.
745 + * @param int $attachment_id Image attachment ID.
746 + *
747 + * @return array
748 + */
749 + public function disable_dam_images_srcset( $sources, $size_array, $image_src, $image_meta, $attachment_id ) {
750 + if ( ! $this->is_dam_imported_image( $attachment_id ) ) {
751 + return $sources;
752 + }
753 +
754 + return [];
935 755 }
936 756 }