PluginProbe
Autoptimize / 3.1.4
Autoptimize v3.1.4
2.2.2 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 All 107 releases
← All changes | classes/autoptimizeImages.php +381 -119 2.7.33.1.4 View file →
@@ -30,8 +30,9 @@
30 30 $options = $this->fetch_options();
31 31 }
32 32
33 33 $this->set_options( $options );
34 + $this->lazyload_counter = 0;
34 35 }
35 36
36 37 public function set_options( array $options )
37 38 {
@@ -50,10 +51,30 @@
50 51
51 52 // get service availability and add it to the options-array.
52 53 $value['availabilities'] = autoptimizeOptionWrapper::get_option( 'autoptimize_service_availablity' );
53 54
54 - if ( empty( $value['availabilities'] ) ) {
55 - $value['availabilities'] = autoptimizeUtils::check_service_availability( true );
55 + if ( empty( $value['availabilities'] ) || ! is_array( $value['availabilities'] ) ) {
56 + $value['availabilities'] = null;
57 +
58 + if ( true === autoptimizeImages::imgopt_active() ) {
59 + $value['availabilities'] = autoptimizeUtils::check_service_availability( true );
60 + }
61 +
62 + if ( null === $value['availabilities'] ) {
63 + // We can't seem to check service availability, use mock result with imgopt status UP.
64 + $_mock_settings = array(
65 + 'extra_imgopt' => array(
66 + 'status' => 'up',
67 + 'hosts' => array(
68 + '1' => 'https://sp-ao.shortpixel.ai/',
69 + ),
70 + ),
71 + 'critcss' => array(
72 + 'status' => 'up',
73 + ),
74 + );
75 + $value['availabilities'] = $_mock_settings;
76 + }
56 77 }
57 78
58 79 return $value;
59 80 }
@@ -112,9 +133,11 @@
112 133 if ( ! $this->should_run() ) {
113 134 if ( $this->should_lazyload() ) {
114 135 add_filter(
115 136 'wp_lazy_loading_enabled',
116 - '__return_false'
137 + array( $this, 'should_disable_core_lazyload' ),
138 + 10,
139 + 3
117 140 );
118 141 add_filter(
119 142 'autoptimize_html_after_minify',
120 143 array( $this, 'filter_lazyload_images' ),
@@ -164,9 +187,11 @@
164 187
165 188 if ( $this->should_lazyload() ) {
166 189 add_filter(
167 190 'wp_lazy_loading_enabled',
168 - '__return_false'
191 + array( $this, 'should_disable_core_lazyload' ),
192 + 10,
193 + 3
169 194 );
170 195 add_action(
171 196 'wp_footer',
172 197 array( $this, 'add_lazyload_js_footer' ),
@@ -176,8 +201,24 @@
176 201 }
177 202 }
178 203
179 204 /**
205 + * Disables core's native lazyload for images, not for iframes.
206 + *
207 + * @param bool $flag Incoming flag (mostly true).
208 + * @param string $tag Tag (img or iframe).
209 + * @param string $context Full context.
210 + *
211 + * @return bool
212 + */
213 + public function should_disable_core_lazyload( $flag = true, $tag = '', $context = '' ) {
214 + if ( 'img' === $tag ) {
215 + return false;
216 + }
217 + return $flag;
218 + }
219 +
220 + /**
180 221 * Basic checks before we can run.
181 222 *
182 223 * @return bool
183 224 */
@@ -209,9 +250,9 @@
209 250 {
210 251 static $imgopt_host = null;
211 252
212 253 if ( null === $imgopt_host ) {
213 - $imgopt_host = 'https://cdn.shortpixel.ai/';
254 + $imgopt_host = 'https://sp-ao.shortpixel.ai/';
214 255 $avail_imgopt = $this->options['availabilities']['extra_imgopt'];
215 256 if ( ! empty( $avail_imgopt ) && array_key_exists( 'hosts', $avail_imgopt ) && is_array( $avail_imgopt['hosts'] ) ) {
216 257 $imgopt_host = array_rand( array_flip( $avail_imgopt['hosts'] ) );
217 258 }
@@ -229,9 +270,9 @@
229 270 }
230 271
231 272 public static function get_service_url_suffix()
232 273 {
233 - $suffix = '/af/GWRGFLW109483/' . AUTOPTIMIZE_SITE_DOMAIN;
274 + $suffix = '/af/U0ZIWMK109483/' . AUTOPTIMIZE_SITE_DOMAIN;
234 275
235 276 return $suffix;
236 277 }
237 278
@@ -344,11 +385,9 @@
344 385 // Default to (the trimmed version of) what was given to us.
345 386 $result = trim( $in );
346 387
347 388 // Some silly plugins wrap background images in html-encoded quotes, so remove those from the img url.
348 - if ( strpos( $result, '"' ) !== false ) {
349 - $result = str_replace( '"', '', $result );
350 - }
389 + $result = $this->fix_silly_bgimg_quotes( $result );
351 390
352 391 if ( autoptimizeUtils::is_protocol_relative( $result ) ) {
353 392 $result = $parsed_site_url['scheme'] . ':' . $result;
354 393 } elseif ( 0 === strpos( $result, '/' ) ) {
@@ -353,12 +392,18 @@
353 392 $result = $parsed_site_url['scheme'] . ':' . $result;
354 393 } elseif ( 0 === strpos( $result, '/' ) ) {
355 394 // Root-relative...
356 395 $result = $parsed_site_url['scheme'] . '://' . $parsed_site_url['host'] . $result;
357 - } elseif ( ! empty( $cdn_domain ) && strpos( $result, $cdn_domain ) !== 0 ) {
396 + } elseif ( ! empty( $cdn_domain ) && false === strpos( $this->get_imgopt_host(), $cdn_domain ) && strpos( $result, $cdn_domain ) !== 0 ) {
397 + // remove CDN except if it is the image optimization one.
358 398 $result = str_replace( $cdn_domain, $parsed_site_url['host'], $result );
359 399 }
360 400
401 + // filter (default off) to remove QS from image URL's to avoid eating away optimization credits.
402 + if ( apply_filters( 'autoptimize_filter_imgopt_no_querystring', false ) && strpos( $result, '?' ) !== false ) {
403 + $result = strtok( $result, '?' );
404 + }
405 +
361 406 $result = apply_filters( 'autoptimize_filter_imgopt_normalized_url', $result );
362 407
363 408 // Store in cache.
364 409 $cache[ $in ] = $result;
@@ -370,9 +415,9 @@
370 415 public function filter_optimize_css_images( $in )
371 416 {
372 417 $in = $this->normalize_img_url( $in );
373 418
374 - if ( $this->can_optimize_image( $in ) ) {
419 + if ( $this->can_optimize_image( $in ) && false === strpos( $in, $this->get_imgopt_host() ) ) {
375 420 return $this->build_imgopt_url( $in, '', '' );
376 421 } else {
377 422 return $in;
378 423 }
@@ -385,9 +430,15 @@
385 430 if ( null === $imgopt_base_url ) {
386 431 $imgopt_host = $this->get_imgopt_host();
387 432 $quality = $this->get_img_quality_string();
388 433 $ret_val = apply_filters( 'autoptimize_filter_imgopt_wait', 'ret_img' ); // values: ret_wait, ret_img, ret_json, ret_blank.
389 - $imgopt_base_url = $imgopt_host . 'client/' . $quality . ',' . $ret_val;
434 + if ( $this->should_ngimg() ) {
435 + $sp_to_string = 'to_auto';
436 + } else {
437 + $sp_to_string = 'to_webp';
438 + }
439 + $sp_to_string = apply_filters( 'autoptimize_filter_imgopt_format', $sp_to_string ); // values: empty (= jpeg), to_webp (smart; webp or fallback), to_avif (avif or fallback) or to_auto (smart avif, webp or fallback).
440 + $imgopt_base_url = $imgopt_host . 'client/' . $sp_to_string . ',' . $quality . ',' . $ret_val;
390 441 $imgopt_base_url = apply_filters( 'autoptimize_filter_imgopt_base_url', $imgopt_base_url );
391 442 }
392 443
393 444 return $imgopt_base_url;
@@ -392,9 +443,14 @@
392 443
393 444 return $imgopt_base_url;
394 445 }
395 446
396 - private function can_optimize_image( $url )
447 + public static function can_optimize_image_wrapper( $url, $tag = '', $testing = false ) {
448 + $self = new self();
449 + return $self->can_optimize_image( $url, $tag = '', $testing = false );
450 + }
451 +
452 + private function can_optimize_image( $url, $tag = '', $testing = false )
397 453 {
398 454 static $cdn_url = null;
399 455 static $nopti_images = null;
400 456
@@ -404,10 +460,13 @@
404 460 autoptimizeOptionWrapper::get_option( 'autoptimize_cdn_url', '' )
405 461 );
406 462 }
407 463
408 - if ( null === $nopti_images ) {
409 - $nopti_images = apply_filters( 'autoptimize_filter_imgopt_noptimize', '' );
464 + if ( null === $nopti_images || $testing ) {
465 + if ( is_array( $this->options ) && array_key_exists( 'autoptimize_imgopt_text_field_6', $this->options ) ) {
466 + $nopti_images = $this->options['autoptimize_imgopt_text_field_6'];
467 + }
468 + $nopti_images = apply_filters( 'autoptimize_filter_imgopt_noptimize', $nopti_images );
410 469 }
411 470
412 471 $site_host = AUTOPTIMIZE_SITE_DOMAIN;
413 472 $url = $this->normalize_img_url( $url );
@@ -414,19 +473,21 @@
414 473 $url_parsed = parse_url( $url );
415 474
416 475 if ( array_key_exists( 'host', $url_parsed ) && $url_parsed['host'] !== $site_host && empty( $cdn_url ) ) {
417 476 return false;
477 + } elseif ( autoptimizeUtils::is_local_server() ) {
478 + return false;
418 479 } elseif ( ! empty( $cdn_url ) && strpos( $url, $cdn_url ) === false && array_key_exists( 'host', $url_parsed ) && $url_parsed['host'] !== $site_host ) {
419 480 return false;
420 481 } elseif ( strpos( $url, '.php' ) !== false ) {
421 482 return false;
422 - } elseif ( str_ireplace( array( '.png', '.gif', '.jpg', '.jpeg', '.webp' ), '', $url_parsed['path'] ) === $url_parsed['path'] ) {
483 + } elseif ( str_ireplace( array( '.png', '.gif', '.jpg', '.jpeg', '.webp', '.avif' ), '', $url_parsed['path'] ) === $url_parsed['path'] ) {
423 484 // fixme: better check against end of string.
424 485 return false;
425 486 } elseif ( ! empty( $nopti_images ) ) {
426 487 $nopti_images_array = array_filter( array_map( 'trim', explode( ',', $nopti_images ) ) );
427 488 foreach ( $nopti_images_array as $nopti_image ) {
428 - if ( strpos( $url, $nopti_image ) !== false ) {
489 + if ( strpos( $url, $nopti_image ) !== false || ( ( '' !== $tag && strpos( $tag, $nopti_image ) !== false ) ) ) {
429 490 return false;
430 491 }
431 492 }
432 493 }
@@ -432,8 +493,14 @@
432 493 }
433 494 return true;
434 495 }
435 496
497 + // wrapper for reuse in AOPro.
498 + public static function build_imgopt_url_wrapper( $orig_url, $width = 0, $height = 0 ) {
499 + $self = new self();
500 + return $self->build_imgopt_url( $orig_url, $width = 0, $height = 0 );
501 + }
502 +
436 503 private function build_imgopt_url( $orig_url, $width = 0, $height = 0 )
437 504 {
438 505 // sanitize width and height.
439 506 if ( strpos( $width, '%' ) !== false ) {
@@ -456,9 +523,15 @@
456 523 if ( $filtered_url !== $orig_url ) {
457 524 return $filtered_url;
458 525 }
459 526
460 - $orig_url = $this->normalize_img_url( $orig_url );
527 + $normalized_url = $this->normalize_img_url( $orig_url );
528 +
529 + // if the URL is ascii we check if we have a real URL with filter_var (which only works on ascii url's) and if not a real URL we return the original one.
530 + if ( apply_filters( 'autoptimize_filter_imgopt_check_normalized_url', true ) && ! preg_match( '/[^\x20-\x7e]/', $normalized_url ) && false === filter_var( $normalized_url, FILTER_VALIDATE_URL ) ) {
531 + return $orig_url;
532 + }
533 +
461 534 $imgopt_base_url = $this->get_imgopt_base_url();
462 535 $imgopt_size = '';
463 536
464 537 if ( $width && 0 !== $width ) {
@@ -468,9 +541,9 @@
468 541 if ( $height && 0 !== $height ) {
469 542 $imgopt_size .= ',h_' . $height;
470 543 }
471 544
472 - $url = $imgopt_base_url . $imgopt_size . '/' . $orig_url;
545 + $url = $imgopt_base_url . $imgopt_size . '/' . $normalized_url;
473 546
474 547 return $url;
475 548 }
476 549
@@ -481,9 +554,9 @@
481 554
482 555 public function replace_img_callback( $matches, $width = 0, $height = 0 )
483 556 {
484 557 $_normalized_img_url = $this->normalize_img_url( $matches[1] );
485 - if ( $this->can_optimize_image( $matches[1] ) ) {
558 + if ( $this->can_optimize_image( $matches[1], $matches[0] ) ) {
486 559 return str_replace( $matches[1], $this->build_imgopt_url( $_normalized_img_url, $width, $height ), $matches[0] );
487 560 } else {
488 561 return $matches[0];
489 562 }
@@ -488,10 +561,29 @@
488 561 return $matches[0];
489 562 }
490 563 }
491 564
492 - public function filter_optimize_images( $in )
565 + public function replace_icon_callback( $matches )
493 566 {
567 + if ( array_key_exists( '2', $matches ) ) {
568 + $sizes = explode( 'x', $matches[2] );
569 + $width = $sizes[0];
570 + $height = $sizes[1];
571 + } else {
572 + $width = 180;
573 + $height = 180;
574 + }
575 +
576 + // make sure we're not trying to optimize a *.ico file.
577 + if ( strpos( $matches[1], '.ico' ) === false ) {
578 + return $this->replace_img_callback( $matches, $width, $height );
579 + } else {
580 + return $matches[0];
581 + }
582 + }
583 +
584 + public function filter_optimize_images( $in, $testing = false )
585 + {
494 586 /*
495 587 * potential future functional improvements:
496 588 *
497 589 * filter for critical CSS.
@@ -496,11 +588,12 @@
496 588 *
497 589 * filter for critical CSS.
498 590 */
499 591 $to_replace = array();
592 + $to_preload = '';
500 593
501 - // hide noscript tags to avoid nesting noscript tags (as lazyloaded images add noscript).
502 - if ( $this->should_lazyload() ) {
594 + // hide (no)script tags to avoid replacing (and potentially breaking) images in script tags.
595 + if ( apply_filters( 'autoptimize_filter_imgopt_hide_script', true ) || $this->should_lazyload() ) {
503 596 $in = autoptimizeBase::replace_contents_with_marker_if_exists(
504 597 'SCRIPT',
505 598 '<script',
506 599 '#<(?:no)?script.*?<\/(?:no)?script>#is',
@@ -507,11 +600,18 @@
507 600 $in
508 601 );
509 602 }
510 603
604 + // get img preloads as set in post metabox, exploding ", " instead of "," because LCP preload
605 + // could be a shortpixel URL, which has comma's and results in way too many preloads.
606 + $metabox_preloads = array_filter( array_map( 'trim', explode( ', ', wp_strip_all_tags( autoptimizeConfig::get_post_meta_ao_settings( 'ao_post_preload' ) ) ) ) );
607 + $metabox_preloads = apply_filters( 'autoptimize_filter_images_metabox_preloads', $metabox_preloads );
608 +
511 609 // extract img tags.
512 610 if ( preg_match_all( '#<img[^>]*src[^>]*>#Usmi', $in, $matches ) ) {
513 611 foreach ( $matches[0] as $tag ) {
612 + $tag = apply_filters( 'autoptimize_filter_imgopt_tag_preopt', $tag );
613 +
514 614 $orig_tag = $tag;
515 615 $imgopt_w = '';
516 616 $imgopt_h = '';
517 617
@@ -517,20 +617,22 @@
517 617
518 618 // first do (data-)srcsets.
519 619 if ( preg_match_all( '#srcset=("|\')(.*)("|\')#Usmi', $tag, $allsrcsets, PREG_SET_ORDER ) ) {
520 620 foreach ( $allsrcsets as $srcset ) {
521 - $srcset = $srcset[2];
522 - $srcsets = explode( ',', $srcset );
621 + $srcset = $srcset[2];
622 + $orig_srcset = $srcset;
623 + $srcsets = explode( ',', $srcset );
523 624 foreach ( $srcsets as $indiv_srcset ) {
524 625 $indiv_srcset_parts = explode( ' ', trim( $indiv_srcset ) );
525 626 if ( isset( $indiv_srcset_parts[1] ) && rtrim( $indiv_srcset_parts[1], 'w' ) !== $indiv_srcset_parts[1] ) {
526 627 $imgopt_w = rtrim( $indiv_srcset_parts[1], 'w' );
527 628 }
528 - if ( $this->can_optimize_image( $indiv_srcset_parts[0] ) ) {
629 + if ( $this->can_optimize_image( $indiv_srcset_parts[0], $tag, $testing ) && false === apply_filters( 'autoptimize_filter_imgopt_do_spai', false ) ) {
529 630 $imgopt_url = $this->build_imgopt_url( $indiv_srcset_parts[0], $imgopt_w, '' );
530 - $tag = str_replace( $indiv_srcset_parts[0], $imgopt_url, $tag );
631 + $srcset = str_replace( $indiv_srcset_parts[0], $imgopt_url, $srcset );
531 632 }
532 633 }
634 + $tag = str_replace( $orig_srcset, $srcset, $tag );
533 635 }
534 636 }
535 637
536 638 // proceed with img src.
@@ -543,9 +645,9 @@
543 645 if ( preg_match_all( '#src=(?:"|\')(?!data)(.*)(?:"|\')#Usmi', $tag, $urls, PREG_SET_ORDER ) ) {
544 646 foreach ( $urls as $url ) {
545 647 $full_src_orig = $url[0];
546 648 $url = $url[1];
547 - if ( $this->can_optimize_image( $url ) ) {
649 + if ( $this->can_optimize_image( $url, $tag, $testing ) && false === apply_filters( 'autoptimize_filter_imgopt_do_spai', false ) ) {
548 650 $imgopt_url = $this->build_imgopt_url( $url, $imgopt_w, $imgopt_h );
549 651 $full_imgopt_src = str_replace( $url, $imgopt_url, $full_src_orig );
550 652 $tag = str_replace( $full_src_orig, $full_imgopt_src, $tag );
551 653 }
@@ -551,8 +653,13 @@
551 653 }
552 654 }
553 655 }
554 656
657 + // check if the image needs to be prelaoded.
658 + if ( ! empty( $metabox_preloads ) && is_array( $metabox_preloads ) && str_replace( $metabox_preloads, '', $tag ) !== $tag ) {
659 + $to_preload .= $this->create_img_preload_tag( $tag );
660 + }
661 +
555 662 // do lazyload stuff.
556 663 if ( $this->should_lazyload( $in ) && ! empty( $url ) ) {
557 664 // first do lpiq placeholder logic.
558 665 if ( strpos( $url, $this->get_imgopt_host() ) === 0 ) {
@@ -565,9 +672,9 @@
565 672
566 673 $_url = $this->normalize_img_url( $_url );
567 674
568 675 $placeholder = '';
569 - if ( $this->can_optimize_image( $_url ) && apply_filters( 'autoptimize_filter_imgopt_lazyload_dolqip', true ) ) {
676 + if ( $this->can_optimize_image( $_url, $tag ) && apply_filters( 'autoptimize_filter_imgopt_lazyload_dolqip', false, $_url ) && false === apply_filters( 'autoptimize_filter_imgopt_do_spai', false ) ) {
570 677 $lqip_w = '';
571 678 $lqip_h = '';
572 679 if ( isset( $imgopt_w ) && ! empty( $imgopt_w ) ) {
573 680 $lqip_w = ',w_' . $imgopt_w;
@@ -580,8 +687,15 @@
580 687 // then call add_lazyload-function with lpiq placeholder if set.
581 688 $tag = $this->add_lazyload( $tag, $placeholder );
582 689 }
583 690
691 + // add decoding="async" behind filter, not sure if I'll make it default true yet.
692 + if ( true === apply_filters( 'autoptimize_filter_imgopt_add_decoding', true ) && false === strpos( $tag, ' decoding=' ) ) {
693 + $tag = str_replace( '<img ', '<img decoding="async" ', $tag );
694 + }
695 +
696 + $tag = apply_filters( 'autoptimize_filter_imgopt_tag_postopt', $tag );
697 +
584 698 // and add tag to array for later replacement.
585 699 if ( $tag !== $orig_tag ) {
586 700 $to_replace[ $orig_tag ] = $tag;
587 701 }
@@ -590,15 +704,21 @@
590 704
591 705 // and replace all.
592 706 $out = str_replace( array_keys( $to_replace ), array_values( $to_replace ), $in );
593 707
594 - // img thumbnails in e.g. woocommerce.
595 - if ( strpos( $out, 'data-thumb' ) !== false && apply_filters( 'autoptimize_filter_imgopt_datathumbs', true ) ) {
596 - $out = preg_replace_callback(
597 - '/\<div(?:[^>]?)\sdata-thumb\=(?:\"|\')(.+?)(?:\"|\')(?:[^>]*)?\>/s',
598 - array( $this, 'replace_data_thumbs' ),
599 - $out
600 - );
708 + // misc. node attributes that might hold image url's (incl. the previously separate data-thumb).
709 + $extra_attr_with_img = apply_filters( 'autoptimize_filter_imgopt_attr_with_img', array( array( 'div', 'data-thumb'), array( 'div', 'data-background' ), array( 'img', 'data-retina' ) ) );
710 + if ( ! empty( $extra_attr_with_img ) && is_array( $extra_attr_with_img ) ) {
711 + foreach ( $extra_attr_with_img as $candidate ) {
712 + if ( is_array( $candidate ) && strpos( $out, $candidate[1] ) !== false ) {
713 + $_regex = '/\<' . $candidate[0] . '(?:[^>]*)?\s' . $candidate[1] . '=(?:"|\')(.+?)(?:"|\')(?:[^>]*)?>/s';
714 + $out = preg_replace_callback(
715 + $_regex,
716 + array( $this, 'replace_img_callback' ),
717 + $out
718 + );
719 + }
720 + }
601 721 }
602 722
603 723 // background-image in inline style.
604 724 if ( strpos( $out, 'background-image:' ) !== false && apply_filters( 'autoptimize_filter_imgopt_backgroundimages', true ) ) {
@@ -608,15 +728,19 @@
608 728 $out
609 729 );
610 730 }
611 731
612 - // lazyload: restore noscript tags + lazyload picture source tags and bgimage.
613 - if ( $this->should_lazyload() ) {
614 - $out = autoptimizeBase::restore_marked_content(
615 - 'SCRIPT',
732 + // act on icon links.
733 + if ( ( strpos( $out, '<link rel="icon"' ) !== false || ( strpos( $out, "<link rel='icon'" ) !== false ) ) && apply_filters( 'autoptimize_filter_imgopt_linkicon', true ) ) {
734 + $out = preg_replace_callback(
735 + '/<link\srel=(?:"|\')(?:apple-touch-)?icon(?:"|\').*\shref=(?:"|\')(.*)(?:"|\')(?:\ssizes=(?:"|\')(\d*x\d*)(?:"|\'))?\s\/>/Um',
736 + array( $this, 'replace_icon_callback' ),
616 737 $out
617 738 );
739 + }
618 740
741 + // lazyload picture source tags and bgimage.
742 + if ( $this->should_lazyload() ) {
619 743 $out = $this->process_picture_tag( $out, true, true );
620 744 $out = $this->process_bgimage( $out );
621 745 } else {
622 746 $out = $this->process_picture_tag( $out, true, false );
@@ -621,12 +745,31 @@
621 745 } else {
622 746 $out = $this->process_picture_tag( $out, true, false );
623 747 }
624 748
749 + // restore (no)script tags.
750 + if ( apply_filters( 'autoptimize_filter_imgopt_hide_script', true ) || $this->should_lazyload() ) {
751 + $out = autoptimizeBase::restore_marked_content(
752 + 'SCRIPT',
753 + $out
754 + );
755 + }
756 +
757 + if ( ! empty( $metabox_preloads ) && is_array( $metabox_preloads ) && empty( $to_preload ) && false !== apply_filters( 'autoptimize_filter_imgopt_dopreloads', true ) ) {
758 + // the preload was not in an img tag, so adding a non-responsive preload instead.
759 + foreach ( $metabox_preloads as $img_preload ) {
760 + $to_preload .= '<link rel="preload" href="' . $img_preload . '" as="image">';
761 + }
762 + }
763 +
764 + if ( ! empty( $to_preload ) ) {
765 + $out = autoptimizeExtra::inject_preloads( $to_preload, $out );
766 + }
767 +
625 768 return $out;
626 769 }
627 770
628 - public function get_size_from_tag( $tag ) {
771 + public static function get_size_from_tag( $tag ) {
629 772 // reusable function to extract widht and height from an image tag
630 773 // enforcing a filterable maximum width and height (default 4999X4999).
631 774 $width = '';
632 775 $height = '';
@@ -645,15 +788,19 @@
645 788 // check for and enforce (filterable) max sizes.
646 789 $_max_width = apply_filters( 'autoptimize_filter_imgopt_max_width', 4999 );
647 790 if ( $width > $_max_width ) {
648 791 $_width = $_max_width;
649 - $height = $_width / $width * $height;
792 + if ( ! empty( $height ) && is_int( $height ) ) {
793 + $height = $_width / $width * $height;
794 + }
650 795 $width = $_width;
651 796 }
652 797 $_max_height = apply_filters( 'autoptimize_filter_imgopt_max_height', 4999 );
653 798 if ( $height > $_max_height ) {
654 799 $_height = $_max_height;
655 - $width = $_height / $height * $width;
800 + if ( ! empty( $width ) && is_int( $width ) ) {
801 + $width = $_height / $height * $width;
802 + }
656 803 $height = $_height;
657 804 }
658 805
659 806 return array(
@@ -676,14 +823,20 @@
676 823 $lazyload_return = true;
677 824 } else {
678 825 $lazyload_return = false;
679 826 }
827 +
828 + // If page/ post check post_meta to see if lazyload is off for page.
829 + if ( false === autoptimizeConfig::get_post_meta_ao_settings( 'ao_post_lazyload' ) ) {
830 + $lazyload_return = false;
831 + }
832 +
680 833 $lazyload_return = apply_filters( 'autoptimize_filter_imgopt_should_lazyload', $lazyload_return, $context );
681 834
682 835 return $lazyload_return;
683 836 }
684 837
685 - public function check_nolazy() {
838 + public static function check_nolazy() {
686 839 if ( array_key_exists( 'ao_nolazy', $_GET ) && '1' === $_GET['ao_nolazy'] ) {
687 840 return true;
688 841 } else {
689 842 return false;
@@ -693,8 +846,9 @@
693 846 public function filter_lazyload_images( $in )
694 847 {
695 848 // only used is image optimization is NOT active but lazyload is.
696 849 $to_replace = array();
850 + $to_preload = '';
697 851
698 852 // hide (no)script tags to avoid nesting noscript tags (as lazyloaded images add noscript).
699 853 $out = autoptimizeBase::replace_contents_with_marker_if_exists(
700 854 'SCRIPT',
@@ -702,11 +856,20 @@
702 856 '#<(?:no)?script.*?<\/(?:no)?script>#is',
703 857 $in
704 858 );
705 859
706 - // extract img tags and add lazyload attribs.
860 + // get img preloads as set in post metabox.
861 + $metabox_preloads = array_filter( array_map( 'trim', explode( ',', wp_strip_all_tags( autoptimizeConfig::get_post_meta_ao_settings( 'ao_post_preload' ) ) ) ) );
862 +
863 + // extract img tags and add lazyload attribs/ add preloads.
707 864 if ( preg_match_all( '#<img[^>]*src[^>]*>#Usmi', $out, $matches ) ) {
708 865 foreach ( $matches[0] as $tag ) {
866 + // check if image needs to be preloaded.
867 + if ( ! empty( $metabox_preloads ) && is_array( $metabox_preloads ) && str_replace( $metabox_preloads, '', $tag ) !== $tag ) {
868 + $to_preload .= $this->create_img_preload_tag( $tag );
869 + }
870 +
871 + // and lazyloaded.
709 872 if ( $this->should_lazyload( $out ) ) {
710 873 $to_replace[ $tag ] = $this->add_lazyload( $tag );
711 874 }
712 875 }
@@ -724,14 +887,33 @@
724 887 'SCRIPT',
725 888 $out
726 889 );
727 890
891 + if ( ! empty( $metabox_preloads ) && is_array( $metabox_preloads ) && empty( $to_preload ) && false !== apply_filters( 'autoptimize_filter_imgopt_dopreloads', true ) ) {
892 + // the preload was not in an img tag, so adding a non-responsive preload instead.
893 + foreach ( $metabox_preloads as $img_preload ) {
894 + $to_preload .= '<link rel="preload" href="' . $img_preload . '" as="image">';
895 + }
896 + }
897 +
898 + if ( ! empty( $to_preload ) ) {
899 + $out = autoptimizeExtra::inject_preloads( $to_preload, $out );
900 + }
901 +
728 902 return $out;
729 903 }
730 904
731 905 public function add_lazyload( $tag, $placeholder = '' ) {
732 906 // adds actual lazyload-attributes to an image node.
733 - if ( str_ireplace( $this->get_lazyload_exclusions(), '', $tag ) === $tag ) {
907 + $this->lazyload_counter++;
908 +
909 + $_lazyload_from_nth = '';
910 + if ( array_key_exists( 'autoptimize_imgopt_number_field_7', $this->options ) ) {
911 + $_lazyload_from_nth = $this->options['autoptimize_imgopt_number_field_7'];
912 + }
913 + $_lazyload_from_nth = apply_filters( 'autoptimize_filter_imgopt_lazyload_from_nth', $_lazyload_from_nth );
914 +
915 + if ( str_ireplace( $this->get_lazyload_exclusions(), '', $tag ) === $tag && $this->lazyload_counter >= $_lazyload_from_nth ) {
734 916 $tag = $this->maybe_fix_missing_quotes( $tag );
735 917
736 918 // store original tag for use in noscript version.
737 919 $noscript_tag = '<noscript>' . autoptimizeUtils::remove_id_from_node( $tag ) . '</noscript>';
@@ -768,8 +950,10 @@
768 950
769 951 // add the noscript-tag from earlier.
770 952 $tag = $noscript_tag . $tag;
771 953 $tag = apply_filters( 'autoptimize_filter_imgopt_lazyloaded_img', $tag );
954 + } else {
955 + $tag = apply_filters( 'autoptimize_filter_imgopt_not_lazyloaded_img', $tag );
772 956 }
773 957
774 958 return $tag;
775 959 }
@@ -774,9 +958,9 @@
774 958 return $tag;
775 959 }
776 960
777 961 public function add_lazyload_js_footer() {
778 - if ( false === autoptimizeMain::should_buffer() ) {
962 + if ( false === autoptimizeMain::should_buffer() || autoptimizeMain::is_amp_markup( '' ) ) {
779 963 return;
780 964 }
781 965
782 966 // The JS will by default be excluded form autoptimization but this can be changed with a filter.
@@ -784,11 +968,19 @@
784 968 if ( apply_filters( 'autoptimize_filter_imgopt_lazyload_js_noptimize', true ) ) {
785 969 $noptimize_flag = ' data-noptimize="1"';
786 970 }
787 971
788 - $lazysizes_js = plugins_url( 'external/js/lazysizes.min.js?ao_version=' . AUTOPTIMIZE_PLUGIN_VERSION, __FILE__ );
972 + $_extra = autoptimizeOptionWrapper::get_option( 'autoptimize_extra_settings', '' );
973 + if ( is_array( $_extra ) && array_key_exists( 'autoptimize_extra_checkbox_field_0', $_extra ) && ! empty( $_extra['autoptimize_extra_checkbox_field_0'] ) ) {
974 + // if "remove query strings" is active in "extra", then let's be consistant and not add one ourselves :-) ?
975 + $lazysizes_js = plugins_url( 'external/js/lazysizes.min.js', __FILE__ );
976 + } else {
977 + $lazysizes_js = plugins_url( 'external/js/lazysizes.min.js?ao_version=' . AUTOPTIMIZE_PLUGIN_VERSION, __FILE__ );
978 + }
979 +
789 980 $cdn_url = $this->get_cdn_url();
790 981 if ( ! empty( $cdn_url ) ) {
982 + $cdn_url = rtrim( $cdn_url, '/' );
791 983 $lazysizes_js = str_replace( AUTOPTIMIZE_WP_SITE_URL, $cdn_url, $lazysizes_js );
792 984 }
793 985
794 986 $type_js = '';
@@ -796,21 +988,42 @@
796 988 $type_js = ' type="text/javascript"';
797 989 }
798 990
799 991 // Adds lazyload CSS & JS to footer, using echo because wp_enqueue_script seems not to support pushing attributes (async).
800 - echo apply_filters( 'autoptimize_filter_imgopt_lazyload_cssoutput', '<style>.lazyload,.lazyloading{opacity:0;}.lazyloaded{opacity:1;transition:opacity 300ms;}</style><noscript><style>.lazyload{display:none;}</style></noscript>' );
992 + echo apply_filters( 'autoptimize_filter_imgopt_lazyload_cssoutput', '<noscript><style>.lazyload{display:none;}</style></noscript>' );
801 993 echo apply_filters( 'autoptimize_filter_imgopt_lazyload_jsconfig', '<script' . $type_js . $noptimize_flag . '>window.lazySizesConfig=window.lazySizesConfig||{};window.lazySizesConfig.loadMode=1;</script>' );
802 994 echo apply_filters( 'autoptimize_filter_imgopt_lazyload_js', '<script async' . $type_js . $noptimize_flag . ' src=\'' . $lazysizes_js . '\'></script>' );
995 + }
803 996
804 - // And add webp detection and loading JS.
805 - if ( $this->should_webp() ) {
806 - $_webp_detect = "function c_webp(A){var n=new Image;n.onload=function(){var e=0<n.width&&0<n.height;A(e)},n.onerror=function(){A(!1)},n.src='data:image/webp;base64,UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA=='}function s_webp(e){window.supportsWebP=e}c_webp(s_webp);";
807 - $_webp_load = "document.addEventListener('lazybeforeunveil',function({target:c}){supportsWebP&&['data-src','data-srcset'].forEach(function(a){attr=c.getAttribute(a),null!==attr&&c.setAttribute(a,attr.replace(/\/client\//,'/client/to_webp,'))})});";
808 - echo apply_filters( 'autoptimize_filter_imgopt_webp_js', '<script' . $type_js . $noptimize_flag . '>' . $_webp_detect . $_webp_load . '</script>' );
997 + public static function create_img_preload_tag( $tag ) {
998 + if ( false === apply_filters( 'autoptimize_filter_imgopt_dopreloads', true ) ) {
999 + return '';
809 1000 }
1001 +
1002 + // clean up; remove tabs/ linebreaks/ spaces.
1003 + $tag = preg_replace( '/\s+/', ' ', $tag );
1004 +
1005 + // remove noscript.
1006 + if ( false !== strpos( $tag, '<noscript' ) ) {
1007 + $tag = preg_replace( '/<noscript.*<\/noscript>/mU', '', $tag );
1008 + }
1009 +
1010 + // rewrite img tag to link preload img.
1011 + $_from = array( '<img ', ' src=', ' sizes=', ' srcset=' );
1012 + $_to = array( '<link rel="preload" as="image" ', ' href=', ' imagesizes=', ' imagesrcset=' );
1013 + $tag = str_replace( $_from, $_to, $tag );
1014 +
1015 + // and remove title, alt, class and id.
1016 + $tag = preg_replace( '/ ((?:title|alt|class|id|loading|fetchpriority|decoding|data-no-lazy)=".*")/Um', '', $tag );
1017 + if ( str_replace( array( ' title=', ' class=', ' alt=', ' id=', ' fetchpriority=', ' decoding=', ' data-no-lazy=' ), '', $tag ) !== $tag ) {
1018 + // 2nd regex pass if still title/ class/ alt in case single quotes were used iso doubles.
1019 + $tag = preg_replace( '/ ((?:title|alt|class|id|loading|fetchpriority|decoding|data-no-lazy)=\'.*\')/Um', '', $tag );
1020 + }
1021 +
1022 + return $tag;
810 1023 }
811 1024
812 - public function get_cdn_url() {
1025 + public static function get_cdn_url() {
813 1026 // getting CDN url here to avoid having to make bigger changes to autoptimizeBase.
814 1027 static $cdn_url = null;
815 1028
816 1029 if ( null === $cdn_url ) {
@@ -850,9 +1063,9 @@
850 1063 public function inject_classes_in_tag( $tag, $target_class ) {
851 1064 if ( strpos( $tag, 'class=' ) !== false ) {
852 1065 $tag = preg_replace( '/(\sclass\s?=\s?("|\'))/', '$1' . $target_class, $tag );
853 1066 } else {
854 - $tag = preg_replace( '/(<img)\s/', '$1 class="' . trim( $target_class ) . '" ', $tag );
1067 + $tag = preg_replace( '/(<[a-zA-Z]*)\s/', '$1 class="' . trim( $target_class ) . '" ', $tag );
855 1068 }
856 1069
857 1070 return $tag;
858 1071 }
@@ -860,21 +1073,21 @@
860 1073 public function get_default_lazyload_placeholder( $imgopt_w, $imgopt_h ) {
861 1074 return 'data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%20' . $imgopt_w . '%20' . $imgopt_h . '%22%3E%3C/svg%3E';
862 1075 }
863 1076
864 - public function should_webp() {
865 - static $webp_return = null;
1077 + public function should_ngimg() {
1078 + static $ngimg_return = null;
866 1079
867 - if ( is_null( $webp_return ) ) {
868 - // webp only works if imgopt and lazyload are also active.
869 - if ( ! empty( $this->options['autoptimize_imgopt_checkbox_field_4'] ) && ! empty( $this->options['autoptimize_imgopt_checkbox_field_3'] ) && $this->imgopt_active() ) {
870 - $webp_return = true;
1080 + if ( is_null( $ngimg_return ) ) {
1081 + // nextgen img only works if imgopt is active.
1082 + if ( ! empty( $this->options['autoptimize_imgopt_checkbox_field_4'] ) && $this->imgopt_active() ) {
1083 + $ngimg_return = true;
871 1084 } else {
872 - $webp_return = false;
1085 + $ngimg_return = false;
873 1086 }
874 1087 }
875 1088
876 - return $webp_return;
1089 + return $ngimg_return;
877 1090 }
878 1091
879 1092 public function process_picture_tag( $in, $imgopt = false, $lazy = false ) {
880 1093 // check if "<picture" is present and if filter allows us to process <picture>.
@@ -893,9 +1106,9 @@
893 1106 foreach ( $_sources as $_source ) {
894 1107 $_picture_replacement = $_source[0];
895 1108
896 1109 // should we optimize the image?
897 - if ( $imgopt && $this->can_optimize_image( $_source[1] ) ) {
1110 + if ( $imgopt && $this->can_optimize_image( $_source[1], $_picture[0] ) ) {
898 1111 $_picture_replacement = str_replace( $_source[1], $this->build_imgopt_url( $_source[1] ), $_picture_replacement );
899 1112 }
900 1113 // should we lazy-load?
901 1114 if ( $lazy && $this->should_lazyload() && str_ireplace( $_exclusions, '', $_picture_replacement ) === $_picture_replacement ) {
@@ -914,9 +1127,9 @@
914 1127
915 1128 public function process_bgimage( $in ) {
916 1129 if ( strpos( $in, 'background-image:' ) !== false && apply_filters( 'autoptimize_filter_imgopt_lazyload_backgroundimages', true ) ) {
917 1130 $out = preg_replace_callback(
918 - '/(<(?:article|aside|body|div|footer|header|p|section|table)[^>]*)\sstyle=(?:"|\')[^<>]*?background-image:\s?url\((?:"|\')?([^"\')]*)(?:"|\')?\)[^>]*/',
1131 + '/(<(?:article|aside|body|div|footer|header|p|section|span|table)[^>]*)\sstyle=(?:"|\')[^<>]*?background-image:\s?url\((?:"|\')?([^"\')]*)(?:"|\')?\)[^>]*/',
919 1132 array( $this, 'lazyload_bgimg_callback' ),
920 1133 $in
921 1134 );
922 1135 return $out;
@@ -928,13 +1141,17 @@
928 1141 if ( str_ireplace( $this->get_lazyload_exclusions(), '', $matches[0] ) === $matches[0] ) {
929 1142 // get placeholder & lazyload class strings.
930 1143 $placeholder = apply_filters( 'autoptimize_filter_imgopt_lazyload_placeholder', $this->get_default_lazyload_placeholder( 500, 300 ) );
931 1144 $lazyload_class = apply_filters( 'autoptimize_filter_imgopt_lazyload_class', 'lazyload' );
1145 + // remove quotes from url() to be able to replace in next step.
1146 + $out = str_replace( array( "url('" . $matches[2] . "')", 'url("' . $matches[2] . '")' ), 'url(' . $matches[2] . ')', $matches[0] );
932 1147 // replace background-image URL with SVG placeholder.
933 - $out = str_replace( $matches[2], $placeholder, $matches[0] );
1148 + $out = str_replace( 'url(' . $matches[2], 'url(' . $placeholder, $out );
1149 + // sanitize bgimg src for quote sillyness.
1150 + $bgimg_src = $this->fix_silly_bgimg_quotes( $matches[2] );
934 1151 // add data-bg attribute with real background-image URL for lazyload to pick up.
935 - $out = str_replace( $matches[1], $matches[1] . ' data-bg="' . trim( str_replace( array( "\r\n", '&quot;' ), '', $matches[2] ) ) . '"', $out );
936 - // add lazyload class to tag.
1152 + $out = str_replace( $matches[1], $matches[1] . ' data-bg="' . $bgimg_src . '"', $out );
1153 + // and finally add lazyload class to tag.
937 1154 $out = $this->inject_classes_in_tag( $out, "$lazyload_class " );
938 1155 return $out;
939 1156 }
940 1157 return $matches[0];
@@ -939,8 +1156,13 @@
939 1156 }
940 1157 return $matches[0];
941 1158 }
942 1159
1160 + public function fix_silly_bgimg_quotes( $tag_in ) {
1161 + // some themes/ pagebuilders wrap backgroundimages in HTML-encoded quotes (or linebreaks) which breaks imgopt/ lazyloading, this removes them.
1162 + return trim( str_replace( array( "\r\n", '&quot;', '&#034;', '&apos;', '&#039;' ), '', $tag_in ) );
1163 + }
1164 +
943 1165 public function maybe_fix_missing_quotes( $tag_in ) {
944 1166 // W3TC's Minify_HTML class removes quotes around attribute value, this re-adds them for the class and width/height attributes so we can lazyload properly.
945 1167 if ( file_exists( WP_PLUGIN_DIR . '/w3-total-cache/w3-total-cache.php' ) && class_exists( 'Minify_HTML' ) && apply_filters( 'autoptimize_filter_imgopt_fixquotes', true ) ) {
946 1168 $tag_out = preg_replace( '/class\s?=([^("|\')]*)(\s|>)/U', 'class=\'$1\'$2', $tag_in );
@@ -958,9 +1180,9 @@
958 1180 {
959 1181 // no acces if multisite and not network admin and no site config allowed.
960 1182 if ( autoptimizeConfig::should_show_menu_tabs() ) {
961 1183 add_submenu_page(
962 - null,
1184 + '',
963 1185 'autoptimize_imgopt',
964 1186 'autoptimize_imgopt',
965 1187 'manage_options',
966 1188 'autoptimize_imgopt',
@@ -972,9 +1194,9 @@
972 1194
973 1195 public function add_imgopt_tab( $in )
974 1196 {
975 1197 if ( autoptimizeConfig::should_show_menu_tabs() ) {
976 - $in = array_merge( $in, array( 'autoptimize_imgopt' => __( 'Images', 'autoptimize' ) ) );
1198 + $in = array_merge( $in, array( 'autoptimize_imgopt' => apply_filters( 'autoptimize_filter_imgopt_tab_text', __( 'Images', 'autoptimize' ) ) ) );
977 1199 }
978 1200
979 1201 return $in;
980 1202 }
@@ -980,11 +1202,14 @@
980 1202 }
981 1203
982 1204 public function imgopt_options_page()
983 1205 {
1206 + // phpcs:disable Squiz.ControlStructures.ControlSignature.NewlineAfterOpenBrace
1207 + // phpcs:disable Generic.Formatting.DisallowMultipleStatements.SameLine
1208 +
984 1209 // Check querystring for "refreshCacheChecker" and call cachechecker if so.
985 1210 if ( array_key_exists( 'refreshImgProvStats', $_GET ) && 1 == $_GET['refreshImgProvStats'] ) {
986 - $this->query_img_provider_stats();
1211 + $this->query_img_provider_stats( true );
987 1212 }
988 1213
989 1214 $options = $this->fetch_options();
990 1215 $sp_url_suffix = $this->get_service_url_suffix();
@@ -995,10 +1220,17 @@
995 1220 #autoptimize_imgopt_descr{font-size: 120%;}
996 1221 </style>
997 1222 <script>document.title = "Autoptimize: <?php _e( 'Images', 'autoptimize' ); ?> " + document.title;</script>
998 1223 <div class="wrap">
999 - <h1><?php _e( 'Autoptimize Settings', 'autoptimize' ); ?></h1>
1224 + <h1><?php apply_filters( 'autoptimize_filter_settings_is_pro', false ) ? _e( 'Autoptimize Pro Settings', 'autoptimize' ) : _e( 'Autoptimize Settings', 'autoptimize' ); ?></h1>
1000 1225 <?php echo autoptimizeConfig::ao_admin_tabs(); ?>
1226 + <?php if ( autoptimizeUtils::is_local_server() ) { ?>
1227 + <div class="notice-warning notice"><p>
1228 + <?php
1229 + echo __( 'The image optimization service does not work on locally hosted sites or when the server is on a private network.', 'autoptimize' );
1230 + ?>
1231 + </p></div>
1232 + <?php } ?>
1001 1233 <?php if ( 'down' === $options['availabilities']['extra_imgopt']['status'] ) { ?>
1002 1234 <div class="notice-warning notice"><p>
1003 1235 <?php
1004 1236 // translators: "Autoptimize support forum" will appear in a "a href".
@@ -1023,14 +1255,14 @@
1023 1255 <?php } ?>
1024 1256 <form id='ao_settings_form' action='<?php echo admin_url( 'options.php' ); ?>' method='post'>
1025 1257 <?php settings_fields( 'autoptimize_imgopt_settings' ); ?>
1026 1258 <h2><?php _e( 'Image optimization', 'autoptimize' ); ?></h2>
1027 - <span id='autoptimize_imgopt_descr'><?php _e( 'Make your site significantly faster by just ticking a couple of checkboxes to optimize and lazy load your images, WebP support included!', 'autoptimize' ); ?></span>
1259 + <span id='autoptimize_imgopt_descr'><?php echo apply_filters( 'autoptimize_filter_imgopt_intro_copy', __( 'Make your site significantly faster by simply ticking a few boxes and start serving CDN powered, optimized images in next-get formats like WebP and AVIF! No additional plugins or services needed.', 'autoptimize' ) ); ?></span>
1028 1260 <table class="form-table">
1029 1261 <tr>
1030 - <th scope="row"><?php _e( 'Optimize Images', 'autoptimize' ); ?></th>
1262 + <th scope="row"><?php _e( 'Image optimization & CDN', 'autoptimize' ); ?></th>
1031 1263 <td>
1032 - <label><input id='autoptimize_imgopt_checkbox' type='checkbox' name='autoptimize_imgopt_settings[autoptimize_imgopt_checkbox_field_1]' <?php if ( ! empty( $options['autoptimize_imgopt_checkbox_field_1'] ) && '1' === $options['autoptimize_imgopt_checkbox_field_1'] ) { echo 'checked="checked"'; } ?> value='1'><?php _e( 'Optimize images on the fly and serve them from Shortpixel\'s global CDN.', 'autoptimize' ); ?></label>
1264 + <label><input id='autoptimize_imgopt_checkbox' type='checkbox' name='autoptimize_imgopt_settings[autoptimize_imgopt_checkbox_field_1]' <?php if ( ! empty( $options['autoptimize_imgopt_checkbox_field_1'] ) && '1' === $options['autoptimize_imgopt_checkbox_field_1'] ) { echo 'checked="checked"'; } ?> value='1'><?php echo apply_filters( 'autoptimize_filter_imgopt_main_setting_copy', __( 'On-the-fly image optimization and fast delivery via the Shortpixel global CDN.', 'autoptimize' ) ); ?></label>
1033 1265 <?php
1034 1266 // show shortpixel status.
1035 1267 $_notice = autoptimizeImages::instance()->get_imgopt_status_notice();
1036 1268 if ( $_notice ) {
@@ -1051,26 +1283,32 @@
1051 1283 }
1052 1284 echo apply_filters( 'autoptimize_filter_imgopt_settings_status', '<p><strong><span style="color:' . $_notice_color . ';">' . __( 'Shortpixel status: ', 'autoptimize' ) . '</span></strong>' . $_notice['notice'] . '</p>' );
1053 1285 } else {
1054 1286 // translators: link points to shortpixel.
1055 - $upsell_msg_1 = '<p>' . sprintf( __( 'Get more Google love and improve your website\'s loading speed by having your publicly available images optimized on the fly (also in the "next-gen" WebP image format) by %1$sShortPixel%2$s and then cached and served fast from Shortpixel\'s global CDN.', 'autoptimize' ), '<a href="https://shortpixel.com/aospai' . $sp_url_suffix . '" target="_blank">', '</a>' );
1287 + $upsell_msg_1 = '<p>' . sprintf( __( 'Get more Google love by speeding up your website. Start serving on-the-fly optimized images (also in the "next-gen" <strong>WebP</strong> and <strong>AVIF</strong> image formats) by %1$sShortPixel%2$s. No additional image optimization plugins are needed: your images are optimized, cached and served from %3$sShortPixel\'s global CDN%2$s.', 'autoptimize' ), '<a href="https://autoptimize.shortpixel.com/" target="_blank">', '</a>', '<a href="https://help.shortpixel.com/article/62-where-does-the-cdn-has-pops" target="_blank">' );
1056 1288 if ( 'launch' === $options['availabilities']['extra_imgopt']['status'] ) {
1057 1289 $upsell_msg_2 = __( 'For a limited time only, this service is offered free for all Autoptimize users, <b>don\'t miss the chance to test it</b> and see how much it could improve your site\'s speed.', 'autoptimize' );
1058 1290 } else {
1059 - // translators: link points to shortpixel.
1060 - $upsell_msg_2 = sprintf( __( '%1$sSign-up now%2$s to receive a 1 000 bonus + 50&#37; more image optimization credits regardless of the traffic used. More image optimizations can be purchased starting with $4.99.', 'autoptimize' ), '<a href="https://shortpixel.com/aospai' . $sp_url_suffix . '" target="_blank">', '</a>' );
1291 + // translators: 1st link points to autoptimize.com.pro, 2nd to shortpixel.
1292 + $upsell_msg_2 = sprintf( __( 'For <strong>unlimited image optimizations %1$sbuy Autoptimize Pro%2$s</strong> which also includes Critical CSS and extra "booster" options or %3$ssign up at Shortpixel%4$s.', 'autoptimize' ), '<a href="https://autoptimize.com/pro/" target="_blank">', '</a>', '<a href="https://autoptimize.shortpixel.com/' . $sp_url_suffix . '" target="_blank">', '</a>' );
1061 1293 }
1062 - echo apply_filters( 'autoptimize_imgopt_imgopt_settings_copy', $upsell_msg_1 . ' ' . $upsell_msg_2 . '</p>' );
1294 + echo apply_filters( 'autoptimize_filter_imgopt_settings_copy', $upsell_msg_1 . ' ' . $upsell_msg_2 . '</p>' );
1063 1295 }
1064 1296 // translators: link points to shortpixel FAQ.
1065 - $faqcopy = sprintf( __( '<strong>Questions</strong>? Have a look at the %1$sShortPixel FAQ%2$s!', 'autoptimize' ), '<strong><a href="https://shortpixel.helpscoutdocs.com/category/60-shortpixel-ai-cdn" target="_blank">', '</strong></a>' );
1066 - $faqcopy = $faqcopy . ' ' . __( 'Only works for sites/ images that are publicly available.', 'autoptimize' );
1297 + $faqcopy = sprintf( __( '<strong>Questions</strong>? Take a look at the %1$sAutoptimize + ShortPixel FAQ%2$s!', 'autoptimize' ), '<strong><a href="https://help.shortpixel.com/category/405-autoptimize" target="_blank">', '</strong></a>' );
1298 + $faqcopy = $faqcopy . ' ' . __( 'Only works for websites and images that are publicly available.', 'autoptimize' );
1067 1299 // translators: links points to shortpixel TOS & Privacy Policy.
1068 - $toscopy = sprintf( __( 'Usage of this feature is subject to Shortpixel\'s %1$sTerms of Use%2$s and %3$sPrivacy policy%4$s.', 'autoptimize' ), '<a href="https://shortpixel.com/tos' . $sp_url_suffix . '" target="_blank">', '</a>', '<a href="https://shortpixel.com/pp' . $sp_url_suffix . '" target="_blank">', '</a>' );
1069 - echo apply_filters( 'autoptimize_imgopt_imgopt_settings_tos', '<p>' . $faqcopy . ' ' . $toscopy . '</p>' );
1300 + $toscopy = sprintf( __( 'Usage of this feature is subject to Shortpixel\'s %1$sTerms of Use%2$s and %3$sPrivacy policy%4$s.', 'autoptimize' ), '<a href="https://shortpixel.com/tos' . $sp_url_suffix . '" target="_blank">', '</a>', '<a href="https://shortpixel.com/privacy' . $sp_url_suffix . '" target="_blank">', '</a>' );
1301 + echo apply_filters( 'autoptimize_filter_imgopt_settings_tos', '<p>' . $faqcopy . ' ' . $toscopy . '</p>' );
1070 1302 ?>
1071 1303 </td>
1072 1304 </tr>
1305 + <tr id='autoptimize_imgopt_optimization_exclusions' <?php if ( ! array_key_exists( 'autoptimize_imgopt_checkbox_field_1', $options ) || ( isset( $options['autoptimize_imgopt_checkbox_field_1'] ) && '1' !== $options['autoptimize_imgopt_checkbox_field_1'] ) ) { echo 'class="hidden"'; } ?>>
1306 + <th scope="row"><?php _e( 'Optimization exclusions', 'autoptimize' ); ?></th>
1307 + <td>
1308 + <label><input type='text' style='width:80%' id='autoptimize_imgopt_optimization_exclusions' name='autoptimize_imgopt_settings[autoptimize_imgopt_text_field_6]' value='<?php if ( ! empty( $options['autoptimize_imgopt_text_field_6'] ) ) { echo esc_attr( $options['autoptimize_imgopt_text_field_6'] ); } ?>'><br /><?php _e( 'Comma-separated list of image classes or filenames that should not be optimized.', 'autoptimize' ); ?></label>
1309 + </td>
1310 + </tr>
1073 1311 <tr id='autoptimize_imgopt_quality' <?php if ( ! array_key_exists( 'autoptimize_imgopt_checkbox_field_1', $options ) || ( isset( $options['autoptimize_imgopt_checkbox_field_1'] ) && '1' !== $options['autoptimize_imgopt_checkbox_field_1'] ) ) { echo 'class="hidden"'; } ?>>
1074 1312 <th scope="row"><?php _e( 'Image Optimization quality', 'autoptimize' ); ?></th>
1075 1313 <td>
1076 1314 <label>
@@ -1092,19 +1330,29 @@
1092 1330 </label>
1093 1331 <p>
1094 1332 <?php
1095 1333 // translators: link points to shortpixel image test page.
1096 - echo apply_filters( 'autoptimize_imgopt_imgopt_quality_copy', sprintf( __( 'You can %1$stest compression levels here%2$s.', 'autoptimize' ), '<a href="https://shortpixel.com/oic' . $sp_url_suffix . '" target="_blank">', '</a>' ) );
1334 + echo apply_filters( 'autoptimize_filter_imgopt_quality_copy', sprintf( __( 'You can %1$stest compression levels here%2$s.', 'autoptimize' ), '<a href="https://shortpixel.com/online-image-compression' . $sp_url_suffix . '" target="_blank">', '</a>' ) );
1097 1335 ?>
1098 1336 </p>
1099 1337 </td>
1100 1338 </tr>
1101 - <tr id='autoptimize_imgopt_webp' <?php if ( ! array_key_exists( 'autoptimize_imgopt_checkbox_field_1', $options ) || ( isset( $options['autoptimize_imgopt_checkbox_field_1'] ) && '1' !== $options['autoptimize_imgopt_checkbox_field_1'] ) ) { echo 'class="hidden"'; } ?>>
1102 - <th scope="row"><?php _e( 'Load WebP in supported browsers?', 'autoptimize' ); ?></th>
1103 - <td>
1104 - <label><input type='checkbox' id='autoptimize_imgopt_webp_checkbox' name='autoptimize_imgopt_settings[autoptimize_imgopt_checkbox_field_4]' <?php if ( ! empty( $options['autoptimize_imgopt_checkbox_field_4'] ) && '1' === $options['autoptimize_imgopt_checkbox_field_3'] ) { echo 'checked="checked"'; } ?> value='1'><?php _e( 'Automatically serve "next-gen" WebP image format to any browser that supports it (requires lazy load to be active).', 'autoptimize' ); ?></label>
1105 - </td>
1106 - </tr>
1339 + <?php
1340 + if ( apply_filters( 'autoptimize_filter_imgopt_settings_show_avif', true ) ) {
1341 + ?>
1342 + <tr id='autoptimize_imgopt_ngimg' <?php if ( ! array_key_exists( 'autoptimize_imgopt_checkbox_field_1', $options ) || ( isset( $options['autoptimize_imgopt_checkbox_field_1'] ) && '1' !== $options['autoptimize_imgopt_checkbox_field_1'] ) ) { echo 'class="hidden"'; } ?>>
1343 + <th scope="row"><?php _e( 'Load AVIF in supported browsers?', 'autoptimize' ); ?></th>
1344 + <td>
1345 + <label><input type='checkbox' id='autoptimize_imgopt_ngimg_checkbox' name='autoptimize_imgopt_settings[autoptimize_imgopt_checkbox_field_4]' <?php if ( ! empty( $options['autoptimize_imgopt_checkbox_field_4'] ) && '1' === $options['autoptimize_imgopt_checkbox_field_4'] ) { echo 'checked="checked"'; } ?> value='1'><?php _e( 'Automatically serve AVIF image format to any browser that supports it.', 'autoptimize' ); ?></label>
1346 + </td>
1347 + </tr>
1348 + <?php
1349 + } else {
1350 + ?>
1351 + <input type='hidden' id='autoptimize_imgopt_ngimg_checkbox' name='autoptimize_imgopt_settings[autoptimize_imgopt_checkbox_field_4]' value='0'>
1352 + <?php
1353 + }
1354 + ?>
1107 1355 <tr>
1108 1356 <th scope="row"><?php _e( 'Lazy-load images?', 'autoptimize' ); ?></th>
1109 1357 <td>
1110 1358 <label><input type='checkbox' id='autoptimize_imgopt_lazyload_checkbox' name='autoptimize_imgopt_settings[autoptimize_imgopt_checkbox_field_3]' <?php if ( ! empty( $options['autoptimize_imgopt_checkbox_field_3'] ) && '1' === $options['autoptimize_imgopt_checkbox_field_3'] ) { echo 'checked="checked"'; } ?> value='1'><?php _e( 'Image lazy-loading will delay the loading of non-visible images to allow the browser to optimally load all resources for the "above the fold"-page first.', 'autoptimize' ); ?></label>
@@ -1109,14 +1357,20 @@
1109 1357 <td>
1110 1358 <label><input type='checkbox' id='autoptimize_imgopt_lazyload_checkbox' name='autoptimize_imgopt_settings[autoptimize_imgopt_checkbox_field_3]' <?php if ( ! empty( $options['autoptimize_imgopt_checkbox_field_3'] ) && '1' === $options['autoptimize_imgopt_checkbox_field_3'] ) { echo 'checked="checked"'; } ?> value='1'><?php _e( 'Image lazy-loading will delay the loading of non-visible images to allow the browser to optimally load all resources for the "above the fold"-page first.', 'autoptimize' ); ?></label>
1111 1359 </td>
1112 1360 </tr>
1113 - <tr id='autoptimize_imgopt_lazyload_exclusions' <?php if ( ! array_key_exists( 'autoptimize_imgopt_checkbox_field_3', $options ) || ( isset( $options['autoptimize_imgopt_checkbox_field_3'] ) && '1' !== $options['autoptimize_imgopt_checkbox_field_3'] ) ) { echo 'class="hidden"'; } ?>>
1361 + <tr id='autoptimize_imgopt_lazyload_exclusions' <?php if ( ! array_key_exists( 'autoptimize_imgopt_checkbox_field_3', $options ) || ( isset( $options['autoptimize_imgopt_checkbox_field_3'] ) && '1' !== $options['autoptimize_imgopt_checkbox_field_3'] ) ) { echo 'class="autoptimize_lazyload_child hidden"'; } else { echo 'class="autoptimize_lazyload_child"'; } ?>>
1114 1362 <th scope="row"><?php _e( 'Lazy-load exclusions', 'autoptimize' ); ?></th>
1115 1363 <td>
1116 - <label><input type='text' style='width:80%' id='autoptimize_imgopt_lazyload_exclusions' name='autoptimize_imgopt_settings[autoptimize_imgopt_text_field_5]' value='<?php if ( ! empty( $options['autoptimize_imgopt_text_field_5'] ) ) { echo esc_attr( $options['autoptimize_imgopt_text_field_5'] ); } ?>'><br /><?php _e( 'Comma-separated list of to be excluded image classes or filenames.', 'autoptimize' ); ?></label>
1364 + <label><input type='text' style='width:80%' id='autoptimize_imgopt_lazyload_exclusions_text' name='autoptimize_imgopt_settings[autoptimize_imgopt_text_field_5]' value='<?php if ( ! empty( $options['autoptimize_imgopt_text_field_5'] ) ) { echo esc_attr( $options['autoptimize_imgopt_text_field_5'] ); } ?>'><br /><?php _e( 'Comma-separated list of to be excluded image classes or filenames.', 'autoptimize' ); ?></label>
1117 1365 </td>
1118 1366 </tr>
1367 + <tr id='autoptimize_imgopt_lazyload_from_nth_image' <?php if ( ! array_key_exists( 'autoptimize_imgopt_checkbox_field_3', $options ) || ( isset( $options['autoptimize_imgopt_checkbox_field_3'] ) && '1' !== $options['autoptimize_imgopt_checkbox_field_3'] ) ) { echo 'class="autoptimize_lazyload_child hidden"'; } else { echo 'class="autoptimize_lazyload_child"'; } ?>>
1368 + <th scope="row"><?php _e( 'Lazy-load from nth image', 'autoptimize' ); ?></th>
1369 + <td>
1370 + <label><input type='number' min='0' max='50' style='width:80%' id='autoptimize_imgopt_lazyload_from_nth_image_number' name='autoptimize_imgopt_settings[autoptimize_imgopt_number_field_7]' value='<?php if ( ! empty( $options['autoptimize_imgopt_number_field_7'] ) ) { echo esc_attr( $options['autoptimize_imgopt_number_field_7'] ); } else { echo '1'; } ?>'><br /><?php _e( 'Don\'t lazyload the first X images, \'1\' lazyloads all.', 'autoptimize' ); ?></label>
1371 + </td>
1372 + </tr>
1119 1373 </table>
1120 1374 <p class="submit"><input type="submit" name="submit" id="submit" class="button button-primary" value="<?php _e( 'Save Changes', 'autoptimize' ); ?>" /></p>
1121 1375 </form>
1122 1376 <script>
@@ -1123,26 +1377,21 @@
1123 1377 jQuery(document).ready(function() {
1124 1378 jQuery("#autoptimize_imgopt_checkbox").change(function() {
1125 1379 if (this.checked) {
1126 1380 jQuery("#autoptimize_imgopt_quality").show("slow");
1127 - jQuery("#autoptimize_imgopt_webp").show("slow");
1381 + jQuery("#autoptimize_imgopt_ngimg").show("slow");
1382 + jQuery("#autoptimize_imgopt_optimization_exclusions").show("slow");
1128 1383 } else {
1129 1384 jQuery("#autoptimize_imgopt_quality").hide("slow");
1130 - jQuery("#autoptimize_imgopt_webp").hide("slow");
1385 + jQuery("#autoptimize_imgopt_ngimg").hide("slow");
1386 + jQuery("#autoptimize_imgopt_optimization_exclusions").hide("slow");
1131 1387 }
1132 1388 });
1133 - jQuery("#autoptimize_imgopt_webp_checkbox").change(function() {
1134 - if (this.checked) {
1135 - jQuery("#autoptimize_imgopt_lazyload_checkbox")[0].checked = true;
1136 - jQuery("#autoptimize_imgopt_lazyload_exclusions").show("slow");
1137 - }
1138 - });
1139 1389 jQuery("#autoptimize_imgopt_lazyload_checkbox").change(function() {
1140 1390 if (this.checked) {
1141 - jQuery("#autoptimize_imgopt_lazyload_exclusions").show("slow");
1391 + jQuery(".autoptimize_lazyload_child").show("slow");
1142 1392 } else {
1143 - jQuery("#autoptimize_imgopt_lazyload_exclusions").hide("slow");
1144 - jQuery("#autoptimize_imgopt_webp_checkbox")[0].checked = false;
1393 + jQuery(".autoptimize_lazyload_child").hide("slow");
1145 1394 }
1146 1395 });
1147 1396 });
1148 1397 </script>
@@ -1152,13 +1401,13 @@
1152 1401 /**
1153 1402 * Ïmg opt status as used on dashboard.
1154 1403 */
1155 1404 public function get_imgopt_status_notice() {
1156 - if ( $this->imgopt_active() ) {
1405 + if ( $this->imgopt_active() && apply_filters( 'autoptimize_filter_imgopt_status_shortpixel', true ) ) {
1157 1406 $_imgopt_notice = '';
1158 1407 $_stat = autoptimizeOptionWrapper::get_option( 'autoptimize_imgopt_provider_stat', '' );
1159 1408 $_site_host = AUTOPTIMIZE_SITE_DOMAIN;
1160 - $_imgopt_upsell = 'https://shortpixel.com/aospai/af/GWRGFLW109483/' . $_site_host;
1409 + $_imgopt_upsell = 'https://autoptimize.shortpixel.com/' . $_site_host;
1161 1410 $_imgopt_assoc = 'https://shortpixel.helpscoutdocs.com/article/94-how-to-associate-a-domain-to-my-account';
1162 1411 $_imgopt_unreach = 'https://shortpixel.helpscoutdocs.com/article/148-why-are-my-images-redirected-from-cdn-shortpixel-ai';
1163 1412
1164 1413 if ( is_array( $_stat ) ) {
@@ -1163,19 +1412,19 @@
1163 1412
1164 1413 if ( is_array( $_stat ) ) {
1165 1414 if ( 1 == $_stat['Status'] ) {
1166 1415 // translators: "add more credits" will appear in a "a href".
1167 - $_imgopt_notice = sprintf( __( 'Your ShortPixel image optimization and CDN quota is almost used, make sure you %1$sadd more credits%2$s to avoid slowing down your website.', 'autoptimize' ), '<a href="' . $_imgopt_upsell . '" target="_blank">', '</a>' );
1416 + $_imgopt_notice = sprintf( __( 'Your ShortPixel image optimization and CDN quota is almost used, make sure you %1$sadd more credits%2$s to avoid slowing down your website <strong>or consider using %3$sAutoptimize Pro%2$s which comes with (nearly) unlimited image optimization</strong> but also automated critical CSS and extra booster options.', 'autoptimize' ), '<a href="' . $_imgopt_upsell . '" target="_blank">', '</a>', '<a href="https://autoptimize.com/pro/" target="_blank">' );
1168 1417 } elseif ( -1 == $_stat['Status'] || -2 == $_stat['Status'] ) {
1169 1418 // translators: "add more credits" will appear in a "a href".
1170 - $_imgopt_notice = sprintf( __( 'Your ShortPixel image optimization and CDN quota was used, %1$sadd more credits%2$s to keep fast serving optimized images on your site', 'autoptimize' ), '<a href="' . $_imgopt_upsell . '" target="_blank">', '</a>' );
1419 + $_imgopt_notice = sprintf( __( 'Your ShortPixel image optimization and CDN quota has been exhausted, %1$sadd more credits%2$s to continue to quickly deliver optimized images on your website <strong>or consider using %3$sAutoptimize Pro%2$s which comes with (nearly) unlimited image optimization</strong> but also automated critical CSS and extra booster options.', 'autoptimize' ), '<a href="' . $_imgopt_upsell . '" target="_blank">', '</a>', '<a href="https://autoptimize.com/pro/" target="_blank">' );
1171 1420 // translators: "associate your domain" will appear in a "a href".
1172 - $_imgopt_notice = $_imgopt_notice . ' ' . sprintf( __( 'If you already have enough credits then you may need to %1$sassociate your domain%2$s to your Shortpixel account.', 'autoptimize' ), '<a rel="noopener noreferrer" href="' . $_imgopt_assoc . '" target="_blank">', '</a>' );
1421 + $_imgopt_notice = $_imgopt_notice . ' ' . sprintf( __( 'If you have enough CDN quota remaining, then you may need to %1$sassociate your domain%2$s to your Shortpixel account.', 'autoptimize' ), '<a rel="noopener noreferrer" href="' . $_imgopt_assoc . '" target="_blank">', '</a>' );
1173 1422 } elseif ( -3 == $_stat['Status'] ) {
1174 1423 // translators: "check the documentation here" will appear in a "a href".
1175 1424 $_imgopt_notice = sprintf( __( 'It seems ShortPixel image optimization is not able to fetch images from your site, %1$scheck the documentation here%2$s for more information', 'autoptimize' ), '<a href="' . $_imgopt_unreach . '" target="_blank">', '</a>' );
1176 1425 } else {
1177 - $_imgopt_upsell = 'https://shortpixel.com/g/af/GWRGFLW109483';
1426 + $_imgopt_upsell = 'https://autoptimize.shortpixel.com/';
1178 1427 // translators: "log in to check your account" will appear in a "a href".
1179 1428 $_imgopt_notice = sprintf( __( 'Your ShortPixel image optimization and CDN quota are in good shape, %1$slog in to check your account%2$s.', 'autoptimize' ), '<a href="' . $_imgopt_upsell . '" target="_blank">', '</a>' );
1180 1429 }
1181 1430
@@ -1180,12 +1429,15 @@
1180 1429 }
1181 1430
1182 1431 // add info on freshness + refresh link if status is not 2 (good shape).
1183 1432 if ( 2 != $_stat['Status'] ) {
1184 - $_imgopt_stats_refresh_url = add_query_arg( array(
1185 - 'page' => 'autoptimize_imgopt',
1186 - 'refreshImgProvStats' => '1',
1187 - ), admin_url( 'options-general.php' ) );
1433 + $_imgopt_stats_refresh_url = add_query_arg(
1434 + array(
1435 + 'page' => 'autoptimize_imgopt',
1436 + 'refreshImgProvStats' => '1',
1437 + ),
1438 + admin_url( 'options-general.php' )
1439 + );
1188 1440 if ( $_stat && array_key_exists( 'timestamp', $_stat ) && ! empty( $_stat['timestamp'] ) ) {
1189 1441 $_imgopt_stats_last_run = __( 'based on status at ', 'autoptimize' ) . date_i18n( autoptimizeOptionWrapper::get_option( 'time_format' ), $_stat['timestamp'] );
1190 1442 } else {
1191 1443 $_imgopt_stats_last_run = __( 'based on previously fetched data', 'autoptimize' );
@@ -1191,9 +1443,9 @@
1191 1443 $_imgopt_stats_last_run = __( 'based on previously fetched data', 'autoptimize' );
1192 1444 }
1193 1445 $_imgopt_notice .= ' (' . $_imgopt_stats_last_run . ', ';
1194 1446 // translators: "here to refresh" links to the Autoptimize Extra page and forces a refresh of the img opt stats.
1195 - $_imgopt_notice .= sprintf( __( 'click %1$shere to refresh%2$s', 'autoptimize' ), '<a href="' . $_imgopt_stats_refresh_url . '">', '</a>).' );
1447 + $_imgopt_notice .= sprintf( __( 'you can click %1$shere to refresh your quota status%2$s', 'autoptimize' ), '<a href="' . $_imgopt_stats_refresh_url . '">', '</a>).' );
1196 1448 }
1197 1449
1198 1450 // and make the full notice filterable.
1199 1451 $_imgopt_notice = apply_filters( 'autoptimize_filter_imgopt_notice', $_imgopt_notice );
@@ -1214,18 +1466,24 @@
1214 1466 }
1215 1467
1216 1468 /**
1217 1469 * Get img provider stats (used to display notice).
1470 + *
1471 + * @param bool $_refresh Should the stats be forcefully refreshed or not.
1218 1472 */
1219 - public function query_img_provider_stats() {
1220 - if ( ! empty( $this->options['autoptimize_imgopt_checkbox_field_1'] ) ) {
1473 + public function query_img_provider_stats( $_refresh = false ) {
1474 + if ( ! empty( $this->options['autoptimize_imgopt_checkbox_field_1'] ) && apply_filters( 'autoptimize_filter_imgopt_status_shortpixel', true ) ) {
1221 1475 $url = '';
1222 - $endpoint = $this->get_imgopt_host() . 'read-domain/';
1476 + $stat_dom = 'https://no-cdn.shortpixel.ai/';
1477 + $endpoint = $stat_dom . 'read-domain/';
1223 1478 $domain = AUTOPTIMIZE_SITE_DOMAIN;
1224 1479
1225 1480 // make sure parse_url result makes sense, keeping $url empty if not.
1226 1481 if ( $domain && ! empty( $domain ) ) {
1227 1482 $url = $endpoint . $domain;
1483 + if ( true === $_refresh ) {
1484 + $url = $url . '/refresh';
1485 + }
1228 1486 }
1229 1487
1230 1488 $url = apply_filters(
1231 1489 'autoptimize_filter_imgopt_stat_url',
@@ -1262,9 +1520,13 @@
1262 1520 {
1263 1521 static $launch_status = null;
1264 1522
1265 1523 if ( null === $launch_status ) {
1266 - $avail_imgopt = $this->options['availabilities']['extra_imgopt'];
1524 + $avail_imgopt = '';
1525 + if ( is_array( $this->options ) && array_key_exists( 'availabilities', $this->options ) && is_array( $this->options['availabilities'] ) && array_key_exists( 'extra_imgopt', $this->options['availabilities'] ) ) {
1526 + $avail_imgopt = $this->options['availabilities']['extra_imgopt'];
1527 + }
1528 +
1267 1529 $magic_number = intval( substr( md5( parse_url( AUTOPTIMIZE_WP_SITE_URL, PHP_URL_HOST ) ), 0, 3 ), 16 );
1268 1530 $has_launched = autoptimizeOptionWrapper::get_option( 'autoptimize_imgopt_launched', '' );
1269 1531 $launch_status = false;
1270 1532 if ( $has_launched || ( is_array( $avail_imgopt ) && array_key_exists( 'launch-threshold', $avail_imgopt ) && $magic_number < $avail_imgopt['launch-threshold'] ) ) {