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/app_replacer.php +182 -57 3.1.3 → trunk View file →
@@ -1,6 +1,9 @@
1 1 <?php
2 2
3 +use Optimole\Sdk\Optimole;
4 +use Optimole\Sdk\ValueObject\Position;
5 +
3 6 /**
4 7 * Class Optml_App_Replacer
5 8 *
6 9 * @package \Optml\Inc
@@ -6,13 +9,14 @@
6 9 * @package \Optml\Inc
7 10 * @author Optimole <[email protected]>
8 11 */
9 12 abstract class Optml_App_Replacer {
13 + use Optml_Dam_Offload_Utils;
10 14
11 15 /**
12 16 * Filters used for lazyload.
13 17 *
14 - * @var null Lazyload filters.
18 + * @var array Lazyload filters.
15 19 */
16 20 protected static $filters = null;
17 21 /**
18 22 * Holds an array of image sizes.
@@ -56,19 +60,31 @@
56 60 * @var Optml_Settings $settings
57 61 */
58 62 public $settings = null;
59 63 /**
60 - * Defines which is the maximum width accepted in the optimization process.
64 + * Cached offloading status.
61 65 *
66 + * @var null|bool Offload status.
67 + */
68 + public static $offload_enabled = null;
69 + /**
70 + * Defines if the dimensions should be limited when images are served.
71 + *
72 + * @var bool
73 + */
74 + protected $limit_dimensions_enabled = false;
75 + /**
76 + * Defines which is the maximum width accepted when images are served.
77 + *
62 78 * @var int
63 79 */
64 - protected $max_width = 3000;
80 + protected $limit_width = 1920;
65 81 /**
66 - * Defines which is the maximum width accepted in the optimization process.
82 + * Defines which is the maximum height accepted when images are served.
67 83 *
68 84 * @var int
69 85 */
70 - protected $max_height = 3000;
86 + protected $limit_height = 1080;
71 87 /**
72 88 * Defines if css minification should be used.
73 89 *
74 90 * @var int
@@ -82,9 +98,9 @@
82 98 protected $is_js_minify_on = 0;
83 99 /**
84 100 * A cached version of `wp_upload_dir`
85 101 *
86 - * @var null
102 + * @var null|array
87 103 */
88 104 protected $upload_resource = null;
89 105
90 106 /**
@@ -118,14 +134,14 @@
118 134 * Whether the site is whitelisted or not. Used when signing the urls.
119 135 *
120 136 * @var bool Domains.
121 137 */
122 - protected $is_allowed_site = [];
138 + protected $is_allowed_site = false;
123 139
124 140 /**
125 - * Holds the most recent value for the cache buster.
141 + * Holds the most recent value for the cache buster, updated to hold only for images if active_cache_buster_assets is defined.
126 142 *
127 - * @var string Cache Buster value.
143 + * @var string Cache Buster global value if active_cache_buster_assets is undefined else the value for images.
128 144 */
129 145 protected $active_cache_buster = '';
130 146
131 147 /**
@@ -135,15 +151,21 @@
135 151 */
136 152 protected static $ignored_url_map = [];
137 153
138 154 /**
155 + * Holds the most recent value for the cache buster for assets.
156 + *
157 + * @var string Cache Buster value.
158 + */
159 + protected $active_cache_buster_assets = '';
160 +
161 + /**
139 162 * Returns possible src attributes.
140 163 *
141 164 * @return array
142 165 */
143 166 public static function possible_src_attributes() {
144 -
145 - if ( ! empty( self::$possible_src_attributes ) && is_array( self::$possible_src_attributes ) ) {
167 + if ( null !== self::$possible_src_attributes ) {
146 168 return self::$possible_src_attributes;
147 169 }
148 170
149 171 self::$possible_src_attributes = apply_filters( 'optml_possible_src_attributes', [] );
@@ -156,14 +178,13 @@
156 178 *
157 179 * @return array
158 180 */
159 181 public static function possible_lazyload_flags() {
160 -
161 - if ( ! empty( self::$ignore_lazyload_strings ) && is_array( self::$ignore_lazyload_strings ) ) {
182 + if ( null !== self::$ignore_lazyload_strings ) {
162 183 return self::$ignore_lazyload_strings;
163 184 }
164 185
165 - self::$possible_src_attributes = apply_filters( 'optml_possible_lazyload_flags', [ 'skip-lazy', 'data-skip-lazy' ] );
186 + self::$possible_src_attributes = apply_filters( 'optml_possible_lazyload_flags', [ 'skip-lazy', 'data-skip-lazy', 'data-opt-src' ] );
166 187
167 188 return array_merge( self::$possible_src_attributes, [ '<noscript' ] );
168 189 }
169 190 /**
@@ -171,16 +192,15 @@
171 192 *
172 193 * @return array
173 194 */
174 195 public static function possible_tag_flags() {
175 -
176 - if ( ! empty( self::$ignore_tag_strings ) && is_array( self::$ignore_tag_strings ) ) {
196 + if ( null !== self::$ignore_tag_strings ) {
177 197 return self::$ignore_tag_strings;
178 198 }
179 199
180 200 self::$ignore_tag_strings = apply_filters( 'optml_skip_optimizations_css_classes', [ 'skip-optimization' ] );
181 201
182 - return self::$ignore_tag_strings;
202 + return self::$ignore_tag_strings;
183 203 }
184 204 /**
185 205 * Returns possible data-opt-src ignore flags attributes.
186 206 *
@@ -186,10 +206,9 @@
186 206 *
187 207 * @return array
188 208 */
189 209 public static function possible_data_ignore_flags() {
190 -
191 - if ( ! empty( self::$ignore_data_opt_attribute ) && is_array( self::$ignore_data_opt_attribute ) ) {
210 + if ( null !== self::$ignore_data_opt_attribute ) {
192 211 return self::$ignore_data_opt_attribute;
193 212 }
194 213
195 214 self::$ignore_data_opt_attribute = apply_filters( 'optml_ignore_data_opt_flag', [] );
@@ -201,10 +220,10 @@
201 220 * Size to crop maping.
202 221 *
203 222 * @return array Size mapping.
204 223 */
205 - protected static function size_to_crop() {
206 - if ( ! empty( self::$size_to_crop ) && is_array( self::$size_to_crop ) ) {
224 + public static function size_to_crop() {
225 + if ( ! empty( self::$size_to_crop ) ) {
207 226 return self::$size_to_crop;
208 227 }
209 228
210 229 foreach ( self::image_sizes() as $size_data ) {
@@ -223,16 +242,17 @@
223 242
224 243 /**
225 244 * Set possible custom size.
226 245 *
227 - * @param null $width Width value.
228 - * @param null $height Height Value.
229 - * @param null $crop Croping.
246 + * @param int $width Width value.
247 + * @param int $height Height Value.
248 + * @param bool|array $crop Croping.
230 249 */
231 250 public static function add_size( $width = null, $height = null, $crop = null ) {
232 - if ( empty( $width ) || empty( $height ) ) {
251 + if ( is_null( $width ) || is_null( $height ) ) {
233 252 return;
234 253 }
254 +
235 255 self::$custom_size_buffer[ 'cmole' . $width . $height ] = [
236 256 'width' => (int) $width,
237 257 'height' => (int) $height,
238 258 'enlarge' => true,
@@ -237,9 +257,8 @@
237 257 'height' => (int) $height,
238 258 'enlarge' => true,
239 259 'crop' => $crop,
240 260 ];
241 -
242 261 }
243 262
244 263 /**
245 264 * Returns the array of image sizes since `get_intermediate_image_sizes` and image metadata doesn't include the
@@ -247,11 +266,10 @@
247 266 *
248 267 * @return array
249 268 * @global $wp_additional_image_sizes
250 269 */
251 - protected static function image_sizes() {
252 -
253 - if ( ! empty( self::$image_sizes ) && is_array( self::$image_sizes ) ) {
270 + public static function image_sizes() {
271 + if ( ! empty( self::$image_sizes ) ) {
254 272 return self::$image_sizes;
255 273 }
256 274
257 275 global $_wp_additional_image_sizes;
@@ -303,9 +321,9 @@
303 321 },
304 322 self::$image_sizes
305 323 );
306 324
307 - return is_array( self::$image_sizes ) ? self::$image_sizes : [];
325 + return self::$image_sizes;
308 326 }
309 327
310 328 /**
311 329 * The initialize method.
@@ -315,8 +333,16 @@
315 333 $this->set_properties();
316 334
317 335 self::$filters = $this->settings->get_filters();
318 336 add_filter(
337 + 'optml_should_avif_ext',
338 + function ( $should_avif, $ext ) {
339 + return $ext !== 'svg';
340 + },
341 + 10,
342 + 2
343 + );
344 + add_filter(
319 345 'optml_possible_lazyload_flags',
320 346 function ( $strings = [] ) {
321 347 foreach ( self::$filters[ Optml_Settings::FILTER_TYPE_LAZYLOAD ][ Optml_Settings::FILTER_CLASS ] as $rule_flag => $status ) {
322 348 $strings[] = $rule_flag;
@@ -323,10 +349,9 @@
323 349 }
324 350
325 351 return $strings;
326 352 },
327 - 10,
328 - 2
353 + 10
329 354 );
330 355 add_filter(
331 356 'optml_skip_optimizations_css_classes',
332 357 function ( $strings = [] ) {
@@ -334,11 +359,13 @@
334 359 $strings[] = $rule_flag;
335 360 }
336 361 return $strings;
337 362 },
338 - 10,
339 - 2
363 + 10
340 364 );
365 + if ( self::$offload_enabled === null ) {
366 + self::$offload_enabled = ( new Optml_Settings() )->is_offload_enabled();
367 + }
341 368 }
342 369
343 370
344 371 /**
@@ -352,10 +379,14 @@
352 379 'directory' => $upload_data['basedir'],
353 380 ];
354 381 $this->upload_resource['url_length'] = strlen( $this->upload_resource['url'] );
355 382
356 - $content_parts = parse_url( content_url() );
383 + $content_url = content_url();
357 384
385 + if ( strpos( $content_url, '/' ) === 0 ) {
386 + $content_url = get_site_url() . $content_url;
387 + }
388 + $content_parts = parse_url( $content_url );
358 389 $this->upload_resource['content_path'] = '/';
359 390 $this->upload_resource['content_folder'] = '/';
360 391 if ( isset( $content_parts['path'] ) ) {
361 392 $this->upload_resource['content_path'] = $content_parts['path'];
@@ -372,11 +403,12 @@
372 403 $domain = $service_data['domain'];
373 404 }
374 405 Optml_Config::init(
375 406 [
376 - 'key' => $service_data['cdn_key'],
377 - 'secret' => $service_data['cdn_secret'],
378 - 'domain' => $domain,
407 + 'key' => $service_data['cdn_key'],
408 + 'secret' => $service_data['cdn_secret'],
409 + 'domain' => $domain,
410 + 'api_key' => $this->settings->get( 'api_key' ),
379 411 ]
380 412 );
381 413
382 414 if ( defined( 'OPTML_SITE_MIRROR' ) && constant( 'OPTML_SITE_MIRROR' ) ) {
@@ -384,9 +416,11 @@
384 416 }
385 417
386 418 $this->possible_sources = $this->extract_domain_from_urls(
387 419 array_merge(
388 - [ get_home_url() ],
420 + [
421 + get_home_url(),
422 + ],
389 423 array_values( $this->site_mappings ),
390 424 array_keys( $this->site_mappings )
391 425 )
392 426 );
@@ -391,9 +425,18 @@
391 425 )
392 426 );
393 427
394 428 $this->allowed_sources = $this->extract_domain_from_urls( $service_data['whitelist'] );
395 - $this->active_cache_buster = $this->settings->get( 'cache_buster' );
429 + $this->active_cache_buster = $this->settings->get( 'cache_buster_images' );
430 + $this->active_cache_buster_assets = $this->settings->get( 'cache_buster_assets' );
431 +
432 + if ( empty( $this->active_cache_buster ) ) {
433 + $this->active_cache_buster = $this->settings->get( 'cache_buster' );
434 + }
435 + if ( empty( $this->active_cache_buster_assets ) ) {
436 + $this->active_cache_buster_assets = $this->settings->get( 'cache_buster' );
437 + }
438 +
396 439 // Allways allow Photon urls.
397 440 $this->allowed_sources['i0.wp.com'] = true;
398 441 $this->allowed_sources['i1.wp.com'] = true;
399 442 $this->allowed_sources['i2.wp.com'] = true;
@@ -398,15 +441,18 @@
398 441 $this->allowed_sources['i1.wp.com'] = true;
399 442 $this->allowed_sources['i2.wp.com'] = true;
400 443 $this->is_allowed_site = count( array_diff_key( $this->possible_sources, $this->allowed_sources ) ) > 0;
401 444
402 - $this->max_height = $this->settings->get( 'max_height' );
403 - $this->max_width = $this->settings->get( 'max_width' );
445 + $this->limit_dimensions_enabled = $this->settings->get( 'limit_dimensions' ) === 'enabled';
446 + if ( $this->limit_dimensions_enabled ) {
447 + $this->limit_height = $this->settings->get( 'limit_height' );
448 + $this->limit_width = $this->settings->get( 'limit_width' );
449 + }
404 450
405 451 $this->is_css_minify_on = ( $this->settings->get( 'css_minify' ) === 'enabled' ) ? 1 : 0;
406 452 $this->is_js_minify_on = ( $this->settings->get( 'js_minify' ) === 'enabled' ) ? 1 : 0;
407 453
408 - add_filter( 'optml_strip_image_size_from_url', [ $this, 'strip_image_size_from_url' ], 10, 1 );
454 + add_filter( 'optml_strip_image_size_from_url', [ $this, 'strip_image_size_from_url' ], 10 );
409 455 add_filter(
410 456 'image_resize_dimensions',
411 457 [ __CLASS__, 'listen_to_sizes' ],
412 458 999999,
@@ -416,9 +462,9 @@
416 462
417 463 /**
418 464 * Method to expose upload resource property.
419 465 *
420 - * @return null
466 + * @return null|array
421 467 */
422 468 public function get_upload_resource() {
423 469 return $this->upload_resource;
424 470 }
@@ -434,9 +480,9 @@
434 480 * @param mixed $crop Cropping behaviour.
435 481 *
436 482 * @return mixed Original value.
437 483 */
438 - static function listen_to_sizes( $value, $orig_w, $orig_h, $dest_w, $dest_h, $crop ) {
484 + public static function listen_to_sizes( $value, $orig_w, $orig_h, $dest_w, $dest_h, $crop ) {
439 485 self::add_size( $dest_w, $dest_h, $crop );
440 486
441 487 return $value;
442 488 }
@@ -443,9 +489,9 @@
443 489
444 490 /**
445 491 * Extract domains and use them as keys for fast processing.
446 492 *
447 - * @param array $urls Input urls.
493 + * @param array|null $urls Input urls.
448 494 *
449 495 * @return array Array of domains as keys.
450 496 */
451 497 protected function extract_domain_from_urls( $urls = [] ) {
@@ -482,9 +528,9 @@
482 528
483 529 /**
484 530 * Check if we can replace the url.
485 531 *
486 - * @param string $url Url to change.
532 + * @param string|mixed $url Url to change.
487 533 *
488 534 * @return bool Either we can replace this url or not.
489 535 */
490 536 public function can_replace_url( $url ) {
@@ -492,8 +538,12 @@
492 538 if ( ! is_string( $url ) ) {
493 539 return false; // @codeCoverageIgnore
494 540 }
495 541
542 + if ( $this->url_has_dam_flag( $url ) ) {
543 + return true;
544 + }
545 +
496 546 $url_parts = parse_url( $url );
497 547
498 548 if ( ! isset( $url_parts['host'] ) ) {
499 549 return false;
@@ -519,15 +569,27 @@
519 569 *
520 570 * @return string
521 571 **/
522 572 public function strip_image_size_from_url( $url ) {
523 -
573 + if ( apply_filters( 'optml_should_skip_strip_image_size', false, $url ) === true ) {
574 + return $url;
575 + }
524 576 if ( preg_match( '#(-\d+x\d+(?:_c)?|(@2x))\.(' . implode( '|', array_keys( Optml_Config::$image_extensions ) ) . '){1}$#i', $url, $src_parts ) ) {
525 577 $stripped_url = str_replace( $src_parts[1], '', $url );
578 +
579 + if ( $this->settings->is_offload_enabled() ) {
580 + // Treat offloaded attachments differently.
581 + $id = $this->attachment_url_to_post_id( $stripped_url );
582 +
583 + if ( $id !== 0 && $this->is_new_offloaded_attachment( $id ) ) {
584 + return $stripped_url;
585 + }
586 + }
587 +
526 588 // Extracts the file path to the image minus the base url
527 589 $file_path = substr( $stripped_url, strpos( $stripped_url, $this->upload_resource['url'] ) + $this->upload_resource['url_length'] );
528 590 if ( file_exists( $this->upload_resource['directory'] . $file_path ) ) {
529 - $url = $stripped_url;
591 + return $stripped_url;
530 592 }
531 593 }
532 594
533 595 return $url;
@@ -549,8 +611,17 @@
549 611 $crop = ( isset( $width_height_string[3] ) && $width_height_string[3] === '_c' );
550 612 if ( $width && $height ) {
551 613 return [ $width, $height, $crop ];
552 614 }
615 + } else {
616 + $optimized_args = $this->parse_dimension_from_optimized_url( $src );
617 + if ( $optimized_args[0] !== false || $optimized_args[1] !== false ) {
618 + return [
619 + $optimized_args[0] !== 'auto' ? (int) $optimized_args[0] : false,
620 + $optimized_args[1] !== 'auto' ? (int) $optimized_args[1] : false,
621 + false,
622 + ];
623 + }
553 624 }
554 625
555 626 return [ false, false, false ];
556 627 }
@@ -557,17 +628,71 @@
557 628
558 629 /**
559 630 * Get the optimized urls for the wp media modal.
560 631 *
561 - * @param string $url Original url.
562 - * @param string $table_id The cloud id of the image.
563 - * @param string $width Image width.
564 - * @param string $height Image height.
565 - * @param array $resize Optml crop array.
632 + * @param string $url Original url.
633 + * @param string $table_id The cloud id of the image.
634 + * @param int|string $width Image width.
635 + * @param int|string $height Image height.
636 + * @param array $resize Optml crop array.
566 637 * @return string The optimized url.
567 638 */
568 639 public function get_media_optimized_url( $url, $table_id, $width = 'auto', $height = 'auto', $resize = [] ) {
569 - $optimized_url = ( new Optml_Image( $url, ['width' => $width, 'height' => $height, 'resize' => $resize, 'quality' => $this->settings->get_numeric_quality()], $this->settings->get( 'cache_buster' ) ) )->get_url();
570 - $optimized_url = str_replace( $url, Optml_Media_Offload::KEYS['not_processed_flag'] . 'media_cloud' . '/' . Optml_Media_Offload::KEYS['uploaded_flag'] . $table_id . '/' . $url, $optimized_url );
571 - return $optimized_url;
640 + return str_replace( $url, Optml_Media_Offload::KEYS['not_processed_flag'] . 'media_cloud' . '/' . Optml_Media_Offload::KEYS['uploaded_flag'] . $table_id . '/' . $url, $this->get_optimized_image_url( $url, $width, $height, $resize ) );
641 + }
642 +
643 + /**
644 + * Test that the url has the dam flag.
645 + *
646 + * @param string $url The image URL to check.
647 + *
648 + * @return bool
649 + */
650 + public function url_has_dam_flag( $url ) {
651 + return strpos( $url, Optml_Dam::URL_DAM_FLAG ) !== false;
652 + }
653 +
654 + /**
655 + * Get the optimized image url for the image url.
656 + *
657 + * @param string $url The image URL.
658 + * @param mixed $width The image width.
659 + * @param mixed $height The image height.
660 + * @param array<string, mixed>|mixed $resize The resize properties.
661 + *
662 + * @return string
663 + */
664 + protected function get_optimized_image_url( $url, $width, $height, $resize = [] ) {
665 + $width = is_int( $width ) ? $width : 'auto';
666 + $height = is_int( $height ) ? $height : 'auto';
667 + // If the image is already using Optimole URL, we extract the source to rebuild it.
668 + $url = $this->get_unoptimized_url( $url );
669 +
670 + $optimized_image = Optimole::image( $url, $this->settings->get( 'cache_buster' ) )
671 + ->width( $width )
672 + ->height( $height );
673 +
674 + if ( is_array( $resize ) && ! empty( $resize['type'] ) ) {
675 + $optimized_image->resize( $resize['type'], $resize['gravity'] ?? Position::CENTER, $resize['enlarge'] ?? false );
676 +
677 + }
678 +
679 + $optimized_image->quality( $this->settings->to_accepted_quality( $this->settings->get_quality() ) );
680 +
681 + return $optimized_image->getUrl();
682 + }
683 +
684 + /**
685 + * Returns an image id from the url.
686 + *
687 + * @param string $url The image URL.
688 + *
689 + * @return int
690 + */
691 + public function get_id_by_url( $url ) {
692 + $url = $this->get_unoptimized_url( $url );
693 + srand( crc32( $url ) );
694 + $random_id = rand();
695 + srand();
696 + return $random_id;
572 697 }
573 698 }