Version Description
- fixed: ExactDN incorrectly scales Elementor background images rather than cropping
- fixed: ExactDN cannot work with Divi/Elementor background images due to use of external CSS files
- fixed: JS WebP rewriting picture tags that already have WebP markup in Force WebP mode
- fixed: JS WebP incorrectly parses GIF/SVG images in Force WebP mode
- fixed: JS WebP does not support lazy load + infinite scroll
- fixed: Lazy Load auto-scaling breaks if background image is enclosed in encoded quotes
- fixed: GRAND FlaGallery integration broken by hook suffix change
Download this release
Release Info
Developer | nosilver4u |
Plugin | EWWW Image Optimizer |
Version | 4.9.3 |
Comparing to | |
See all releases |
Code changes from version 4.8.1 to 4.9.3
- aux-optimize.php +8 -8
- bulk.php +2 -2
- changelog.txt +29 -0
- classes/{class-ewwwio-alt-webp.php → class-eio-alt-webp.php} +37 -13
- classes/class-eio-base.php +333 -0
- classes/class-eio-hs-beacon.php +116 -0
- classes/class-eio-lazy-load.php +672 -0
- classes/class-eio-page-parser.php +321 -0
- classes/class-ewww-flag.php +37 -5
- classes/class-ewww-nextgen.php +3 -3
- classes/class-ewwwio-hs-beacon.php +0 -110
- classes/class-ewwwio-lazy-load.php +0 -623
- classes/class-ewwwio-page-parser.php +0 -318
- classes/class-exactdn.php +2311 -2325
- common.php +314 -84
- ewww-image-optimizer.php +7 -3
- includes/eio.js +2 -2
- includes/lazysizes-post.js +5 -2
- includes/lazysizes.min.js +1 -1
- includes/load_webp.js +5 -0
- includes/load_webp.min.js +1 -1
- includes/ls.print.js +51 -0
- includes/ls.print.min.js +2 -0
- includes/ls.unveilhooks.js +3 -1
- readme.txt +33 -31
- tests/test-utility.php +3 -3
- unique.php +26 -13
aux-optimize.php
CHANGED
@@ -73,7 +73,7 @@ function ewww_image_optimizer_aux_images() {
|
|
73 |
$help_instructions = esc_html__( 'Enable the Debugging option and refresh this page to include debugging information with your question.', 'ewww-image-optimizer' ) . ' ' .
|
74 |
esc_html__( 'This will allow us to assist you more quickly.', 'ewww-image-optimizer' );
|
75 |
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
|
76 |
-
global $
|
77 |
ewww_image_optimizer_options( 'debug-silent' );
|
78 |
$output .= '<p style="clear:both"><b>' . esc_html__( 'Debugging Information', 'ewww-image-optimizer' ) . ':</b> <button id="ewww-copy-debug" class="button button-secondary" type="button">' . esc_html__( 'Copy', 'ewww-image-optimizer' ) . '</button>';
|
79 |
if ( is_file( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'debug.log' ) ) {
|
@@ -81,7 +81,7 @@ function ewww_image_optimizer_aux_images() {
|
|
81 |
$output .= " <a href='$debug_log_url'>" . esc_html( 'View Debug Log', 'ewww-image-optimizer' ) . "</a> - <a href='admin.php?action=ewww_image_optimizer_delete_debug_log'>" . esc_html( 'Remove Debug Log', 'ewww-image-optimizer' ) . '</a>';
|
82 |
}
|
83 |
$output .= '</p>';
|
84 |
-
$output .= '<div id="ewww-debug-info" style="border:1px solid #e5e5e5;background:#fff;overflow:auto;height:300px;width:800px;" contenteditable="true">' . $
|
85 |
$help_instructions = esc_html__( 'Debugging information will be included with your message automatically.', 'ewww-image-optimizer' ) . ' ' .
|
86 |
esc_html__( 'This will allow us to assist you more quickly.', 'ewww-image-optimizer' );
|
87 |
}
|
@@ -104,11 +104,11 @@ function ewww_image_optimizer_aux_images() {
|
|
104 |
'email' => utf8_encode( $help_email ),
|
105 |
);
|
106 |
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
|
107 |
-
$
|
108 |
-
$
|
109 |
-
foreach ( $
|
110 |
-
$hs_identify[ 'debug_info_' . $
|
111 |
-
$
|
112 |
}
|
113 |
}
|
114 |
?>
|
@@ -123,7 +123,7 @@ function ewww_image_optimizer_aux_images() {
|
|
123 |
</script>
|
124 |
<?php
|
125 |
}
|
126 |
-
$
|
127 |
ewwwio_memory( __FUNCTION__ );
|
128 |
}
|
129 |
|
73 |
$help_instructions = esc_html__( 'Enable the Debugging option and refresh this page to include debugging information with your question.', 'ewww-image-optimizer' ) . ' ' .
|
74 |
esc_html__( 'This will allow us to assist you more quickly.', 'ewww-image-optimizer' );
|
75 |
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
|
76 |
+
global $eio_debug;
|
77 |
ewww_image_optimizer_options( 'debug-silent' );
|
78 |
$output .= '<p style="clear:both"><b>' . esc_html__( 'Debugging Information', 'ewww-image-optimizer' ) . ':</b> <button id="ewww-copy-debug" class="button button-secondary" type="button">' . esc_html__( 'Copy', 'ewww-image-optimizer' ) . '</button>';
|
79 |
if ( is_file( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'debug.log' ) ) {
|
81 |
$output .= " <a href='$debug_log_url'>" . esc_html( 'View Debug Log', 'ewww-image-optimizer' ) . "</a> - <a href='admin.php?action=ewww_image_optimizer_delete_debug_log'>" . esc_html( 'Remove Debug Log', 'ewww-image-optimizer' ) . '</a>';
|
82 |
}
|
83 |
$output .= '</p>';
|
84 |
+
$output .= '<div id="ewww-debug-info" style="border:1px solid #e5e5e5;background:#fff;overflow:auto;height:300px;width:800px;" contenteditable="true">' . $eio_debug . '</div>';
|
85 |
$help_instructions = esc_html__( 'Debugging information will be included with your message automatically.', 'ewww-image-optimizer' ) . ' ' .
|
86 |
esc_html__( 'This will allow us to assist you more quickly.', 'ewww-image-optimizer' );
|
87 |
}
|
104 |
'email' => utf8_encode( $help_email ),
|
105 |
);
|
106 |
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
|
107 |
+
$eio_debug_array = explode( '<br>', $eio_debug );
|
108 |
+
$eio_debug_i = 0;
|
109 |
+
foreach ( $eio_debug_array as $eio_debug_line ) {
|
110 |
+
$hs_identify[ 'debug_info_' . $eio_debug_i ] = $eio_debug_line;
|
111 |
+
$eio_debug_i++;
|
112 |
}
|
113 |
}
|
114 |
?>
|
123 |
</script>
|
124 |
<?php
|
125 |
}
|
126 |
+
$eio_debug = '';
|
127 |
ewwwio_memory( __FUNCTION__ );
|
128 |
}
|
129 |
|
bulk.php
CHANGED
@@ -1609,10 +1609,10 @@ function ewww_image_optimizer_bulk_loop( $hook = '', $delay = 0 ) {
|
|
1609 |
// Store the updated list of attachment IDs back in the 'bulk_attachments' option.
|
1610 |
// update_option( 'ewww_image_optimizer_bulk_attachments', $attachments, false );.
|
1611 |
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
|
1612 |
-
global $
|
1613 |
$debug_button = esc_html__( 'Show Debug Output', 'ewww-image-optimizer' );
|
1614 |
$debug_id = uniqid();
|
1615 |
-
$output['results'] .= "<button type='button' class='ewww-show-debug-meta button button-secondary' data-id='$debug_id'>$debug_button</button><div class='ewww-debug-meta-$debug_id' style='background-color:#f1f1f1;display:none;'>$
|
1616 |
}
|
1617 |
if ( ! empty( $next_image->file ) ) {
|
1618 |
$next_file = esc_html( $next_image->file );
|
1609 |
// Store the updated list of attachment IDs back in the 'bulk_attachments' option.
|
1610 |
// update_option( 'ewww_image_optimizer_bulk_attachments', $attachments, false );.
|
1611 |
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
|
1612 |
+
global $eio_debug;
|
1613 |
$debug_button = esc_html__( 'Show Debug Output', 'ewww-image-optimizer' );
|
1614 |
$debug_id = uniqid();
|
1615 |
+
$output['results'] .= "<button type='button' class='ewww-show-debug-meta button button-secondary' data-id='$debug_id'>$debug_button</button><div class='ewww-debug-meta-$debug_id' style='background-color:#f1f1f1;display:none;'>$eio_debug</div>";
|
1616 |
}
|
1617 |
if ( ! empty( $next_image->file ) ) {
|
1618 |
$next_file = esc_html( $next_image->file );
|
changelog.txt
CHANGED
@@ -1,3 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
= 4.8.1 =
|
2 |
* added: Lazy Load background image support added for span elements
|
3 |
* changed: constrain by height for background images that are taller than they are wide
|
1 |
+
= 4.9.3 =
|
2 |
+
* fixed: ExactDN incorrectly scales Elementor background images rather than cropping
|
3 |
+
* fixed: ExactDN cannot work with Divi/Elementor background images due to use of external CSS files
|
4 |
+
* fixed: JS WebP rewriting picture tags that already have WebP markup in Force WebP mode
|
5 |
+
* fixed: JS WebP incorrectly parses GIF/SVG images in Force WebP mode
|
6 |
+
* fixed: JS WebP does not support lazy load + infinite scroll
|
7 |
+
* fixed: Lazy Load auto-scaling breaks if background image is enclosed in encoded quotes
|
8 |
+
* fixed: GRAND FlaGallery integration broken by hook suffix change
|
9 |
+
|
10 |
+
= 4.9.2 =
|
11 |
+
* fixed: generating lazy load PNG placeholders with large heights causes 500 errors
|
12 |
+
* fixed: error when importing media via WordPress Importer plugin
|
13 |
+
* fixed: error with WP/LR Sync
|
14 |
+
|
15 |
+
= 4.9.1 =
|
16 |
+
* fixed: error on settings screen when JS WebP is enabled
|
17 |
+
|
18 |
+
= 4.9.0 =
|
19 |
+
* added: Lazy Load background image support for section elements
|
20 |
+
* added: ExactDN background image support for li,span, and section elements
|
21 |
+
* added: lazysizes print plugin, enable via EWWW_IMAGE_OPTIMIZER_LAZY_PRINT constant
|
22 |
+
* added: compatibility with upcoming Easy Image Optimizer
|
23 |
+
* changed: automatic compression disabled during WP/LR Sync with admin notice
|
24 |
+
* changed: Lazy Load PNG placeholders capped at 1920px wide to prevent errors
|
25 |
+
* changed: use ExactDN, when active, for Lazy Load PNG placeholders
|
26 |
+
* changed: EWWW_MEMORY_LIMIT renamed to EIO_MEMORY_LIMIT for setting plugin memory limit
|
27 |
+
* fixed: WebP test image not refreshing after inserting .htaccess rules
|
28 |
+
* fixed: errors when manually adding lazysizes script
|
29 |
+
|
30 |
= 4.8.1 =
|
31 |
* added: Lazy Load background image support added for span elements
|
32 |
* changed: constrain by height for background images that are taller than they are wide
|
classes/{class-ewwwio-alt-webp.php → class-eio-alt-webp.php}
RENAMED
@@ -3,7 +3,7 @@
|
|
3 |
* Implements WebP rewriting using page parsing and JS functionality.
|
4 |
*
|
5 |
* @link https://ewww.io
|
6 |
-
* @package
|
7 |
*/
|
8 |
|
9 |
if ( ! defined( 'ABSPATH' ) ) {
|
@@ -13,7 +13,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
13 |
/**
|
14 |
* Enables EWWW IO to filter the page content and replace img elements with WebP markup.
|
15 |
*/
|
16 |
-
class
|
17 |
|
18 |
/**
|
19 |
* The Alt WebP inline script contents. Current length 11704.
|
@@ -43,8 +43,8 @@ class EWWWIO_Alt_Webp extends EWWWIO_Page_Parser {
|
|
43 |
* Register (once) actions and filters for Alt WebP.
|
44 |
*/
|
45 |
function __construct() {
|
46 |
-
global $
|
47 |
-
if ( is_object( $
|
48 |
return 'you are doing it wrong';
|
49 |
}
|
50 |
if ( ewww_image_optimizer_ce_webp_enabled() ) {
|
@@ -297,7 +297,9 @@ class EWWWIO_Alt_Webp extends EWWWIO_Page_Parser {
|
|
297 |
is_feed() ||
|
298 |
is_preview() ||
|
299 |
( defined( 'REST_REQUEST' ) && REST_REQUEST ) ||
|
300 |
-
preg_match( '/^<\?xml/', $buffer )
|
|
|
|
|
301 |
) {
|
302 |
if ( empty( $buffer ) ) {
|
303 |
ewwwio_debug_message( 'empty buffer' );
|
@@ -338,8 +340,12 @@ class EWWWIO_Alt_Webp extends EWWWIO_Page_Parser {
|
|
338 |
/* TODO: detect non-utf8 encoding and convert the buffer (if necessary). */
|
339 |
|
340 |
$images = $this->get_images_from_html( preg_replace( '/<noscript.*?\/noscript>/s', '', $buffer ), false );
|
341 |
-
if (
|
342 |
foreach ( $images[0] as $index => $image ) {
|
|
|
|
|
|
|
|
|
343 |
$file = $images['img_url'][ $index ];
|
344 |
ewwwio_debug_message( "parsing an image: $file" );
|
345 |
if ( strpos( $image, 'jetpack-lazy-image' ) && $this->validate_image_url( $file ) ) {
|
@@ -457,12 +463,16 @@ class EWWWIO_Alt_Webp extends EWWWIO_Page_Parser {
|
|
457 |
} // End if().
|
458 |
// Now we will look for any lazy images that don't have a src attribute (this search returns ALL img elements though).
|
459 |
$images = $this->get_images_from_html( preg_replace( '/<noscript.*?\/noscript>/s', '', $buffer ), false, false );
|
460 |
-
if (
|
461 |
ewwwio_debug_message( 'parsing images without requiring src' );
|
462 |
foreach ( $images[0] as $index => $image ) {
|
463 |
if ( $this->get_attribute( $image, 'src' ) ) {
|
464 |
continue;
|
465 |
}
|
|
|
|
|
|
|
|
|
466 |
ewwwio_debug_message( 'found img without src' );
|
467 |
if ( strpos( $image, 'data-src=' ) && strpos( $image, 'data-srcset=' ) && strpos( $image, 'lazyload' ) ) {
|
468 |
// EWWW IO Lazy Load.
|
@@ -515,6 +525,9 @@ class EWWWIO_Alt_Webp extends EWWWIO_Page_Parser {
|
|
515 |
$pictures = $this->get_picture_tags_from_html( $buffer );
|
516 |
if ( ewww_image_optimizer_iterable( $pictures ) ) {
|
517 |
foreach ( $pictures as $index => $picture ) {
|
|
|
|
|
|
|
518 |
$sources = $this->get_elements_from_html( $picture, 'source' );
|
519 |
if ( ewww_image_optimizer_iterable( $sources ) ) {
|
520 |
foreach ( $sources as $source ) {
|
@@ -642,9 +655,6 @@ class EWWWIO_Alt_Webp extends EWWWIO_Page_Parser {
|
|
642 |
}
|
643 |
}
|
644 |
ewwwio_debug_message( 'all done parsing page for alt webp' );
|
645 |
-
if ( true ) { // Set to true for extra logging.
|
646 |
-
ewww_image_optimizer_debug_log();
|
647 |
-
}
|
648 |
return $buffer;
|
649 |
}
|
650 |
|
@@ -689,7 +699,7 @@ class EWWWIO_Alt_Webp extends EWWWIO_Page_Parser {
|
|
689 |
/**
|
690 |
* Checks if the path is a valid "forced" WebP image.
|
691 |
*
|
692 |
-
* @param string $image The image
|
693 |
* @return bool True if the file matches a forced path, false otherwise.
|
694 |
*/
|
695 |
function validate_image_url( $image ) {
|
@@ -702,6 +712,20 @@ class EWWWIO_Alt_Webp extends EWWWIO_Page_Parser {
|
|
702 |
ewwwio_debug_message( 'lazy load placeholder' );
|
703 |
return false;
|
704 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
705 |
if ( $this->parsing_exactdn && false !== strpos( $image, $this->exactdn_domain ) ) {
|
706 |
ewwwio_debug_message( 'exactdn image' );
|
707 |
return true;
|
@@ -788,5 +812,5 @@ class EWWWIO_Alt_Webp extends EWWWIO_Page_Parser {
|
|
788 |
}
|
789 |
}
|
790 |
|
791 |
-
global $
|
792 |
-
$
|
3 |
* Implements WebP rewriting using page parsing and JS functionality.
|
4 |
*
|
5 |
* @link https://ewww.io
|
6 |
+
* @package EIO
|
7 |
*/
|
8 |
|
9 |
if ( ! defined( 'ABSPATH' ) ) {
|
13 |
/**
|
14 |
* Enables EWWW IO to filter the page content and replace img elements with WebP markup.
|
15 |
*/
|
16 |
+
class EIO_Alt_Webp extends EIO_Page_Parser {
|
17 |
|
18 |
/**
|
19 |
* The Alt WebP inline script contents. Current length 11704.
|
43 |
* Register (once) actions and filters for Alt WebP.
|
44 |
*/
|
45 |
function __construct() {
|
46 |
+
global $eio_alt_webp;
|
47 |
+
if ( is_object( $eio_alt_webp ) ) {
|
48 |
return 'you are doing it wrong';
|
49 |
}
|
50 |
if ( ewww_image_optimizer_ce_webp_enabled() ) {
|
297 |
is_feed() ||
|
298 |
is_preview() ||
|
299 |
( defined( 'REST_REQUEST' ) && REST_REQUEST ) ||
|
300 |
+
preg_match( '/^<\?xml/', $buffer ) ||
|
301 |
+
strpos( $buffer, 'amp-boilerplate' ) ||
|
302 |
+
ewww_image_optimizer_ce_webp_enabled()
|
303 |
) {
|
304 |
if ( empty( $buffer ) ) {
|
305 |
ewwwio_debug_message( 'empty buffer' );
|
340 |
/* TODO: detect non-utf8 encoding and convert the buffer (if necessary). */
|
341 |
|
342 |
$images = $this->get_images_from_html( preg_replace( '/<noscript.*?\/noscript>/s', '', $buffer ), false );
|
343 |
+
if ( ! empty( $images[0] ) && $this->is_iterable( $images[0] ) ) {
|
344 |
foreach ( $images[0] as $index => $image ) {
|
345 |
+
// Ignore 0-size Pinterest schema images.
|
346 |
+
if ( strpos( $image, 'data-pin-description=' ) && strpos( $image, 'width="0" height="0"' ) ) {
|
347 |
+
continue;
|
348 |
+
}
|
349 |
$file = $images['img_url'][ $index ];
|
350 |
ewwwio_debug_message( "parsing an image: $file" );
|
351 |
if ( strpos( $image, 'jetpack-lazy-image' ) && $this->validate_image_url( $file ) ) {
|
463 |
} // End if().
|
464 |
// Now we will look for any lazy images that don't have a src attribute (this search returns ALL img elements though).
|
465 |
$images = $this->get_images_from_html( preg_replace( '/<noscript.*?\/noscript>/s', '', $buffer ), false, false );
|
466 |
+
if ( ! empty( $images[0] ) && $this->is_iterable( $images[0] ) ) {
|
467 |
ewwwio_debug_message( 'parsing images without requiring src' );
|
468 |
foreach ( $images[0] as $index => $image ) {
|
469 |
if ( $this->get_attribute( $image, 'src' ) ) {
|
470 |
continue;
|
471 |
}
|
472 |
+
// Ignore 0-size Pinterest schema images.
|
473 |
+
if ( strpos( $image, 'data-pin-description=' ) && strpos( $image, 'width="0" height="0"' ) ) {
|
474 |
+
continue;
|
475 |
+
}
|
476 |
ewwwio_debug_message( 'found img without src' );
|
477 |
if ( strpos( $image, 'data-src=' ) && strpos( $image, 'data-srcset=' ) && strpos( $image, 'lazyload' ) ) {
|
478 |
// EWWW IO Lazy Load.
|
525 |
$pictures = $this->get_picture_tags_from_html( $buffer );
|
526 |
if ( ewww_image_optimizer_iterable( $pictures ) ) {
|
527 |
foreach ( $pictures as $index => $picture ) {
|
528 |
+
if ( strpos( $picture, 'image/webp' ) ) {
|
529 |
+
continue;
|
530 |
+
}
|
531 |
$sources = $this->get_elements_from_html( $picture, 'source' );
|
532 |
if ( ewww_image_optimizer_iterable( $sources ) ) {
|
533 |
foreach ( $sources as $source ) {
|
655 |
}
|
656 |
}
|
657 |
ewwwio_debug_message( 'all done parsing page for alt webp' );
|
|
|
|
|
|
|
658 |
return $buffer;
|
659 |
}
|
660 |
|
699 |
/**
|
700 |
* Checks if the path is a valid "forced" WebP image.
|
701 |
*
|
702 |
+
* @param string $image The image URL.
|
703 |
* @return bool True if the file matches a forced path, false otherwise.
|
704 |
*/
|
705 |
function validate_image_url( $image ) {
|
712 |
ewwwio_debug_message( 'lazy load placeholder' );
|
713 |
return false;
|
714 |
}
|
715 |
+
$extension = '';
|
716 |
+
$image_path = $this->parse_url( $image, PHP_URL_PATH );
|
717 |
+
if ( ! is_null( $image_path ) && $image_path ) {
|
718 |
+
$extension = strtolower( pathinfo( $image_path, PATHINFO_EXTENSION ) );
|
719 |
+
}
|
720 |
+
if ( $extension && 'gif' === $extension ) {
|
721 |
+
return false;
|
722 |
+
}
|
723 |
+
if ( $extension && 'svg' === $extension ) {
|
724 |
+
return false;
|
725 |
+
}
|
726 |
+
if ( $extension && 'webp' === $extension ) {
|
727 |
+
return false;
|
728 |
+
}
|
729 |
if ( $this->parsing_exactdn && false !== strpos( $image, $this->exactdn_domain ) ) {
|
730 |
ewwwio_debug_message( 'exactdn image' );
|
731 |
return true;
|
812 |
}
|
813 |
}
|
814 |
|
815 |
+
global $eio_alt_webp;
|
816 |
+
$eio_alt_webp = new EIO_Alt_Webp();
|
classes/class-eio-base.php
ADDED
@@ -0,0 +1,333 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Implements basic and common utility functions for all sub-classes.
|
4 |
+
*
|
5 |
+
* @link https://ewww.io
|
6 |
+
* @package EIO
|
7 |
+
*/
|
8 |
+
|
9 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
10 |
+
exit;
|
11 |
+
}
|
12 |
+
|
13 |
+
if ( ! class_exists( 'EIO_Base' ) ) {
|
14 |
+
/**
|
15 |
+
* HTML element and attribute parsing, replacing, etc.
|
16 |
+
*/
|
17 |
+
class EIO_Base {
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Content directory (URL) for the plugin to use.
|
21 |
+
*
|
22 |
+
* @access protected
|
23 |
+
* @var string $content_url
|
24 |
+
*/
|
25 |
+
protected $content_url = WP_CONTENT_URL . 'ewww/';
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Content directory (path) for the plugin to use.
|
29 |
+
*
|
30 |
+
* @access protected
|
31 |
+
* @var string $content_dir
|
32 |
+
*/
|
33 |
+
protected $content_dir = WP_CONTENT_DIR . '/ewww/';
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Plugin version for the plugin.
|
37 |
+
*
|
38 |
+
* @access protected
|
39 |
+
* @var float $version
|
40 |
+
*/
|
41 |
+
protected $version = 1.1;
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Prefix to be used by plugin in option and hook names.
|
45 |
+
*
|
46 |
+
* @access protected
|
47 |
+
* @var string $prefix
|
48 |
+
*/
|
49 |
+
protected $prefix = 'ewww_image_optimizer_';
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Set class properties for children.
|
53 |
+
*
|
54 |
+
* @param string $child_class_path The location of the child class extending the base class.
|
55 |
+
*/
|
56 |
+
function __construct( $child_class_path = '' ) {
|
57 |
+
if ( strpos( $child_class_path, 'ewww' ) ) {
|
58 |
+
$this->content_url = content_url( 'ewww/' );
|
59 |
+
$this->content_dir = WP_CONTENT_DIR . '/ewww/';
|
60 |
+
$this->version = EWWW_IMAGE_OPTIMIZER_VERSION;
|
61 |
+
} elseif ( strpos( $child_class_path, 'easy' ) ) {
|
62 |
+
$this->content_url = content_url( 'easyio/' );
|
63 |
+
$this->content_dir = WP_CONTENT_DIR . '/easyio/';
|
64 |
+
$this->version = EASYIO_VERSION;
|
65 |
+
$this->prefix = 'easyio_';
|
66 |
+
} else {
|
67 |
+
$this->content_url = content_url( 'ewww/' );
|
68 |
+
}
|
69 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Saves the in-memory debug log to a logfile in the plugin folder.
|
74 |
+
*
|
75 |
+
* @global string $eio_debug The in-memory debug log.
|
76 |
+
*/
|
77 |
+
function debug_log() {
|
78 |
+
global $eio_debug;
|
79 |
+
global $ewwwio_temp_debug;
|
80 |
+
global $easyio_temp_debug;
|
81 |
+
$debug_log = $this->content_dir . 'debug.log';
|
82 |
+
if ( is_writable( WP_CONTENT_DIR ) && ! is_dir( $this->content_dir ) ) {
|
83 |
+
mkdir( $this->content_dir );
|
84 |
+
}
|
85 |
+
$debug_enabled = $this->get_option( $this->prefix . 'debug' );
|
86 |
+
if ( ! empty( $eio_debug ) && empty( $ewwwio_temp_debug ) && empty( $easyio_temp_debug ) && $debug_enabled && is_writable( $this->content_dir ) ) {
|
87 |
+
$memory_limit = $this->memory_limit();
|
88 |
+
clearstatcache();
|
89 |
+
$timestamp = date( 'Y-m-d H:i:s' ) . "\n";
|
90 |
+
if ( ! file_exists( $debug_log ) ) {
|
91 |
+
touch( $debug_log );
|
92 |
+
} else {
|
93 |
+
if ( filesize( $debug_log ) + 4000000 + memory_get_usage( true ) > $memory_limit ) {
|
94 |
+
unlink( $debug_log );
|
95 |
+
touch( $debug_log );
|
96 |
+
}
|
97 |
+
}
|
98 |
+
if ( filesize( $debug_log ) + strlen( $eio_debug ) + 4000000 + memory_get_usage( true ) <= $memory_limit && is_writable( $debug_log ) ) {
|
99 |
+
$eio_debug = str_replace( '<br>', "\n", $eio_debug );
|
100 |
+
file_put_contents( $debug_log, $timestamp . $eio_debug, FILE_APPEND );
|
101 |
+
}
|
102 |
+
}
|
103 |
+
$eio_debug = '';
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Adds information to the in-memory debug log.
|
108 |
+
*
|
109 |
+
* @global string $eio_debug The in-memory debug log.
|
110 |
+
* @global bool $easyio_temp_debug Indicator that we are temporarily debugging on the wp-admin.
|
111 |
+
* @global bool $ewwwio_temp_debug Indicator that we are temporarily debugging on the wp-admin.
|
112 |
+
*
|
113 |
+
* @param string $message Debug information to add to the log.
|
114 |
+
*/
|
115 |
+
function debug_message( $message ) {
|
116 |
+
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
117 |
+
WP_CLI::debug( $message );
|
118 |
+
return;
|
119 |
+
}
|
120 |
+
global $ewwwio_temp_debug;
|
121 |
+
global $easyio_temp_debug;
|
122 |
+
if ( $easyio_temp_debug || $ewwwio_temp_debug || $this->get_option( $this->prefix . 'debug' ) ) {
|
123 |
+
$memory_limit = $this->memory_limit();
|
124 |
+
if ( strlen( $message ) + 4000000 + memory_get_usage( true ) <= $memory_limit ) {
|
125 |
+
global $eio_debug;
|
126 |
+
$message = str_replace( "\n\n\n", '<br>', $message );
|
127 |
+
$message = str_replace( "\n\n", '<br>', $message );
|
128 |
+
$message = str_replace( "\n", '<br>', $message );
|
129 |
+
$eio_debug .= "$message<br>";
|
130 |
+
} else {
|
131 |
+
global $eio_debug;
|
132 |
+
$eio_debug = "not logging message, memory limit is $memory_limit";
|
133 |
+
}
|
134 |
+
}
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Checks if a function is disabled or does not exist.
|
139 |
+
*
|
140 |
+
* @param string $function The name of a function to test.
|
141 |
+
* @param bool $debug Whether to output debugging.
|
142 |
+
* @return bool True if the function is available, False if not.
|
143 |
+
*/
|
144 |
+
function function_exists( $function, $debug = false ) {
|
145 |
+
if ( function_exists( 'ini_get' ) ) {
|
146 |
+
$disabled = @ini_get( 'disable_functions' );
|
147 |
+
if ( $debug ) {
|
148 |
+
easyio_debug_message( "disable_functions: $disabled" );
|
149 |
+
}
|
150 |
+
}
|
151 |
+
if ( extension_loaded( 'suhosin' ) && function_exists( 'ini_get' ) ) {
|
152 |
+
$suhosin_disabled = @ini_get( 'suhosin.executor.func.blacklist' );
|
153 |
+
if ( $debug ) {
|
154 |
+
easyio_debug_message( "suhosin_blacklist: $suhosin_disabled" );
|
155 |
+
}
|
156 |
+
if ( ! empty( $suhosin_disabled ) ) {
|
157 |
+
$suhosin_disabled = explode( ',', $suhosin_disabled );
|
158 |
+
$suhosin_disabled = array_map( 'trim', $suhosin_disabled );
|
159 |
+
$suhosin_disabled = array_map( 'strtolower', $suhosin_disabled );
|
160 |
+
if ( function_exists( $function ) && ! in_array( $function, $suhosin_disabled, true ) ) {
|
161 |
+
return true;
|
162 |
+
}
|
163 |
+
return false;
|
164 |
+
}
|
165 |
+
}
|
166 |
+
return function_exists( $function );
|
167 |
+
}
|
168 |
+
|
169 |
+
/**
|
170 |
+
* Check for GD support.
|
171 |
+
*
|
172 |
+
* @return bool Debug True if GD support detected.
|
173 |
+
*/
|
174 |
+
function gd_support() {
|
175 |
+
$this->debug_message( '<b>' . __FUNCTION__ . '()</b>' );
|
176 |
+
if ( function_exists( 'gd_info' ) ) {
|
177 |
+
$gd_support = gd_info();
|
178 |
+
$this->debug_message( 'GD found, supports:' );
|
179 |
+
if ( $this->is_iterable( $gd_support ) ) {
|
180 |
+
foreach ( $gd_support as $supports => $supported ) {
|
181 |
+
$this->debug_message( "$supports: $supported" );
|
182 |
+
}
|
183 |
+
if ( ( ! empty( $gd_support['JPEG Support'] ) || ! empty( $gd_support['JPG Support'] ) ) && ! empty( $gd_support['PNG Support'] ) ) {
|
184 |
+
return true;
|
185 |
+
}
|
186 |
+
}
|
187 |
+
}
|
188 |
+
return false;
|
189 |
+
}
|
190 |
+
|
191 |
+
/**
|
192 |
+
* Retrieve option: use 'site' setting if plugin is network activated, otherwise use 'blog' setting.
|
193 |
+
*
|
194 |
+
* Retrieves multi-site and single-site options as appropriate as well as allowing overrides with
|
195 |
+
* same-named constant. Overrides are only available for integer and boolean options.
|
196 |
+
*
|
197 |
+
* @param string $option_name The name of the option to retrieve.
|
198 |
+
* @return mixed The value of the option.
|
199 |
+
*/
|
200 |
+
function get_option( $option_name ) {
|
201 |
+
$constant_name = strtoupper( $option_name );
|
202 |
+
if ( defined( $constant_name ) && ( is_int( constant( $constant_name ) ) || is_bool( constant( $constant_name ) ) ) ) {
|
203 |
+
return constant( $constant_name );
|
204 |
+
}
|
205 |
+
if ( ! function_exists( 'is_plugin_active_for_network' ) && is_multisite() ) {
|
206 |
+
// Need to include the plugin library for the is_plugin_active function.
|
207 |
+
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
208 |
+
}
|
209 |
+
if (
|
210 |
+
is_multisite() &&
|
211 |
+
is_plugin_active_for_network( constant( strtoupper( $this->prefix ) . 'PLUGIN_FILE_REL' ) ) &&
|
212 |
+
! get_site_option( $this->prefix . 'allow_multisite_override' )
|
213 |
+
) {
|
214 |
+
$option_value = get_site_option( $option_name );
|
215 |
+
} else {
|
216 |
+
$option_value = get_option( $option_name );
|
217 |
+
}
|
218 |
+
return $option_value;
|
219 |
+
}
|
220 |
+
|
221 |
+
/**
|
222 |
+
* Implode a multi-dimensional array without throwing errors. Arguments can be reverse order, same as implode().
|
223 |
+
*
|
224 |
+
* @param string $delimiter The character to put between the array items (the glue).
|
225 |
+
* @param array $data The array to output with the glue.
|
226 |
+
* @return string The array values, separated by the delimiter.
|
227 |
+
*/
|
228 |
+
function implode( $delimiter, $data = '' ) {
|
229 |
+
if ( is_array( $delimiter ) ) {
|
230 |
+
$temp_data = $delimiter;
|
231 |
+
$delimiter = $data;
|
232 |
+
$data = $temp_data;
|
233 |
+
}
|
234 |
+
if ( is_array( $delimiter ) ) {
|
235 |
+
return '';
|
236 |
+
}
|
237 |
+
$output = '';
|
238 |
+
foreach ( $data as $value ) {
|
239 |
+
if ( is_string( $value ) || is_numeric( $value ) ) {
|
240 |
+
$output .= $value . $delimiter;
|
241 |
+
} elseif ( is_bool( $value ) ) {
|
242 |
+
$output .= ( $value ? 'true' : 'false' ) . $delimiter;
|
243 |
+
} elseif ( is_array( $value ) ) {
|
244 |
+
$output .= 'Array,';
|
245 |
+
}
|
246 |
+
}
|
247 |
+
return rtrim( $output, ',' );
|
248 |
+
}
|
249 |
+
|
250 |
+
/**
|
251 |
+
* Checks to see if the current page being output is an AMP page.
|
252 |
+
*
|
253 |
+
* @return bool True for an AMP endpoint, false otherwise.
|
254 |
+
*/
|
255 |
+
function is_amp() {
|
256 |
+
if ( function_exists( 'is_amp_endpoint' ) && is_amp_endpoint() ) {
|
257 |
+
return true;
|
258 |
+
}
|
259 |
+
if ( function_exists( 'ampforwp_is_amp_endpoint' ) && ampforwp_is_amp_endpoint() ) {
|
260 |
+
return true;
|
261 |
+
}
|
262 |
+
return false;
|
263 |
+
}
|
264 |
+
|
265 |
+
/**
|
266 |
+
* Make sure an array/object can be parsed by a foreach().
|
267 |
+
*
|
268 |
+
* @param mixed $var A variable to test for iteration ability.
|
269 |
+
* @return bool True if the variable is iterable.
|
270 |
+
*/
|
271 |
+
function is_iterable( $var ) {
|
272 |
+
return ! empty( $var ) && ( is_array( $var ) || $var instanceof Traversable );
|
273 |
+
}
|
274 |
+
|
275 |
+
/**
|
276 |
+
* Finds the current PHP memory limit or a reasonable default.
|
277 |
+
*
|
278 |
+
* @return int The memory limit in bytes.
|
279 |
+
*/
|
280 |
+
function memory_limit() {
|
281 |
+
if ( defined( 'EIO_MEMORY_LIMIT' ) && EIO_MEMORY_LIMIT ) {
|
282 |
+
$memory_limit = EIO_MEMORY_LIMIT;
|
283 |
+
} elseif ( function_exists( 'ini_get' ) ) {
|
284 |
+
$memory_limit = ini_get( 'memory_limit' );
|
285 |
+
} else {
|
286 |
+
if ( ! defined( 'EIO_MEMORY_LIMIT' ) ) {
|
287 |
+
// Conservative default, current usage + 16M.
|
288 |
+
$current_memory = memory_get_usage( true );
|
289 |
+
$memory_limit = round( $current_memory / ( 1024 * 1024 ) ) + 16;
|
290 |
+
define( 'EIO_MEMORY_LIMIT', $memory_limit );
|
291 |
+
}
|
292 |
+
}
|
293 |
+
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
294 |
+
WP_CLI::debug( "memory limit is set at $memory_limit" );
|
295 |
+
}
|
296 |
+
if ( ! $memory_limit || -1 === intval( $memory_limit ) ) {
|
297 |
+
// Unlimited, set to 32GB.
|
298 |
+
$memory_limit = '32000M';
|
299 |
+
}
|
300 |
+
if ( strpos( $memory_limit, 'G' ) ) {
|
301 |
+
$memory_limit = intval( $memory_limit ) * 1024 * 1024 * 1024;
|
302 |
+
} else {
|
303 |
+
$memory_limit = intval( $memory_limit ) * 1024 * 1024;
|
304 |
+
}
|
305 |
+
return $memory_limit;
|
306 |
+
}
|
307 |
+
|
308 |
+
/**
|
309 |
+
* Set an option: use 'site' setting if plugin is network activated, otherwise use 'blog' setting.
|
310 |
+
*
|
311 |
+
* @param string $option_name The name of the option to save.
|
312 |
+
* @param mixed $option_value The value to save for the option.
|
313 |
+
* @return bool True if the operation was successful.
|
314 |
+
*/
|
315 |
+
function set_option( $option_name, $option_value ) {
|
316 |
+
if ( ! function_exists( 'is_plugin_active_for_network' ) && is_multisite() ) {
|
317 |
+
// Need to include the plugin library for the is_plugin_active function.
|
318 |
+
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
319 |
+
}
|
320 |
+
if (
|
321 |
+
is_multisite() &&
|
322 |
+
is_plugin_active_for_network( constant( strtoupper( $this->prefix ) . 'PLUGIN_FILE_REL' ) ) &&
|
323 |
+
! get_site_option( $this->prefix . 'allow_multisite_override' )
|
324 |
+
) {
|
325 |
+
$success = update_site_option( $option_name, $option_value );
|
326 |
+
} else {
|
327 |
+
$success = update_option( $option_name, $option_value );
|
328 |
+
}
|
329 |
+
return $success;
|
330 |
+
}
|
331 |
+
|
332 |
+
}
|
333 |
+
}
|
classes/class-eio-hs-beacon.php
ADDED
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Help integration functions for embedding the HS Beacon for users that have opted in.
|
4 |
+
*
|
5 |
+
* @package EIO
|
6 |
+
* @since 3.5.1
|
7 |
+
*/
|
8 |
+
|
9 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
10 |
+
exit;
|
11 |
+
}
|
12 |
+
|
13 |
+
if ( ! class_exists( 'EIO_HS_Beacon' ) ) {
|
14 |
+
/**
|
15 |
+
* Embed HS Beacon to give users more help when they need it.
|
16 |
+
*
|
17 |
+
* @since 3.5.1
|
18 |
+
*/
|
19 |
+
class EIO_HS_Beacon extends EIO_Base {
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Get things going
|
23 |
+
*/
|
24 |
+
public function __construct() {
|
25 |
+
parent::__construct( __FILE__ );
|
26 |
+
add_action( 'admin_action_eio_opt_into_hs_beacon', array( $this, 'check_for_optin' ) );
|
27 |
+
add_action( 'admin_action_eio_opt_out_of_hs_beacon', array( $this, 'check_for_optout' ) );
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Check for a new opt-in on settings save
|
32 |
+
*
|
33 |
+
* @param bool $input The enable_help setting.
|
34 |
+
* @return bool The unaltered setting.
|
35 |
+
*/
|
36 |
+
public function check_for_settings_optin( $input ) {
|
37 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
38 |
+
if ( isset( $_POST[ $this->prefix . 'enable_help' ] ) && $_POST[ $this->prefix . 'enable_help' ] ) {
|
39 |
+
$this->set_option( $this->prefix . 'enable_help_notice', 1 );
|
40 |
+
}
|
41 |
+
return $input;
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Check for a new opt-in via the admin notice
|
46 |
+
*/
|
47 |
+
public function check_for_optin() {
|
48 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
49 |
+
$this->set_option( $this->prefix . 'enable_help', 1 );
|
50 |
+
$this->set_option( $this->prefix . 'enable_help_notice', 1 );
|
51 |
+
wp_redirect( remove_query_arg( 'action', wp_get_referer() ) );
|
52 |
+
exit;
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Check for a new opt-out via the admin notice
|
57 |
+
*/
|
58 |
+
public function check_for_optout() {
|
59 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
60 |
+
delete_option( $this->prefix . 'enable_help' );
|
61 |
+
delete_network_option( null, $this->prefix . 'enable_help' );
|
62 |
+
$this->set_option( $this->prefix . 'enable_help_notice', 1 );
|
63 |
+
wp_redirect( remove_query_arg( 'action', wp_get_referer() ) );
|
64 |
+
exit;
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Display the admin notice to users that have not opted-in or out
|
69 |
+
*
|
70 |
+
* @access public
|
71 |
+
* @param string $network_class A string that indicates where this is being displayed.
|
72 |
+
* @return void
|
73 |
+
*/
|
74 |
+
public function admin_notice( $network_class = '' ) {
|
75 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
76 |
+
$hide_notice = $this->get_option( $this->prefix . 'enable_help_notice' );
|
77 |
+
if ( 'network-multisite' === $network_class && get_site_option( $this->prefix . 'allow_multisite_override' ) ) {
|
78 |
+
return;
|
79 |
+
}
|
80 |
+
if ( 'network-singlesite' === $network_class && ! get_site_option( $this->prefix . 'allow_multisite_override' ) ) {
|
81 |
+
return;
|
82 |
+
}
|
83 |
+
|
84 |
+
if ( $hide_notice ) {
|
85 |
+
return;
|
86 |
+
}
|
87 |
+
if ( $this->get_option( $this->prefix . 'enable_help' ) ) {
|
88 |
+
return;
|
89 |
+
}
|
90 |
+
|
91 |
+
if ( ! current_user_can( 'manage_options' ) ) {
|
92 |
+
return;
|
93 |
+
}
|
94 |
+
|
95 |
+
if ( ! function_exists( 'is_plugin_active_for_network' ) && is_multisite() ) {
|
96 |
+
// Need to include the plugin library for the is_plugin_active function.
|
97 |
+
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
98 |
+
}
|
99 |
+
if (
|
100 |
+
is_multisite() &&
|
101 |
+
is_plugin_active_for_network( constant( strtoupper( $this->prefix ) . 'PLUGIN_FILE_REL' ) ) &&
|
102 |
+
! current_user_can( 'manage_network_options' )
|
103 |
+
) {
|
104 |
+
return;
|
105 |
+
}
|
106 |
+
if ( strpos( __FILE__, 'ewww' ) ) {
|
107 |
+
ewww_image_optimizer_notice_beacon();
|
108 |
+
} elseif ( strpos( __FILE__, 'easy' ) ) {
|
109 |
+
easyio_notice_beacon();
|
110 |
+
}
|
111 |
+
}
|
112 |
+
}
|
113 |
+
|
114 |
+
global $eio_hs_beacon;
|
115 |
+
$eio_hs_beacon = new EIO_HS_Beacon;
|
116 |
+
}
|
classes/class-eio-lazy-load.php
ADDED
@@ -0,0 +1,672 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Implements Lazy Loading using page parsing and JS functionality.
|
4 |
+
*
|
5 |
+
* @link https://ewww.io
|
6 |
+
* @package EIO
|
7 |
+
*/
|
8 |
+
|
9 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
10 |
+
exit;
|
11 |
+
}
|
12 |
+
|
13 |
+
if ( ! class_exists( 'EIO_Lazy_Load' ) ) {
|
14 |
+
/**
|
15 |
+
* Enables plugin to filter the page content and replace img elements with Lazy Load markup.
|
16 |
+
*/
|
17 |
+
class EIO_Lazy_Load extends EIO_Page_Parser {
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Base64-encoded placeholder image.
|
21 |
+
*
|
22 |
+
* @access protected
|
23 |
+
* @var string $placeholder_src
|
24 |
+
*/
|
25 |
+
protected $placeholder_src = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Indicates if we are filtering ExactDN urls.
|
29 |
+
*
|
30 |
+
* @access protected
|
31 |
+
* @var bool $parsing_exactdn
|
32 |
+
*/
|
33 |
+
protected $parsing_exactdn = false;
|
34 |
+
|
35 |
+
/**
|
36 |
+
* The folder to store any PIIPs.
|
37 |
+
*
|
38 |
+
* @access protected
|
39 |
+
* @var string $piip_folder
|
40 |
+
*/
|
41 |
+
protected $piip_folder = '';
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Whether to allow PIIPs.
|
45 |
+
*
|
46 |
+
* @access public
|
47 |
+
* @var bool $allow_piip
|
48 |
+
*/
|
49 |
+
public $allow_piip = true;
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Register (once) actions and filters for Lazy Load.
|
53 |
+
*/
|
54 |
+
function __construct() {
|
55 |
+
parent::__construct( __FILE__ );
|
56 |
+
$this->piip_folder = $this->content_dir . 'lazy/';
|
57 |
+
$this->debug_message( 'firing up lazy load' );
|
58 |
+
global $eio_lazy_load;
|
59 |
+
if ( is_object( $eio_lazy_load ) ) {
|
60 |
+
$this->debug_message( 'you are doing it wrong' );
|
61 |
+
return 'you are doing it wrong';
|
62 |
+
}
|
63 |
+
|
64 |
+
add_action( 'wp_head', array( $this, 'no_js_css' ) );
|
65 |
+
|
66 |
+
add_filter( $this->prefix . 'filter_page_output', array( $this, 'filter_page_output' ), 15 );
|
67 |
+
|
68 |
+
if ( class_exists( 'ExactDN' ) && $this->get_option( $this->prefix . 'exactdn' ) ) {
|
69 |
+
global $exactdn;
|
70 |
+
$this->exactdn_domain = $exactdn->get_exactdn_domain();
|
71 |
+
if ( $this->exactdn_domain ) {
|
72 |
+
$this->parsing_exactdn = true;
|
73 |
+
$this->debug_message( 'parsing an exactdn page' );
|
74 |
+
}
|
75 |
+
}
|
76 |
+
|
77 |
+
if ( $this->parsing_exactdn ) {
|
78 |
+
$this->allow_piip = true;
|
79 |
+
} elseif ( ! is_dir( $this->piip_folder ) ) {
|
80 |
+
$this->allow_piip = wp_mkdir_p( $this->piip_folder ) && $this->gd_support();
|
81 |
+
} else {
|
82 |
+
$this->allow_piip = is_writable( $this->piip_folder ) && $this->gd_support();
|
83 |
+
}
|
84 |
+
|
85 |
+
// Filter early, so that others at the default priority take precendence.
|
86 |
+
add_filter( 'eio_use_lqip', array( $this, 'maybe_lqip' ), 9 );
|
87 |
+
add_filter( 'eio_use_piip', array( $this, 'maybe_piip' ), 9 );
|
88 |
+
add_filter( 'eio_use_siip', array( $this, 'maybe_siip' ), 9 );
|
89 |
+
|
90 |
+
// Overrides for admin-ajax images.
|
91 |
+
add_filter( 'eio_allow_admin_lazyload', array( $this, 'allow_admin_lazyload' ) );
|
92 |
+
|
93 |
+
// Load the appropriate JS.
|
94 |
+
if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
|
95 |
+
// Load the non-minified and separate versions of the lazy load scripts.
|
96 |
+
add_action( 'wp_enqueue_scripts', array( $this, 'debug_script' ) );
|
97 |
+
} else {
|
98 |
+
// Load the minified, combined version of the lazy load script.
|
99 |
+
add_action( 'wp_enqueue_scripts', array( $this, 'min_script' ) );
|
100 |
+
}
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Starts an output buffer and registers the callback function to do WebP replacement.
|
105 |
+
*/
|
106 |
+
function buffer_start() {
|
107 |
+
ob_start( array( $this, 'filter_page_output' ) );
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Replaces images within a srcset attribute, just a placeholder at the moment.
|
112 |
+
*
|
113 |
+
* @param string $srcset A valid srcset attribute from an img element.
|
114 |
+
* @return bool|string False if no changes were made, or the new srcset if any WebP images replaced the originals.
|
115 |
+
*/
|
116 |
+
function srcset_replace( $srcset ) {
|
117 |
+
return $srcset;
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Search for img elements and rewrite them for Lazy Load with fallback to noscript elements.
|
122 |
+
*
|
123 |
+
* @param string $buffer The full HTML page generated since the output buffer was started.
|
124 |
+
* @return string The altered buffer containing the full page with Lazy Load attributes.
|
125 |
+
*/
|
126 |
+
function filter_page_output( $buffer ) {
|
127 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
128 |
+
// Don't foul up the admin side of things, unless a plugin needs to.
|
129 |
+
if ( is_admin() &&
|
130 |
+
/**
|
131 |
+
* Provide plugins a way of running Lazy Load for images in the WordPress Dashboard (wp-admin).
|
132 |
+
*
|
133 |
+
* @param bool false Allow Lazy Load to run on the Dashboard. Default to false.
|
134 |
+
*/
|
135 |
+
false === apply_filters( 'eio_allow_admin_lazyload', false )
|
136 |
+
) {
|
137 |
+
$this->debug_message( 'is_admin' );
|
138 |
+
return $buffer;
|
139 |
+
}
|
140 |
+
// Don't lazy load in these cases...
|
141 |
+
$uri = $_SERVER['REQUEST_URI'];
|
142 |
+
if (
|
143 |
+
empty( $buffer ) ||
|
144 |
+
! empty( $_GET['cornerstone'] ) ||
|
145 |
+
strpos( $uri, 'cornerstone-endpoint' ) !== false ||
|
146 |
+
! empty( $_GET['ct_builder'] ) ||
|
147 |
+
! empty( $_GET['elementor-preview'] ) ||
|
148 |
+
! empty( $_GET['et_fb'] ) ||
|
149 |
+
! empty( $_GET['tatsu'] ) ||
|
150 |
+
( ! empty( $_POST['action'] ) && 'tatsu_get_concepts' === $_POST['action'] ) ||
|
151 |
+
! apply_filters( 'eio_do_lazyload', true ) ||
|
152 |
+
is_feed() ||
|
153 |
+
is_preview() ||
|
154 |
+
( defined( 'REST_REQUEST' ) && REST_REQUEST ) ||
|
155 |
+
wp_script_is( 'twentytwenty-twentytwenty', 'enqueued' ) ||
|
156 |
+
preg_match( '/^<\?xml/', $buffer ) ||
|
157 |
+
strpos( $buffer, 'amp-boilerplate' )
|
158 |
+
) {
|
159 |
+
if ( empty( $buffer ) ) {
|
160 |
+
$this->debug_message( 'empty buffer' );
|
161 |
+
}
|
162 |
+
if ( ! empty( $_GET['cornerstone'] ) || strpos( $uri, 'cornerstone-endpoint' ) !== false ) {
|
163 |
+
$this->debug_message( 'cornerstone editor' );
|
164 |
+
}
|
165 |
+
if ( ! empty( $_GET['ct_builder'] ) ) {
|
166 |
+
$this->debug_message( 'oxygen builder' );
|
167 |
+
}
|
168 |
+
if ( ! empty( $_GET['elementor-preview'] ) ) {
|
169 |
+
$this->debug_message( 'elementor preview' );
|
170 |
+
}
|
171 |
+
if ( ! empty( $_GET['et_fb'] ) ) {
|
172 |
+
$this->debug_message( 'et_fb' );
|
173 |
+
}
|
174 |
+
if ( ! empty( $_GET['tatsu'] ) || ( ! empty( $_POST['action'] ) && 'tatsu_get_concepts' === $_POST['action'] ) ) {
|
175 |
+
$this->debug_message( 'tatsu' );
|
176 |
+
}
|
177 |
+
if ( ! apply_filters( 'eio_do_lazyload', true ) ) {
|
178 |
+
$this->debug_message( 'do_lazyload short-circuit' );
|
179 |
+
}
|
180 |
+
if ( is_feed() ) {
|
181 |
+
$this->debug_message( 'is_feed' );
|
182 |
+
}
|
183 |
+
if ( is_preview() ) {
|
184 |
+
$this->debug_message( 'is_preview' );
|
185 |
+
}
|
186 |
+
if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
|
187 |
+
$this->debug_message( 'rest request' );
|
188 |
+
}
|
189 |
+
if ( wp_script_is( 'twentytwenty-twentytwenty', 'enqueued' ) ) {
|
190 |
+
$this->debug_message( 'twentytwenty enqueued' );
|
191 |
+
}
|
192 |
+
if ( preg_match( '/^<\?xml/', $buffer ) ) {
|
193 |
+
$this->debug_message( 'not html, xml tag found' );
|
194 |
+
}
|
195 |
+
if ( strpos( $buffer, 'amp-boilerplate' ) ) {
|
196 |
+
$this->debug_message( 'AMP page processing' );
|
197 |
+
}
|
198 |
+
return $buffer;
|
199 |
+
}
|
200 |
+
|
201 |
+
global $exactdn;
|
202 |
+
$above_the_fold = apply_filters( 'eio_lazy_fold', 0 );
|
203 |
+
$images_processed = 0;
|
204 |
+
|
205 |
+
// Clean the buffer of incompatible sections.
|
206 |
+
$search_buffer = preg_replace( '/<div id="footer_photostream".*?\/div>/s', '', $buffer );
|
207 |
+
$search_buffer = preg_replace( '/<(noscript|script).*?\/\1>/s', '', $search_buffer );
|
208 |
+
|
209 |
+
$images = $this->get_images_from_html( $search_buffer, false );
|
210 |
+
if ( ! empty( $images[0] ) && $this->is_iterable( $images[0] ) ) {
|
211 |
+
foreach ( $images[0] as $index => $image ) {
|
212 |
+
$images_processed++;
|
213 |
+
if ( $images_processed <= $above_the_fold ) {
|
214 |
+
continue;
|
215 |
+
}
|
216 |
+
$file = $images['img_url'][ $index ];
|
217 |
+
$this->debug_message( "parsing an image: $file" );
|
218 |
+
if ( $this->validate_image_tag( $image ) ) {
|
219 |
+
$this->debug_message( 'found a valid image tag' );
|
220 |
+
$this->debug_message( "original image tag: $image" );
|
221 |
+
$orig_img = $image;
|
222 |
+
$noscript = '<noscript>' . $orig_img . '</noscript>';
|
223 |
+
$this->set_attribute( $image, 'data-src', $file, true );
|
224 |
+
$srcset = $this->get_attribute( $image, 'srcset' );
|
225 |
+
|
226 |
+
$placeholder_src = $this->placeholder_src;
|
227 |
+
if ( false === strpos( $file, 'nggid' ) && ! preg_match( '#\.svg(\?|$)#', $file ) && apply_filters( 'eio_use_lqip', true, $file ) && $this->parsing_exactdn && strpos( $file, $this->exactdn_domain ) ) {
|
228 |
+
$this->debug_message( 'using lqip' );
|
229 |
+
list( $width, $height ) = $this->get_dimensions_from_filename( $file );
|
230 |
+
if ( $width && $height && $width < 201 && $height < 201 ) {
|
231 |
+
$placeholder_src = $exactdn->generate_url( $this->content_url . 'lazy/placeholder-' . $width . 'x' . $height . '.png' );
|
232 |
+
} else {
|
233 |
+
$placeholder_src = add_query_arg( array( 'lazy' => 1 ), $file );
|
234 |
+
}
|
235 |
+
} elseif ( $this->allow_piip && $srcset && apply_filters( 'eio_use_piip', true, $file ) ) {
|
236 |
+
$this->debug_message( 'trying piip' );
|
237 |
+
// Get image dimensions for PNG placeholder.
|
238 |
+
list( $width, $height ) = $this->get_dimensions_from_filename( $file );
|
239 |
+
|
240 |
+
$width_attr = $this->get_attribute( $image, 'width' );
|
241 |
+
$height_attr = $this->get_attribute( $image, 'height' );
|
242 |
+
|
243 |
+
// Can't use a relative width or height, so unset the dimensions in favor of not breaking things.
|
244 |
+
if ( false !== strpos( $width_attr, '%' ) || false !== strpos( $height_attr, '%' ) ) {
|
245 |
+
$width_attr = false;
|
246 |
+
$height_attr = false;
|
247 |
+
}
|
248 |
+
|
249 |
+
if ( false === $width || false === $height ) {
|
250 |
+
$width = $width_attr;
|
251 |
+
$height = $height_attr;
|
252 |
+
}
|
253 |
+
|
254 |
+
// Falsify them if empty.
|
255 |
+
$width = $width ? (int) $width : false;
|
256 |
+
$height = $height ? (int) $height : false;
|
257 |
+
if ( $width && $height ) {
|
258 |
+
$this->debug_message( "creating piip of $width x $height" );
|
259 |
+
$placeholder_src = $this->create_piip( $width, $height );
|
260 |
+
}
|
261 |
+
} elseif ( apply_filters( 'eio_use_siip', true, $file ) ) {
|
262 |
+
$this->debug_message( 'trying siip' );
|
263 |
+
$width = $this->get_attribute( $image, 'width' );
|
264 |
+
$height = $this->get_attribute( $image, 'height' );
|
265 |
+
|
266 |
+
// Can't use a relative width or height, so unset the dimensions in favor of not breaking things.
|
267 |
+
if ( false !== strpos( $width, '%' ) || false !== strpos( $height, '%' ) ) {
|
268 |
+
$width = false;
|
269 |
+
$height = false;
|
270 |
+
}
|
271 |
+
|
272 |
+
// Falsify them if empty.
|
273 |
+
$width = $width ? (int) $width : false;
|
274 |
+
$height = $height ? (int) $height : false;
|
275 |
+
if ( $width && $height ) {
|
276 |
+
$placeholder_src = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 $width $height'%3E%3C/svg%3E";
|
277 |
+
}
|
278 |
+
}
|
279 |
+
$this->debug_message( "current placeholder is $placeholder_src" );
|
280 |
+
|
281 |
+
if ( $srcset ) {
|
282 |
+
$placeholder_src = apply_filters( 'eio_lazy_placeholder', $placeholder_src, $image );
|
283 |
+
if ( strpos( $placeholder_src, '64,R0lGOD' ) ) {
|
284 |
+
$this->set_attribute( $image, 'srcset', $placeholder_src, true );
|
285 |
+
$this->remove_attribute( $image, 'src' );
|
286 |
+
} else {
|
287 |
+
$this->set_attribute( $image, 'src', $placeholder_src, true );
|
288 |
+
$this->remove_attribute( $image, 'srcset' );
|
289 |
+
}
|
290 |
+
$this->set_attribute( $image, 'data-srcset', $srcset, true );
|
291 |
+
$srcset_sizes = $this->get_attribute( $image, 'sizes' );
|
292 |
+
// Return false on this filter to disable automatic sizes calculation,
|
293 |
+
// or use the sizes value passed via the filter to conditionally disable it.
|
294 |
+
if ( apply_filters( 'eio_lazy_responsive', $srcset_sizes ) ) {
|
295 |
+
$this->set_attribute( $image, 'data-sizes', 'auto', true );
|
296 |
+
$this->remove_attribute( $image, 'sizes' );
|
297 |
+
}
|
298 |
+
} else {
|
299 |
+
$this->set_attribute( $image, 'src', $placeholder_src, true );
|
300 |
+
}
|
301 |
+
$this->set_attribute( $image, 'class', $this->get_attribute( $image, 'class' ) . ' lazyload', true );
|
302 |
+
$buffer = str_replace( $orig_img, $image . $noscript, $buffer );
|
303 |
+
}
|
304 |
+
} // End foreach().
|
305 |
+
} // End if().
|
306 |
+
// Process background images on div elements.
|
307 |
+
$buffer = $this->parse_background_images( $buffer, 'div' );
|
308 |
+
// Process background images on li elements.
|
309 |
+
$buffer = $this->parse_background_images( $buffer, 'li' );
|
310 |
+
// Process background images on span elements.
|
311 |
+
$buffer = $this->parse_background_images( $buffer, 'span' );
|
312 |
+
// Process background images on section elements.
|
313 |
+
$buffer = $this->parse_background_images( $buffer, 'section' );
|
314 |
+
// Images listed as picture/source elements. Mostly for NextGEN, but should work anywhere.
|
315 |
+
$pictures = $this->get_picture_tags_from_html( $buffer );
|
316 |
+
if ( $this->is_iterable( $pictures ) ) {
|
317 |
+
foreach ( $pictures as $index => $picture ) {
|
318 |
+
$sources = $this->get_elements_from_html( $picture, 'source' );
|
319 |
+
if ( $this->is_iterable( $sources ) ) {
|
320 |
+
foreach ( $sources as $source ) {
|
321 |
+
if ( false !== strpos( $source, 'data-src' ) ) {
|
322 |
+
continue;
|
323 |
+
}
|
324 |
+
$this->debug_message( "parsing a picture source: $source" );
|
325 |
+
$srcset = $this->get_attribute( $source, 'srcset' );
|
326 |
+
if ( $srcset ) {
|
327 |
+
$this->debug_message( 'found srcset in source' );
|
328 |
+
$lazy_source = $source;
|
329 |
+
$this->set_attribute( $lazy_source, 'data-srcset', $srcset );
|
330 |
+
$this->set_attribute( $lazy_source, 'srcset', $this->placeholder_src, true );
|
331 |
+
$picture = str_replace( $source, $lazy_source, $picture );
|
332 |
+
}
|
333 |
+
}
|
334 |
+
if ( $picture !== $pictures[ $index ] ) {
|
335 |
+
$this->debug_message( 'lazified sources for picture element' );
|
336 |
+
$buffer = str_replace( $pictures[ $index ], $picture, $buffer );
|
337 |
+
}
|
338 |
+
}
|
339 |
+
}
|
340 |
+
}
|
341 |
+
// Video elements, looking for poster attributes that are images.
|
342 |
+
/* $videos = $this->get_elements_from_html( $buffer, 'video' ); */
|
343 |
+
$videos = '';
|
344 |
+
if ( $this->is_iterable( $videos ) ) {
|
345 |
+
foreach ( $videos as $index => $video ) {
|
346 |
+
$this->debug_message( 'parsing a video element' );
|
347 |
+
$file = $this->get_attribute( $video, 'poster' );
|
348 |
+
if ( $file ) {
|
349 |
+
$this->debug_message( "checking webp for video poster: $file" );
|
350 |
+
if ( $this->validate_image_tag( $file ) ) {
|
351 |
+
$this->set_attribute( $video, 'data-poster-webp', $this->placeholder_src );
|
352 |
+
$this->set_attribute( $video, 'data-poster-image', $file );
|
353 |
+
$this->remove_attribute( $video, 'poster' );
|
354 |
+
$this->debug_message( "found webp for video poster: $file" );
|
355 |
+
$buffer = str_replace( $videos[ $index ], $video, $buffer );
|
356 |
+
}
|
357 |
+
}
|
358 |
+
}
|
359 |
+
}
|
360 |
+
$this->debug_message( 'all done parsing page for lazy' );
|
361 |
+
return $buffer;
|
362 |
+
}
|
363 |
+
|
364 |
+
/**
|
365 |
+
* Parse elements of a given type for inline CSS background images.
|
366 |
+
*
|
367 |
+
* @param string $buffer The HTML content to parse.
|
368 |
+
* @param string $tag_type The type of HTML tag to look for.
|
369 |
+
* @return string The modified content with LL markup.
|
370 |
+
*/
|
371 |
+
function parse_background_images( $buffer, $tag_type ) {
|
372 |
+
$elements = $this->get_elements_from_html( $buffer, $tag_type );
|
373 |
+
if ( $this->is_iterable( $elements ) ) {
|
374 |
+
foreach ( $elements as $index => $element ) {
|
375 |
+
$this->debug_message( "parsing a $tag_type" );
|
376 |
+
if ( false === strpos( $element, 'background:' ) && false === strpos( $element, 'background-image:' ) ) {
|
377 |
+
continue;
|
378 |
+
}
|
379 |
+
$this->debug_message( 'element contains background/background-image:' );
|
380 |
+
if ( ! $this->validate_bgimage_tag( $element ) ) {
|
381 |
+
continue;
|
382 |
+
}
|
383 |
+
$this->debug_message( 'element is valid' );
|
384 |
+
$style = $this->get_attribute( $element, 'style' );
|
385 |
+
if ( empty( $style ) ) {
|
386 |
+
continue;
|
387 |
+
}
|
388 |
+
$this->debug_message( "checking style attr for background-image: $style" );
|
389 |
+
$bg_image_url = $this->get_background_image_url( $style );
|
390 |
+
if ( $bg_image_url ) {
|
391 |
+
$this->debug_message( 'bg-image url found' );
|
392 |
+
$new_style = $this->remove_background_image( $style );
|
393 |
+
if ( $style !== $new_style ) {
|
394 |
+
$this->debug_message( 'style modified, continuing' );
|
395 |
+
$this->set_attribute( $element, 'class', $this->get_attribute( $element, 'class' ) . ' lazyload', true );
|
396 |
+
$this->set_attribute( $element, 'data-bg', $bg_image_url );
|
397 |
+
$element = str_replace( $style, $new_style, $element );
|
398 |
+
}
|
399 |
+
}
|
400 |
+
if ( $element !== $elements[ $index ] ) {
|
401 |
+
$this->debug_message( "$tag_type modified, replacing in html source" );
|
402 |
+
$buffer = str_replace( $elements[ $index ], $element, $buffer );
|
403 |
+
}
|
404 |
+
}
|
405 |
+
}
|
406 |
+
return $buffer;
|
407 |
+
}
|
408 |
+
|
409 |
+
/**
|
410 |
+
* Checks if the tag is allowed to be lazy loaded.
|
411 |
+
*
|
412 |
+
* @param string $image The image (img) tag.
|
413 |
+
* @return bool True if the tag is allowed, false otherwise.
|
414 |
+
*/
|
415 |
+
function validate_image_tag( $image ) {
|
416 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
417 |
+
if (
|
418 |
+
strpos( $image, 'base64,R0lGOD' ) ||
|
419 |
+
strpos( $image, 'lazy-load/images/1x1' ) ||
|
420 |
+
strpos( $image, '/assets/images/' )
|
421 |
+
) {
|
422 |
+
$this->debug_message( 'lazy load placeholder detected' );
|
423 |
+
return false;
|
424 |
+
}
|
425 |
+
|
426 |
+
// Skip inline data URIs.
|
427 |
+
$image_src = $this->get_attribute( $image, 'src' );
|
428 |
+
if ( false !== strpos( $image_src, 'data:image' ) ) {
|
429 |
+
return false;
|
430 |
+
}
|
431 |
+
if ( false !== strpos( $image, 'data:image' ) && false !== strpos( $image, 'lazyload' ) ) {
|
432 |
+
return false;
|
433 |
+
}
|
434 |
+
// Ignore 0-size Pinterest schema images.
|
435 |
+
if ( strpos( $image, 'data-pin-description=' ) && strpos( $image, 'width="0" height="0"' ) ) {
|
436 |
+
return false;
|
437 |
+
}
|
438 |
+
|
439 |
+
// Ignore native lazy loading images.
|
440 |
+
$loading_attr = $this->get_attribute( $image, 'loading' );
|
441 |
+
if ( $loading_attr && in_array( trim( $loading_attr ), array( 'auto', 'eager', 'lazy' ), true ) ) {
|
442 |
+
return false;
|
443 |
+
}
|
444 |
+
|
445 |
+
$exclusions = apply_filters(
|
446 |
+
'eio_lazy_exclusions',
|
447 |
+
array(
|
448 |
+
'class="ls-bg',
|
449 |
+
'class="ls-l',
|
450 |
+
'class="rev-slidebg',
|
451 |
+
'data-bgposition=',
|
452 |
+
'data-envira-src=',
|
453 |
+
'data-lazy=',
|
454 |
+
'data-lazy-original=',
|
455 |
+
'data-lazy-src=',
|
456 |
+
'data-lazy-srcset=',
|
457 |
+
'data-lazyload=',
|
458 |
+
'data-lazysrc=',
|
459 |
+
'data-no-lazy=',
|
460 |
+
'data-src=',
|
461 |
+
'data-srcset=',
|
462 |
+
'ewww_webp_lazy_load',
|
463 |
+
'fullurl=',
|
464 |
+
'gazette-featured-content-thumbnail',
|
465 |
+
'lazy-slider-img=',
|
466 |
+
'mgl-lazy',
|
467 |
+
'skip-lazy',
|
468 |
+
'timthumb.php?',
|
469 |
+
'wpcf7_captcha/',
|
470 |
+
),
|
471 |
+
$image
|
472 |
+
);
|
473 |
+
foreach ( $exclusions as $exclusion ) {
|
474 |
+
if ( false !== strpos( $image, $exclusion ) ) {
|
475 |
+
return false;
|
476 |
+
}
|
477 |
+
}
|
478 |
+
return true;
|
479 |
+
}
|
480 |
+
|
481 |
+
/**
|
482 |
+
* Checks if a tag with a background image is allowed to be lazy loaded.
|
483 |
+
*
|
484 |
+
* @param string $tag The tag.
|
485 |
+
* @return bool True if the tag is allowed, false otherwise.
|
486 |
+
*/
|
487 |
+
function validate_bgimage_tag( $tag ) {
|
488 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
489 |
+
$exclusions = apply_filters(
|
490 |
+
'eio_lazy_bg_image_exclusions',
|
491 |
+
array(
|
492 |
+
'data-no-lazy=',
|
493 |
+
'header-gallery-wrapper ',
|
494 |
+
'lazyload',
|
495 |
+
'skip-lazy',
|
496 |
+
'avia-bg-style-fixed',
|
497 |
+
),
|
498 |
+
$tag
|
499 |
+
);
|
500 |
+
foreach ( $exclusions as $exclusion ) {
|
501 |
+
if ( false !== strpos( $tag, $exclusion ) ) {
|
502 |
+
return false;
|
503 |
+
}
|
504 |
+
}
|
505 |
+
return true;
|
506 |
+
}
|
507 |
+
|
508 |
+
/**
|
509 |
+
* Build a PNG inline image placeholder.
|
510 |
+
*
|
511 |
+
* @param int $width The width of the placeholder image.
|
512 |
+
* @param int $height The height of the placeholder image.
|
513 |
+
* @return string The PNG placeholder link.
|
514 |
+
*/
|
515 |
+
function create_piip( $width = 1, $height = 1 ) {
|
516 |
+
$width = (int) $width;
|
517 |
+
$height = (int) $height;
|
518 |
+
if ( ( 1 === $width && 1 === $height ) || ! $width || ! $height ) {
|
519 |
+
return $this->placeholder_src;
|
520 |
+
}
|
521 |
+
|
522 |
+
if ( $width > 1920 ) {
|
523 |
+
$ratio = $height / $width;
|
524 |
+
$width = 1920;
|
525 |
+
$height = round( 1920 * $ratio );
|
526 |
+
}
|
527 |
+
$height = min( $height, 1920 );
|
528 |
+
|
529 |
+
$piip_path = $this->piip_folder . 'placeholder-' . $width . 'x' . $height . '.png';
|
530 |
+
if ( $this->parsing_exactdn ) {
|
531 |
+
global $exactdn;
|
532 |
+
return $exactdn->generate_url( $this->content_url . 'lazy/placeholder-' . $width . 'x' . $height . '.png' );
|
533 |
+
} elseif ( ! is_file( $piip_path ) ) {
|
534 |
+
$img = imagecreatetruecolor( $width, $height );
|
535 |
+
$color = imagecolorallocatealpha( $img, 0, 0, 0, 127 );
|
536 |
+
imagefill( $img, 0, 0, $color );
|
537 |
+
imagesavealpha( $img, true );
|
538 |
+
imagecolortransparent( $img, imagecolorat( $img, 0, 0 ) );
|
539 |
+
imagetruecolortopalette( $img, false, 1 );
|
540 |
+
imagepng( $img, $piip_path, 9 );
|
541 |
+
}
|
542 |
+
if ( is_file( $piip_path ) ) {
|
543 |
+
return $this->content_url . 'lazy/placeholder-' . $width . 'x' . $height . '.png';
|
544 |
+
}
|
545 |
+
return $this->placeholder_src;
|
546 |
+
}
|
547 |
+
/**
|
548 |
+
* Allow lazy loading of images for some admin-ajax requests.
|
549 |
+
*
|
550 |
+
* @param bool $allow Will normally be false, unless already modified by another function.
|
551 |
+
* @return bool True if it's an allowable admin-ajax request, false for all other admin requests.
|
552 |
+
*/
|
553 |
+
function allow_admin_lazyload( $allow ) {
|
554 |
+
if ( ! wp_doing_ajax() ) {
|
555 |
+
return $allow;
|
556 |
+
}
|
557 |
+
if ( ! empty( $_POST['action'] ) && 'vc_get_vc_grid_data' === $_POST['action'] ) {
|
558 |
+
$this->debug_message( 'allowing lazy on vc grid' );
|
559 |
+
return true;
|
560 |
+
}
|
561 |
+
if ( ! empty( $_POST['action'] ) && 'Essential_Grid_Front_request_ajax' === $_POST['action'] ) {
|
562 |
+
/* return true; */
|
563 |
+
}
|
564 |
+
return $allow;
|
565 |
+
}
|
566 |
+
|
567 |
+
/**
|
568 |
+
* Check if LQIP should be used, but allow filters to alter the option.
|
569 |
+
*
|
570 |
+
* @param bool $use_lqip Whether LL should use low-quality image placeholders.
|
571 |
+
* @return bool True to use LQIP, false to skip them.
|
572 |
+
*/
|
573 |
+
function maybe_lqip( $use_lqip ) {
|
574 |
+
if ( defined( 'EWWW_IMAGE_OPTIMIZER_USE_LQIP' ) && ! EWWW_IMAGE_OPTIMIZER_USE_LQIP ) {
|
575 |
+
return false;
|
576 |
+
}
|
577 |
+
if ( defined( 'EASYIO_USE_LQIP' ) && ! EASYIO_USE_LQIP ) {
|
578 |
+
return false;
|
579 |
+
}
|
580 |
+
return $use_lqip;
|
581 |
+
}
|
582 |
+
|
583 |
+
/**
|
584 |
+
* Check if PIIP should be used, but allow filters to alter the option.
|
585 |
+
*
|
586 |
+
* @param bool $use_piip Whether LL should use PNG inline image placeholders.
|
587 |
+
* @return bool True to use PIIP, false to skip them.
|
588 |
+
*/
|
589 |
+
function maybe_piip( $use_piip ) {
|
590 |
+
if ( defined( 'EWWW_IMAGE_OPTIMIZER_USE_PIIP' ) && ! EWWW_IMAGE_OPTIMIZER_USE_PIIP ) {
|
591 |
+
return false;
|
592 |
+
}
|
593 |
+
if ( defined( 'EASYIO_USE_PIIP' ) && ! EASYIO_USE_PIIP ) {
|
594 |
+
return false;
|
595 |
+
}
|
596 |
+
return $use_piip;
|
597 |
+
}
|
598 |
+
|
599 |
+
/**
|
600 |
+
* Check if SIIP should be used, but allow filters to alter the option.
|
601 |
+
*
|
602 |
+
* @param bool $use_siip Whether LL should use SVG inline image placeholders.
|
603 |
+
* @return bool True to use SIIP, false to skip them.
|
604 |
+
*/
|
605 |
+
function maybe_siip( $use_siip ) {
|
606 |
+
if ( defined( 'EWWW_IMAGE_OPTIMIZER_USE_SIIP' ) && ! EWWW_IMAGE_OPTIMIZER_USE_SIIP ) {
|
607 |
+
return false;
|
608 |
+
}
|
609 |
+
if ( defined( 'EASYIO_USE_SIIP' ) && ! EASYIO_USE_SIIP ) {
|
610 |
+
return false;
|
611 |
+
}
|
612 |
+
return $use_siip;
|
613 |
+
}
|
614 |
+
|
615 |
+
/**
|
616 |
+
* Adds a small CSS block to hide lazyload elements for no-JS browsers.
|
617 |
+
*/
|
618 |
+
function no_js_css() {
|
619 |
+
echo '<noscript><style>.lazyload[data-src]{display:none !important;}</style></noscript>';
|
620 |
+
}
|
621 |
+
|
622 |
+
/**
|
623 |
+
* Load full lazysizes script when SCRIPT_DEBUG is enabled.
|
624 |
+
*/
|
625 |
+
function debug_script() {
|
626 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
627 |
+
if ( $this->is_amp() ) {
|
628 |
+
return;
|
629 |
+
}
|
630 |
+
$plugin_file = constant( strtoupper( $this->prefix ) . 'PLUGIN_FILE' );
|
631 |
+
wp_enqueue_script( 'eio-lazy-load-pre', plugins_url( '/includes/lazysizes-pre.js', $plugin_file ), array(), $this->version );
|
632 |
+
wp_enqueue_script( 'eio-lazy-load', plugins_url( '/includes/lazysizes.js', $plugin_file ), array(), $this->version );
|
633 |
+
wp_enqueue_script( 'eio-lazy-load-post', plugins_url( '/includes/lazysizes-post.js', $plugin_file ), array(), $this->version );
|
634 |
+
wp_enqueue_script( 'eio-lazy-load-uvh', plugins_url( '/includes/ls.unveilhooks.js', $plugin_file ), array(), $this->version );
|
635 |
+
if ( defined( strtoupper( $this->prefix ) . 'LAZY_PRINT' ) && constant( strtoupper( $this->prefix ) . 'LAZY_PRINT' ) ) {
|
636 |
+
wp_enqueue_script( 'eio-lazy-load-print', plugins_url( '/includes/ls.print.js', $plugin_file ), array(), $this->version );
|
637 |
+
}
|
638 |
+
wp_localize_script(
|
639 |
+
'eio-lazy-load',
|
640 |
+
'eio_lazy_vars',
|
641 |
+
array(
|
642 |
+
'exactdn_domain' => ( $this->parsing_exactdn ? $this->exactdn_domain : '' ),
|
643 |
+
)
|
644 |
+
);
|
645 |
+
}
|
646 |
+
|
647 |
+
/**
|
648 |
+
* Load minified lazysizes script.
|
649 |
+
*/
|
650 |
+
function min_script() {
|
651 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
652 |
+
if ( $this->is_amp() ) {
|
653 |
+
return;
|
654 |
+
}
|
655 |
+
$plugin_file = constant( strtoupper( $this->prefix ) . 'PLUGIN_FILE' );
|
656 |
+
wp_enqueue_script( 'eio-lazy-load', plugins_url( '/includes/lazysizes.min.js', $plugin_file ), array(), $this->version );
|
657 |
+
if ( defined( strtoupper( $this->prefix ) . 'LAZY_PRINT' ) && constant( strtoupper( $this->prefix ) . 'LAZY_PRINT' ) ) {
|
658 |
+
wp_enqueue_script( 'eio-lazy-load-print', plugins_url( '/includes/ls.print.min.js', $plugin_file ), array(), $this->version );
|
659 |
+
}
|
660 |
+
wp_localize_script(
|
661 |
+
'eio-lazy-load',
|
662 |
+
'eio_lazy_vars',
|
663 |
+
array(
|
664 |
+
'exactdn_domain' => ( $this->parsing_exactdn ? $this->exactdn_domain : '' ),
|
665 |
+
)
|
666 |
+
);
|
667 |
+
}
|
668 |
+
}
|
669 |
+
|
670 |
+
global $eio_lazy_load;
|
671 |
+
$eio_lazy_load = new EIO_Lazy_Load();
|
672 |
+
}
|
classes/class-eio-page-parser.php
ADDED
@@ -0,0 +1,321 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Implements basic page parsing functions.
|
4 |
+
*
|
5 |
+
* @link https://ewww.io
|
6 |
+
* @package EIO
|
7 |
+
*/
|
8 |
+
|
9 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
10 |
+
exit;
|
11 |
+
}
|
12 |
+
|
13 |
+
if ( ! class_exists( 'EIO_Page_Parser' ) ) {
|
14 |
+
/**
|
15 |
+
* HTML element and attribute parsing, replacing, etc.
|
16 |
+
*/
|
17 |
+
class EIO_Page_Parser extends EIO_Base {
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Allowed image extensions.
|
21 |
+
*
|
22 |
+
* @access protected
|
23 |
+
* @var array $extensions
|
24 |
+
*/
|
25 |
+
protected $extensions = array(
|
26 |
+
'gif',
|
27 |
+
'jpg',
|
28 |
+
'jpeg',
|
29 |
+
'jpe',
|
30 |
+
'png',
|
31 |
+
);
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Match all images and any relevant <a> tags in a block of HTML.
|
35 |
+
*
|
36 |
+
* The hyperlinks param implies that the src attribute is required, but not the other way around.
|
37 |
+
*
|
38 |
+
* @param string $content Some HTML.
|
39 |
+
* @param bool $hyperlinks Default true. Should we include encasing hyperlinks in our search.
|
40 |
+
* @param bool $src_required Default true. Should we look only for images with src attributes.
|
41 |
+
* @return array An array of $images matches, where $images[0] is
|
42 |
+
* an array of full matches, and the link_url, img_tag,
|
43 |
+
* and img_url keys are arrays of those matches.
|
44 |
+
*/
|
45 |
+
function get_images_from_html( $content, $hyperlinks = true, $src_required = true ) {
|
46 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
47 |
+
$images = array();
|
48 |
+
$unquoted_images = array();
|
49 |
+
|
50 |
+
$unquoted_pattern = '';
|
51 |
+
$search_pattern = '#(?P<img_tag><img\s[^>]*?>)#is';
|
52 |
+
if ( $hyperlinks ) {
|
53 |
+
$this->debug_message( 'using figure+hyperlink(a) patterns with src required' );
|
54 |
+
$search_pattern = '#(?:<figure[^>]*?\s+?class\s*=\s*["\'](?P<figure_class>[\w\s-]+?)["\'][^>]*?>\s*)?(?:<a[^>]*?\s+?href\s*=\s*["\'](?P<link_url>[^\s]+?)["\'][^>]*?>\s*)?(?P<img_tag><img[^>]*?\s+?src\s*=\s*("|\')(?P<img_url>(?!\4).+?)\4[^>]*?>){1}(?:\s*</a>)?#is';
|
55 |
+
$unquoted_pattern = '#(?:<figure[^>]*?\s+?class\s*=\s*(?P<figure_class>[\w-]+)[^>]*?>\s*)?(?:<a[^>]*?\s+?href\s*=\s*(?P<link_url>[^"\'][^\s>]+)[^>]*?>\s*)?(?P<img_tag><img[^>]*?\s+?src\s*=\s*(?P<img_url>[^"\'][^\s>]+)[^>]*?>){1}(?:\s*</a>)?#is';
|
56 |
+
} elseif ( $src_required ) {
|
57 |
+
$this->debug_message( 'using plain img pattern, src still required' );
|
58 |
+
$search_pattern = '#(?P<img_tag><img[^>]*?\s+?src\s*=\s*("|\')(?P<img_url>(?!\2).+?)\2[^>]*?>)#is';
|
59 |
+
$unquoted_pattern = '#(?P<img_tag><img[^>]*?\s+?src\s*=\s*(?P<img_url>[^"\'][^\s>]+)[^>]*?>)#is';
|
60 |
+
}
|
61 |
+
if ( preg_match_all( $search_pattern, $content, $images ) ) {
|
62 |
+
$this->debug_message( 'found ' . count( $images[0] ) . ' image elements with quoted pattern' );
|
63 |
+
foreach ( $images as $key => $unused ) {
|
64 |
+
// Simplify the output as much as possible.
|
65 |
+
if ( is_numeric( $key ) && $key > 0 ) {
|
66 |
+
unset( $images[ $key ] );
|
67 |
+
}
|
68 |
+
}
|
69 |
+
/* $this->debug_message( print_r( $images, true ) ); */
|
70 |
+
}
|
71 |
+
$images = array_filter( $images );
|
72 |
+
if ( $unquoted_pattern && preg_match_all( $unquoted_pattern, $content, $unquoted_images ) ) {
|
73 |
+
$this->debug_message( 'found ' . count( $unquoted_images[0] ) . ' image elements with unquoted pattern' );
|
74 |
+
foreach ( $unquoted_images as $key => $unused ) {
|
75 |
+
// Simplify the output as much as possible.
|
76 |
+
if ( is_numeric( $key ) && $key > 0 ) {
|
77 |
+
unset( $unquoted_images[ $key ] );
|
78 |
+
}
|
79 |
+
}
|
80 |
+
/* $this->debug_message( print_r( $unquoted_images, true ) ); */
|
81 |
+
}
|
82 |
+
$unquoted_images = array_filter( $unquoted_images );
|
83 |
+
if ( ! empty( $images ) && ! empty( $unquoted_images ) ) {
|
84 |
+
$this->debug_message( 'both patterns found results, merging' );
|
85 |
+
/* $this->debug_message( print_r( $images, true ) ); */
|
86 |
+
$images = array_merge_recursive( $images, $unquoted_images );
|
87 |
+
/* $this->debug_message( print_r( $images, true ) ); */
|
88 |
+
if ( ! empty( $images[0] ) && ! empty( $images[1] ) ) {
|
89 |
+
$images[0] = array_merge( $images[0], $images[1] );
|
90 |
+
unset( $images[1] );
|
91 |
+
}
|
92 |
+
} elseif ( empty( $images ) && ! empty( $unquoted_images ) ) {
|
93 |
+
$this->debug_message( 'unquoted results only, subbing in' );
|
94 |
+
$images = $unquoted_images;
|
95 |
+
}
|
96 |
+
/* $this->debug_message( print_r( $images, true ) ); */
|
97 |
+
return $images;
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Match all images wrapped in <noscript> tags in a block of HTML.
|
102 |
+
*
|
103 |
+
* @param string $content Some HTML.
|
104 |
+
* @return array An array of $images matches, where $images[0] is
|
105 |
+
* an array of full matches, and the noscript_tag, img_tag,
|
106 |
+
* and img_url keys are arrays of those matches.
|
107 |
+
*/
|
108 |
+
function get_noscript_images_from_html( $content ) {
|
109 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
110 |
+
$images = array();
|
111 |
+
|
112 |
+
if ( preg_match_all( '#(?P<noscript_tag><noscript[^>]*?>\s*)(?P<img_tag><img[^>]*?\s+?src\s*=\s*["\'](?P<img_url>[^\s]+?)["\'][^>]*?>){1}(?:\s*</noscript>)?#is', $content, $images ) ) {
|
113 |
+
foreach ( $images as $key => $unused ) {
|
114 |
+
// Simplify the output as much as possible, mostly for confirming test results.
|
115 |
+
if ( is_numeric( $key ) && $key > 0 ) {
|
116 |
+
unset( $images[ $key ] );
|
117 |
+
}
|
118 |
+
}
|
119 |
+
return $images;
|
120 |
+
}
|
121 |
+
return array();
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Match all sources wrapped in <picture> tags in a block of HTML.
|
126 |
+
*
|
127 |
+
* @param string $content Some HTML.
|
128 |
+
* @return array An array of $pictures matches, containing full elements with ending tags.
|
129 |
+
*/
|
130 |
+
function get_picture_tags_from_html( $content ) {
|
131 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
132 |
+
$pictures = array();
|
133 |
+
if ( preg_match_all( '#(?:<picture[^>]*?>\s*)(?:<source[^>]*?>)+(?:.*?</picture>)?#is', $content, $pictures ) ) {
|
134 |
+
return $pictures[0];
|
135 |
+
}
|
136 |
+
return array();
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Match all elements by tag name in a block of HTML. Does not retrieve contents or closing tags.
|
141 |
+
*
|
142 |
+
* @param string $content Some HTML.
|
143 |
+
* @param string $tag_name The name of the elements to retrieve.
|
144 |
+
* @return array An array of $elements.
|
145 |
+
*/
|
146 |
+
function get_elements_from_html( $content, $tag_name ) {
|
147 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
148 |
+
if ( ! ctype_alpha( $tag_name ) ) {
|
149 |
+
return array();
|
150 |
+
}
|
151 |
+
if ( preg_match_all( '#<' . $tag_name . '\s[^>]+?>#is', $content, $elements ) ) {
|
152 |
+
return $elements[0];
|
153 |
+
}
|
154 |
+
return array();
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Try to determine height and width from strings WP appends to resized image filenames.
|
159 |
+
*
|
160 |
+
* @param string $src The image URL.
|
161 |
+
* @return array An array consisting of width and height.
|
162 |
+
*/
|
163 |
+
function get_dimensions_from_filename( $src ) {
|
164 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
165 |
+
$width_height_string = array();
|
166 |
+
$this->debug_message( "looking for dimensions in $src" );
|
167 |
+
if ( preg_match( '#-(\d+)x(\d+)(@2x)?\.(?:' . implode( '|', $this->extensions ) . '){1}(?:\?.+)?$#i', $src, $width_height_string ) ) {
|
168 |
+
$width = (int) $width_height_string[1];
|
169 |
+
$height = (int) $width_height_string[2];
|
170 |
+
|
171 |
+
if ( strpos( $src, '@2x' ) ) {
|
172 |
+
$width = 2 * $width;
|
173 |
+
$height = 2 * $height;
|
174 |
+
}
|
175 |
+
if ( $width && $height ) {
|
176 |
+
$this->debug_message( "found w$width h$height" );
|
177 |
+
return array( $width, $height );
|
178 |
+
}
|
179 |
+
}
|
180 |
+
return array( false, false );
|
181 |
+
}
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Get the width from an image element.
|
185 |
+
*
|
186 |
+
* @param string $img The full image element.
|
187 |
+
* @return string The width found or an empty string.
|
188 |
+
*/
|
189 |
+
public function get_img_width( $img ) {
|
190 |
+
$width = $this->get_attribute( $img, 'width' );
|
191 |
+
// Then check for an inline max-width directive.
|
192 |
+
$style = $this->get_attribute( $img, 'style' );
|
193 |
+
if ( $style && preg_match( '#max-width:\s?(\d+)px#', $style, $max_width_string ) ) {
|
194 |
+
if ( $max_width_string[1] && ( ! $width || $max_width_string[1] < $width ) ) {
|
195 |
+
$width = $max_width_string[1];
|
196 |
+
}
|
197 |
+
}
|
198 |
+
return $width;
|
199 |
+
}
|
200 |
+
|
201 |
+
/**
|
202 |
+
* Get an attribute from an HTML element.
|
203 |
+
*
|
204 |
+
* @param string $element The HTML element to parse.
|
205 |
+
* @param string $name The name of the attribute to search for.
|
206 |
+
* @return string The value of the attribute, or an empty string if not found.
|
207 |
+
*/
|
208 |
+
function get_attribute( $element, $name ) {
|
209 |
+
// Don't forget, back references cannot be used in character classes.
|
210 |
+
if ( preg_match( '#\s' . $name . '\s*=\s*("|\')((?!\1).+?)\1#is', $element, $attr_matches ) ) {
|
211 |
+
if ( ! empty( $attr_matches[2] ) ) {
|
212 |
+
return $attr_matches[2];
|
213 |
+
}
|
214 |
+
}
|
215 |
+
// If there were not any matches with quotes, look for unquoted attributes, no spaces or quotes allowed.
|
216 |
+
if ( preg_match( '#\s' . $name . '\s*=\s*([^"\'][^\s>]+)#is', $element, $attr_matches ) ) {
|
217 |
+
if ( ! empty( $attr_matches[1] ) ) {
|
218 |
+
return $attr_matches[1];
|
219 |
+
}
|
220 |
+
}
|
221 |
+
return '';
|
222 |
+
}
|
223 |
+
|
224 |
+
/**
|
225 |
+
* Get a CSS background-image URL.
|
226 |
+
*
|
227 |
+
* @param string $attribute An element's style attribute. Do not pass a full HTML element.
|
228 |
+
* @return string The URL from the background/background-image property.
|
229 |
+
*/
|
230 |
+
function get_background_image_url( $attribute ) {
|
231 |
+
if ( ( false !== strpos( $attribute, 'background:' ) || false !== strpos( $attribute, 'background-image:' ) ) && false !== strpos( $attribute, 'url(' ) ) {
|
232 |
+
if ( preg_match( '#url\(([^)]+)\)#', $attribute, $prop_match ) ) {
|
233 |
+
return trim( html_entity_decode( $prop_match[1], ENT_QUOTES | ENT_HTML401 ), "'\"\t\n\r " );
|
234 |
+
}
|
235 |
+
}
|
236 |
+
return '';
|
237 |
+
}
|
238 |
+
|
239 |
+
/**
|
240 |
+
* Set an attribute on an HTML element.
|
241 |
+
*
|
242 |
+
* @param string $element The HTML element to modify. Passed by reference.
|
243 |
+
* @param string $name The name of the attribute to set.
|
244 |
+
* @param string $value The value of the attribute to set.
|
245 |
+
* @param bool $replace Default false. True to replace, false to append.
|
246 |
+
*/
|
247 |
+
function set_attribute( &$element, $name, $value, $replace = false ) {
|
248 |
+
if ( 'class' === $name ) {
|
249 |
+
$element = preg_replace( "#\s$name\s+[^=]#", ' ', $element );
|
250 |
+
}
|
251 |
+
$element = preg_replace( "#\s$name=\"\"#", ' ', $element );
|
252 |
+
$value = trim( $value );
|
253 |
+
if ( $replace ) {
|
254 |
+
// Don't forget, back references cannot be used in character classes.
|
255 |
+
$new_element = preg_replace( '#\s' . $name . '\s*=\s*("|\')(?!\1).*?\1#is', " $name=$1$value$1", $element );
|
256 |
+
if ( strpos( $new_element, "$name=" ) ) {
|
257 |
+
$element = $new_element;
|
258 |
+
return;
|
259 |
+
}
|
260 |
+
$element = preg_replace( '#\s' . $name . '\s*=\s*[^"\'][^\s>]+#is', ' ', $element );
|
261 |
+
}
|
262 |
+
$closing = ' />';
|
263 |
+
if ( false === strpos( $element, '/>' ) ) {
|
264 |
+
$closing = '>';
|
265 |
+
}
|
266 |
+
if ( false === strpos( $value, '"' ) ) {
|
267 |
+
$element = rtrim( $element, $closing ) . " $name=\"$value\"$closing";
|
268 |
+
return;
|
269 |
+
}
|
270 |
+
$element = rtrim( $element, $closing ) . " $name='$value'$closing";
|
271 |
+
}
|
272 |
+
|
273 |
+
/**
|
274 |
+
* Remove an attribute from an HTML element.
|
275 |
+
*
|
276 |
+
* @param string $element The HTML element to modify. Passed by reference.
|
277 |
+
* @param string $name The name of the attribute to remove.
|
278 |
+
*/
|
279 |
+
function remove_attribute( &$element, $name ) {
|
280 |
+
// Don't forget, back references cannot be used in character classes.
|
281 |
+
$element = preg_replace( '#\s' . $name . '\s*=\s*("|\')(?!\1).+?\1#is', ' ', $element );
|
282 |
+
$element = preg_replace( '#\s' . $name . '\s*=\s*[^"\'][^\s>]+#is', ' ', $element );
|
283 |
+
}
|
284 |
+
|
285 |
+
/**
|
286 |
+
* Remove the background image URL from a style attribute.
|
287 |
+
*
|
288 |
+
* @param string $attribute The element's style attribute to modify.
|
289 |
+
* @return string The style attribute with any image url removed.
|
290 |
+
*/
|
291 |
+
function remove_background_image( $attribute ) {
|
292 |
+
if ( false !== strpos( $attribute, 'background:' ) && false !== strpos( $attribute, 'url(' ) ) {
|
293 |
+
$attribute = preg_replace( '#\s?url\([^)]+\)#', '', $attribute );
|
294 |
+
}
|
295 |
+
if ( false !== strpos( $attribute, 'background-image:' ) && false !== strpos( $attribute, 'url(' ) ) {
|
296 |
+
$attribute = preg_replace( '#background-image:\s*url\([^)]+\);?#', '', $attribute );
|
297 |
+
}
|
298 |
+
return $attribute;
|
299 |
+
}
|
300 |
+
|
301 |
+
/**
|
302 |
+
* A wrapper for PHP's parse_url, prepending assumed scheme for network path
|
303 |
+
* URLs. PHP versions 5.4.6 and earlier do not correctly parse without scheme.
|
304 |
+
*
|
305 |
+
* @param string $url The URL to parse.
|
306 |
+
* @param integer $component Retrieve specific URL component.
|
307 |
+
* @return mixed Result of parse_url.
|
308 |
+
*/
|
309 |
+
function parse_url( $url, $component = -1 ) {
|
310 |
+
if ( 0 === strpos( $url, '//' ) ) {
|
311 |
+
$url = ( is_ssl() ? 'https:' : 'http:' ) . $url;
|
312 |
+
}
|
313 |
+
if ( false === strpos( $url, 'http' ) && '/' !== substr( $url, 0, 1 ) ) {
|
314 |
+
$url = ( is_ssl() ? 'https://' : 'http://' ) . $url;
|
315 |
+
}
|
316 |
+
// Because encoded ampersands in the filename break things.
|
317 |
+
$url = str_replace( '&', '&', $url );
|
318 |
+
return parse_url( $url, $component );
|
319 |
+
}
|
320 |
+
}
|
321 |
+
}
|
classes/class-ewww-flag.php
CHANGED
@@ -170,6 +170,38 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
|
|
170 |
echo '</div></div>';
|
171 |
}
|
172 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
173 |
/**
|
174 |
* Prepares the bulk operation and includes the necessary javascript files.
|
175 |
*
|
@@ -181,15 +213,15 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
|
|
181 |
function ewww_flag_bulk_script( $hook ) {
|
182 |
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
183 |
// Make sure we are being hooked from a valid location.
|
184 |
-
if (
|
185 |
return;
|
186 |
}
|
187 |
// If there is no requested bulk action, do nothing.
|
188 |
-
if (
|
189 |
return;
|
190 |
}
|
191 |
// If there is no media to optimize, do nothing.
|
192 |
-
if (
|
193 |
return;
|
194 |
}
|
195 |
$ids = null;
|
@@ -234,7 +266,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
|
|
234 |
} elseif ( ! empty( $resume ) ) {
|
235 |
// If there is an operation to resume, get those IDs from the db.
|
236 |
$ids = get_option( 'ewww_image_optimizer_bulk_flag_attachments' );
|
237 |
-
} elseif (
|
238 |
// Otherwise, if we are on the main bulk optimize page, just get all the IDs available.
|
239 |
global $wpdb;
|
240 |
$ids = $wpdb->get_col( "SELECT pid FROM $wpdb->flagpictures ORDER BY sortorder ASC" );
|
@@ -636,7 +668,7 @@ if ( ! class_exists( 'EWWW_Flag' ) ) {
|
|
636 |
*/
|
637 |
function ewww_flag_manual_actions_script( $hook ) {
|
638 |
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
639 |
-
if (
|
640 |
return;
|
641 |
}
|
642 |
if ( ! current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
|
170 |
echo '</div></div>';
|
171 |
}
|
172 |
|
173 |
+
/**
|
174 |
+
* Checks the hook suffix to see if this is the individual gallery management page.
|
175 |
+
*
|
176 |
+
* @param string $hook The hook suffix of the page.
|
177 |
+
* @returns boolean True for the gallery page, false anywhere else.
|
178 |
+
*/
|
179 |
+
function is_gallery_page( $hook ) {
|
180 |
+
if ( 'flagallery_page_flag-manage-gallery' === $hook ) {
|
181 |
+
return true;
|
182 |
+
}
|
183 |
+
if ( false !== strpos( $hook, 'page_flag-manage-gallery' ) ) {
|
184 |
+
return true;
|
185 |
+
}
|
186 |
+
return false;
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
* Checks the hook suffix to see if this is the bulk optimize page.
|
191 |
+
*
|
192 |
+
* @param string $hook The hook suffix of the page.
|
193 |
+
* @returns boolean True for the bulk page, false anywhere else.
|
194 |
+
*/
|
195 |
+
function is_bulk_page( $hook ) {
|
196 |
+
if ( 'flagallery_page_flag-bulk-optimize' === $hook ) {
|
197 |
+
return true;
|
198 |
+
}
|
199 |
+
if ( false !== strpos( $hook, 'page_flag-bulk-optimize' ) ) {
|
200 |
+
return true;
|
201 |
+
}
|
202 |
+
return false;
|
203 |
+
}
|
204 |
+
|
205 |
/**
|
206 |
* Prepares the bulk operation and includes the necessary javascript files.
|
207 |
*
|
213 |
function ewww_flag_bulk_script( $hook ) {
|
214 |
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
215 |
// Make sure we are being hooked from a valid location.
|
216 |
+
if ( ! $this->is_bulk_page( $hook ) && ! $this->is_gallery_page( $hook ) ) {
|
217 |
return;
|
218 |
}
|
219 |
// If there is no requested bulk action, do nothing.
|
220 |
+
if ( $this->is_gallery_page( $hook ) && ( empty( $_REQUEST['bulkaction'] ) || 0 === strpos( $_REQUEST['bulkaction'], 'bulk_optimize' ) ) ) {
|
221 |
return;
|
222 |
}
|
223 |
// If there is no media to optimize, do nothing.
|
224 |
+
if ( $this->is_gallery_page( $hook ) && ( empty( $_REQUEST['doaction'] ) || ! is_array( $_REQUEST['doaction'] ) ) ) {
|
225 |
return;
|
226 |
}
|
227 |
$ids = null;
|
266 |
} elseif ( ! empty( $resume ) ) {
|
267 |
// If there is an operation to resume, get those IDs from the db.
|
268 |
$ids = get_option( 'ewww_image_optimizer_bulk_flag_attachments' );
|
269 |
+
} elseif ( $this->is_bulk_page( $hook ) ) {
|
270 |
// Otherwise, if we are on the main bulk optimize page, just get all the IDs available.
|
271 |
global $wpdb;
|
272 |
$ids = $wpdb->get_col( "SELECT pid FROM $wpdb->flagpictures ORDER BY sortorder ASC" );
|
668 |
*/
|
669 |
function ewww_flag_manual_actions_script( $hook ) {
|
670 |
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
671 |
+
if ( ! $this->is_gallery_page( $hook ) ) {
|
672 |
return;
|
673 |
}
|
674 |
if ( ! current_user_can( apply_filters( 'ewww_image_optimizer_manual_permissions', '' ) ) ) {
|
classes/class-ewww-nextgen.php
CHANGED
@@ -588,7 +588,7 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
|
|
588 |
/**
|
589 |
* Output the html for the bulk optimize page.
|
590 |
*
|
591 |
-
* @global string $
|
592 |
*/
|
593 |
function ewww_ngg_bulk_preview() {
|
594 |
if ( ! empty( $_REQUEST['doaction'] ) ) {
|
@@ -679,8 +679,8 @@ if ( ! class_exists( 'EWWW_Nextgen' ) ) {
|
|
679 |
}
|
680 |
echo '</div></div>';
|
681 |
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
|
682 |
-
global $
|
683 |
-
echo '<p><strong>' . esc_html__( 'Debugging Information', 'ewww-image-optimizer' ) . ':</strong></p><div style="border:1px solid #e5e5e5;background:#fff;overflow:auto;height:300px;width:800px;">' . $
|
684 |
}
|
685 |
return;
|
686 |
}
|
588 |
/**
|
589 |
* Output the html for the bulk optimize page.
|
590 |
*
|
591 |
+
* @global string $eio_debug In-memory debug log.
|
592 |
*/
|
593 |
function ewww_ngg_bulk_preview() {
|
594 |
if ( ! empty( $_REQUEST['doaction'] ) ) {
|
679 |
}
|
680 |
echo '</div></div>';
|
681 |
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
|
682 |
+
global $eio_debug;
|
683 |
+
echo '<p><strong>' . esc_html__( 'Debugging Information', 'ewww-image-optimizer' ) . ':</strong></p><div style="border:1px solid #e5e5e5;background:#fff;overflow:auto;height:300px;width:800px;">' . $eio_debug . '</div>';
|
684 |
}
|
685 |
return;
|
686 |
}
|
classes/class-ewwwio-hs-beacon.php
DELETED
@@ -1,110 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Help integration functions for embedding the HS Beacon for users that have opted in.
|
4 |
-
*
|
5 |
-
* @package EWWW_Image_Optimizer
|
6 |
-
* @since 3.5.1
|
7 |
-
*/
|
8 |
-
|
9 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
10 |
-
exit;
|
11 |
-
}
|
12 |
-
|
13 |
-
/**
|
14 |
-
* Embed HS Beacon to give users more help when they need it.
|
15 |
-
*
|
16 |
-
* @since 3.5.1
|
17 |
-
*/
|
18 |
-
class EWWWIO_HS_Beacon {
|
19 |
-
|
20 |
-
/**
|
21 |
-
* Get things going
|
22 |
-
*/
|
23 |
-
public function __construct() {
|
24 |
-
add_action( 'admin_action_ewww_opt_into_hs_beacon', array( $this, 'check_for_optin' ) );
|
25 |
-
add_action( 'admin_action_ewww_opt_out_of_hs_beacon', array( $this, 'check_for_optout' ) );
|
26 |
-
}
|
27 |
-
|
28 |
-
/**
|
29 |
-
* Check for a new opt-in on settings save
|
30 |
-
*
|
31 |
-
* @param bool $input The enable_help setting.
|
32 |
-
* @return bool The unaltered setting.
|
33 |
-
*/
|
34 |
-
public function check_for_settings_optin( $input ) {
|
35 |
-
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
36 |
-
if ( isset( $_POST['ewww_image_optimizer_enable_help'] ) && $_POST['ewww_image_optimizer_enable_help'] ) {
|
37 |
-
ewww_image_optimizer_set_option( 'ewww_image_optimizer_tracking_notice', 1 );
|
38 |
-
}
|
39 |
-
return $input;
|
40 |
-
}
|
41 |
-
|
42 |
-
/**
|
43 |
-
* Check for a new opt-in via the admin notice
|
44 |
-
*/
|
45 |
-
public function check_for_optin() {
|
46 |
-
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
47 |
-
ewww_image_optimizer_set_option( 'ewww_image_optimizer_enable_help', 1 );
|
48 |
-
ewww_image_optimizer_set_option( 'ewww_image_optimizer_enable_help_notice', 1 );
|
49 |
-
wp_redirect( remove_query_arg( 'action', wp_get_referer() ) );
|
50 |
-
exit;
|
51 |
-
}
|
52 |
-
|
53 |
-
/**
|
54 |
-
* Check for a new opt-out via the admin notice
|
55 |
-
*/
|
56 |
-
public function check_for_optout() {
|
57 |
-
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
58 |
-
delete_option( 'ewww_image_optimizer_enable_help' );
|
59 |
-
delete_network_option( null, 'ewww_image_optimizer_enable_help' );
|
60 |
-
ewww_image_optimizer_set_option( 'ewww_image_optimizer_enable_help_notice', 1 );
|
61 |
-
wp_redirect( remove_query_arg( 'action', wp_get_referer() ) );
|
62 |
-
exit;
|
63 |
-
}
|
64 |
-
|
65 |
-
/**
|
66 |
-
* Display the admin notice to users that have not opted-in or out
|
67 |
-
*
|
68 |
-
* @access public
|
69 |
-
* @param string $network_class A string that indicates where this is being displayed.
|
70 |
-
* @return void
|
71 |
-
*/
|
72 |
-
public function admin_notice( $network_class = '' ) {
|
73 |
-
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
74 |
-
$hide_notice = ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_help_notice' );
|
75 |
-
if ( 'network-multisite' === $network_class && get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) ) {
|
76 |
-
return;
|
77 |
-
}
|
78 |
-
if ( 'network-singlesite' === $network_class && ! get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) ) {
|
79 |
-
return;
|
80 |
-
}
|
81 |
-
|
82 |
-
if ( $hide_notice ) {
|
83 |
-
return;
|
84 |
-
}
|
85 |
-
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_enable_help' ) ) {
|
86 |
-
return;
|
87 |
-
}
|
88 |
-
|
89 |
-
if ( ! current_user_can( 'manage_options' ) ) {
|
90 |
-
return;
|
91 |
-
}
|
92 |
-
|
93 |
-
if ( ! function_exists( 'is_plugin_active_for_network' ) && is_multisite() ) {
|
94 |
-
// Need to include the plugin library for the is_plugin_active function.
|
95 |
-
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
96 |
-
}
|
97 |
-
if ( is_multisite() && is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) && ! current_user_can( 'manage_network_options' ) ) {
|
98 |
-
return;
|
99 |
-
}
|
100 |
-
$optin_url = 'admin.php?action=ewww_opt_into_hs_beacon';
|
101 |
-
$optout_url = 'admin.php?action=ewww_opt_out_of_hs_beacon';
|
102 |
-
echo '<div class="updated"><p>';
|
103 |
-
esc_html_e( 'Enable the support beacon, which gives you access to documentation and our support team right from your WordPress dashboard. To assist you more efficiently, we may collect the current url, IP address, browser/device information, and debugging information.', 'ewww-image-optimizer' );
|
104 |
-
echo ' <a href="' . esc_url( $optin_url ) . '" class="button-secondary">' . esc_html__( 'Allow', 'ewww-image-optimizer' ) . '</a>';
|
105 |
-
echo ' <a href="' . esc_url( $optout_url ) . '" class="button-secondary">' . esc_html__( 'Do not allow', 'ewww-image-optimizer' ) . '</a>';
|
106 |
-
echo '</p></div>';
|
107 |
-
}
|
108 |
-
|
109 |
-
}
|
110 |
-
$ewwwio_hs_beacon = new EWWWIO_HS_Beacon;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
classes/class-ewwwio-lazy-load.php
DELETED
@@ -1,623 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Implements Lazy Loading using page parsing and JS functionality.
|
4 |
-
*
|
5 |
-
* @link https://ewww.io
|
6 |
-
* @package EWWW_Image_Optimizer
|
7 |
-
*/
|
8 |
-
|
9 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
10 |
-
exit;
|
11 |
-
}
|
12 |
-
|
13 |
-
/**
|
14 |
-
* Enables EWWW IO to filter the page content and replace img elements with Lazy Load markup.
|
15 |
-
*/
|
16 |
-
class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Base64-encoded placeholder image.
|
20 |
-
*
|
21 |
-
* @access protected
|
22 |
-
* @var string $placeholder_src
|
23 |
-
*/
|
24 |
-
protected $placeholder_src = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
|
25 |
-
|
26 |
-
/**
|
27 |
-
* Indicates if we are filtering ExactDN urls.
|
28 |
-
*
|
29 |
-
* @access protected
|
30 |
-
* @var bool $parsing_exactdn
|
31 |
-
*/
|
32 |
-
protected $parsing_exactdn = false;
|
33 |
-
|
34 |
-
/**
|
35 |
-
* The folder to store any PIIPs.
|
36 |
-
*
|
37 |
-
* @access protected
|
38 |
-
* @var string $piip_folder
|
39 |
-
*/
|
40 |
-
protected $piip_folder = WP_CONTENT_DIR . '/ewww/lazy/';
|
41 |
-
|
42 |
-
/**
|
43 |
-
* Whether to allow PIIPs.
|
44 |
-
*
|
45 |
-
* @access public
|
46 |
-
* @var bool $allow_piip
|
47 |
-
*/
|
48 |
-
public $allow_piip = true;
|
49 |
-
|
50 |
-
/**
|
51 |
-
* Register (once) actions and filters for Lazy Load.
|
52 |
-
*/
|
53 |
-
function __construct() {
|
54 |
-
ewwwio_debug_message( 'firing up lazy load' );
|
55 |
-
global $ewwwio_lazy_load;
|
56 |
-
if ( is_object( $ewwwio_lazy_load ) ) {
|
57 |
-
ewwwio_debug_message( 'you are doing it wrong' );
|
58 |
-
return 'you are doing it wrong';
|
59 |
-
}
|
60 |
-
|
61 |
-
add_action( 'wp_head', array( $this, 'no_js_css' ) );
|
62 |
-
add_filter( 'ewww_image_optimizer_filter_page_output', array( $this, 'filter_page_output' ), 15 );
|
63 |
-
|
64 |
-
if ( class_exists( 'ExactDN' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
|
65 |
-
global $exactdn;
|
66 |
-
$this->exactdn_domain = $exactdn->get_exactdn_domain();
|
67 |
-
if ( $this->exactdn_domain ) {
|
68 |
-
$this->parsing_exactdn = true;
|
69 |
-
ewwwio_debug_message( 'parsing an exactdn page' );
|
70 |
-
}
|
71 |
-
}
|
72 |
-
|
73 |
-
if ( ! is_dir( $this->piip_folder ) ) {
|
74 |
-
$this->allow_piip = wp_mkdir_p( $this->piip_folder ) && ewww_image_optimizer_gd_support();
|
75 |
-
} else {
|
76 |
-
$this->allow_piip = is_writable( $this->piip_folder ) && ewww_image_optimizer_gd_support();
|
77 |
-
}
|
78 |
-
|
79 |
-
// Filter early, so that others at the default priority take precendence.
|
80 |
-
add_filter( 'ewww_image_optimizer_use_lqip', array( $this, 'maybe_lqip' ), 9 );
|
81 |
-
add_filter( 'ewww_image_optimizer_use_piip', array( $this, 'maybe_piip' ), 9 );
|
82 |
-
add_filter( 'ewww_image_optimizer_use_siip', array( $this, 'maybe_siip' ), 9 );
|
83 |
-
|
84 |
-
// Overrides for admin-ajax images.
|
85 |
-
add_filter( 'ewww_image_optimizer_admin_allow_lazyload', array( $this, 'allow_admin_lazyload' ) );
|
86 |
-
|
87 |
-
// Load the appropriate JS.
|
88 |
-
if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
|
89 |
-
// Load the non-minified and separate versions of the lazy load scripts.
|
90 |
-
add_action( 'wp_enqueue_scripts', array( $this, 'debug_script' ) );
|
91 |
-
} else {
|
92 |
-
// Load the minified, combined version of the lazy load script.
|
93 |
-
add_action( 'wp_enqueue_scripts', array( $this, 'min_script' ) );
|
94 |
-
}
|
95 |
-
}
|
96 |
-
|
97 |
-
/**
|
98 |
-
* Starts an output buffer and registers the callback function to do WebP replacement.
|
99 |
-
*/
|
100 |
-
function buffer_start() {
|
101 |
-
ob_start( array( $this, 'filter_page_output' ) );
|
102 |
-
}
|
103 |
-
|
104 |
-
/**
|
105 |
-
* Replaces images within a srcset attribute, just a placeholder at the moment.
|
106 |
-
*
|
107 |
-
* @param string $srcset A valid srcset attribute from an img element.
|
108 |
-
* @return bool|string False if no changes were made, or the new srcset if any WebP images replaced the originals.
|
109 |
-
*/
|
110 |
-
function srcset_replace( $srcset ) {
|
111 |
-
return $srcset;
|
112 |
-
}
|
113 |
-
|
114 |
-
/**
|
115 |
-
* Search for img elements and rewrite them for Lazy Load with fallback to noscript elements.
|
116 |
-
*
|
117 |
-
* @param string $buffer The full HTML page generated since the output buffer was started.
|
118 |
-
* @return string The altered buffer containing the full page with Lazy Load attributes.
|
119 |
-
*/
|
120 |
-
function filter_page_output( $buffer ) {
|
121 |
-
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
122 |
-
// Don't foul up the admin side of things, unless a plugin needs to.
|
123 |
-
if ( is_admin() &&
|
124 |
-
/**
|
125 |
-
* Provide plugins a way of running Lazy Load for images in the WordPress Dashboard (wp-admin).
|
126 |
-
*
|
127 |
-
* @param bool false Allow Lazy Load to run on the Dashboard. Default to false.
|
128 |
-
*/
|
129 |
-
false === apply_filters( 'ewww_image_optimizer_admin_allow_lazyload', false )
|
130 |
-
) {
|
131 |
-
ewwwio_debug_message( 'is_admin' );
|
132 |
-
return $buffer;
|
133 |
-
}
|
134 |
-
// Don't lazy load in these cases...
|
135 |
-
$uri = $_SERVER['REQUEST_URI'];
|
136 |
-
if (
|
137 |
-
empty( $buffer ) ||
|
138 |
-
! empty( $_GET['cornerstone'] ) ||
|
139 |
-
strpos( $uri, 'cornerstone-endpoint' ) !== false ||
|
140 |
-
! empty( $_GET['ct_builder'] ) ||
|
141 |
-
! empty( $_GET['elementor-preview'] ) ||
|
142 |
-
! empty( $_GET['et_fb'] ) ||
|
143 |
-
! empty( $_GET['tatsu'] ) ||
|
144 |
-
( ! empty( $_POST['action'] ) && 'tatsu_get_concepts' === $_POST['action'] ) ||
|
145 |
-
! apply_filters( 'ewww_image_optimizer_do_lazyload', true ) ||
|
146 |
-
is_feed() ||
|
147 |
-
is_preview() ||
|
148 |
-
( defined( 'REST_REQUEST' ) && REST_REQUEST ) ||
|
149 |
-
wp_script_is( 'twentytwenty-twentytwenty', 'enqueued' ) ||
|
150 |
-
preg_match( '/^<\?xml/', $buffer )
|
151 |
-
) {
|
152 |
-
if ( empty( $buffer ) ) {
|
153 |
-
ewwwio_debug_message( 'empty buffer' );
|
154 |
-
}
|
155 |
-
if ( ! empty( $_GET['cornerstone'] ) || strpos( $uri, 'cornerstone-endpoint' ) !== false ) {
|
156 |
-
ewwwio_debug_message( 'cornerstone editor' );
|
157 |
-
}
|
158 |
-
if ( ! empty( $_GET['ct_builder'] ) ) {
|
159 |
-
ewwwio_debug_message( 'oxygen builder' );
|
160 |
-
}
|
161 |
-
if ( ! empty( $_GET['elementor-preview'] ) ) {
|
162 |
-
ewwwio_debug_message( 'elementor preview' );
|
163 |
-
}
|
164 |
-
if ( ! empty( $_GET['et_fb'] ) ) {
|
165 |
-
ewwwio_debug_message( 'et_fb' );
|
166 |
-
}
|
167 |
-
if ( ! empty( $_GET['tatsu'] ) || ( ! empty( $_POST['action'] ) && 'tatsu_get_concepts' === $_POST['action'] ) ) {
|
168 |
-
ewwwio_debug_message( 'tatsu' );
|
169 |
-
}
|
170 |
-
if ( ! apply_filters( 'ewww_image_optimizer_do_lazyload', true ) ) {
|
171 |
-
ewwwio_debug_message( 'do_lazyload short-circuit' );
|
172 |
-
}
|
173 |
-
if ( is_feed() ) {
|
174 |
-
ewwwio_debug_message( 'is_feed' );
|
175 |
-
}
|
176 |
-
if ( is_preview() ) {
|
177 |
-
ewwwio_debug_message( 'is_preview' );
|
178 |
-
}
|
179 |
-
if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
|
180 |
-
ewwwio_debug_message( 'rest request' );
|
181 |
-
}
|
182 |
-
if ( wp_script_is( 'twentytwenty-twentytwenty', 'enqueued' ) ) {
|
183 |
-
ewwwio_debug_message( 'twentytwenty enqueued' );
|
184 |
-
}
|
185 |
-
if ( preg_match( '/^<\?xml/', $buffer ) ) {
|
186 |
-
ewwwio_debug_message( 'not html, xml tag found' );
|
187 |
-
}
|
188 |
-
if ( strpos( $buffer, 'amp-boilerplate' ) ) {
|
189 |
-
ewwwio_debug_message( 'AMP page processing' );
|
190 |
-
}
|
191 |
-
return $buffer;
|
192 |
-
}
|
193 |
-
|
194 |
-
$above_the_fold = apply_filters( 'ewww_image_optimizer_lazy_fold', 0 );
|
195 |
-
$images_processed = 0;
|
196 |
-
|
197 |
-
$images = $this->get_images_from_html( preg_replace( '/<(noscript|script).*?\/\1>/s', '', $buffer ), false );
|
198 |
-
if ( ! empty( $images[0] ) && ewww_image_optimizer_iterable( $images[0] ) ) {
|
199 |
-
foreach ( $images[0] as $index => $image ) {
|
200 |
-
$images_processed++;
|
201 |
-
if ( $images_processed <= $above_the_fold ) {
|
202 |
-
continue;
|
203 |
-
}
|
204 |
-
$file = $images['img_url'][ $index ];
|
205 |
-
ewwwio_debug_message( "parsing an image: $file" );
|
206 |
-
if ( $this->validate_image_tag( $image ) ) {
|
207 |
-
ewwwio_debug_message( 'found a valid image tag' );
|
208 |
-
$orig_img = $image;
|
209 |
-
$noscript = '<noscript>' . $orig_img . '</noscript>';
|
210 |
-
$this->set_attribute( $image, 'data-src', $file, true );
|
211 |
-
$srcset = $this->get_attribute( $image, 'srcset' );
|
212 |
-
|
213 |
-
$placeholder_src = $this->placeholder_src;
|
214 |
-
if ( false === strpos( $file, 'nggid' ) && ! preg_match( '#\.svg(\?|$)#', $file ) && apply_filters( 'ewww_image_optimizer_use_lqip', true, $file ) && $this->parsing_exactdn && strpos( $file, $this->exactdn_domain ) ) {
|
215 |
-
ewwwio_debug_message( 'using lqip' );
|
216 |
-
$placeholder_src = add_query_arg( array( 'lazy' => 1 ), $file );
|
217 |
-
} elseif ( $this->allow_piip && $srcset && apply_filters( 'ewww_image_optimizer_use_piip', true, $file ) ) {
|
218 |
-
ewwwio_debug_message( 'trying piip' );
|
219 |
-
// Get image dimensions for PNG placeholder.
|
220 |
-
list( $width, $height ) = $this->get_dimensions_from_filename( $file );
|
221 |
-
|
222 |
-
$width_attr = $this->get_attribute( $image, 'width' );
|
223 |
-
$height_attr = $this->get_attribute( $image, 'height' );
|
224 |
-
|
225 |
-
// Can't use a relative width or height, so unset the dimensions in favor of not breaking things.
|
226 |
-
if ( false !== strpos( $width_attr, '%' ) || false !== strpos( $height_attr, '%' ) ) {
|
227 |
-
$width_attr = false;
|
228 |
-
$height_attr = false;
|
229 |
-
}
|
230 |
-
|
231 |
-
if ( false === $width || false === $height ) {
|
232 |
-
$width = $width_attr;
|
233 |
-
$height = $height_attr;
|
234 |
-
}
|
235 |
-
|
236 |
-
// Falsify them if empty.
|
237 |
-
$width = $width ? (int) $width : false;
|
238 |
-
$height = $height ? (int) $height : false;
|
239 |
-
if ( $width && $height ) {
|
240 |
-
ewwwio_debug_message( "creating piip of $width x $height" );
|
241 |
-
$placeholder_src = $this->create_piip( $width, $height );
|
242 |
-
}
|
243 |
-
} elseif ( apply_filters( 'ewww_image_optimizer_use_siip', true, $file ) ) {
|
244 |
-
ewwwio_debug_message( 'trying siip' );
|
245 |
-
$width = $this->get_attribute( $image, 'width' );
|
246 |
-
$height = $this->get_attribute( $image, 'height' );
|
247 |
-
|
248 |
-
// Can't use a relative width or height, so unset the dimensions in favor of not breaking things.
|
249 |
-
if ( false !== strpos( $width, '%' ) || false !== strpos( $height, '%' ) ) {
|
250 |
-
$width = false;
|
251 |
-
$height = false;
|
252 |
-
}
|
253 |
-
|
254 |
-
// Falsify them if empty.
|
255 |
-
$width = $width ? (int) $width : false;
|
256 |
-
$height = $height ? (int) $height : false;
|
257 |
-
if ( $width && $height ) {
|
258 |
-
$placeholder_src = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 $width $height'%3E%3C/svg%3E";
|
259 |
-
}
|
260 |
-
}
|
261 |
-
ewwwio_debug_message( "current placeholder is $placeholder_src" );
|
262 |
-
|
263 |
-
if ( $srcset ) {
|
264 |
-
$placeholder_src = apply_filters( 'ewww_image_optimizer_lazy_placeholder', $placeholder_src, $image );
|
265 |
-
if ( strpos( $placeholder_src, '64,R0lGOD' ) ) {
|
266 |
-
$this->set_attribute( $image, 'srcset', $placeholder_src, true );
|
267 |
-
$this->remove_attribute( $image, 'src' );
|
268 |
-
} else {
|
269 |
-
$this->set_attribute( $image, 'src', $placeholder_src, true );
|
270 |
-
$this->remove_attribute( $image, 'srcset' );
|
271 |
-
}
|
272 |
-
$this->set_attribute( $image, 'data-srcset', $srcset, true );
|
273 |
-
$srcset_sizes = $this->get_attribute( $image, 'sizes' );
|
274 |
-
// Return false on this filter to disable automatic sizes calculation,
|
275 |
-
// or use the sizes value passed via the filter to conditionally disable it.
|
276 |
-
if ( apply_filters( 'ewww_image_optimizer_lazy_responsive', $srcset_sizes ) ) {
|
277 |
-
$this->set_attribute( $image, 'data-sizes', 'auto', true );
|
278 |
-
$this->remove_attribute( $image, 'sizes' );
|
279 |
-
}
|
280 |
-
} else {
|
281 |
-
$this->set_attribute( $image, 'src', $placeholder_src, true );
|
282 |
-
}
|
283 |
-
$this->set_attribute( $image, 'class', $this->get_attribute( $image, 'class' ) . ' lazyload', true );
|
284 |
-
$buffer = str_replace( $orig_img, $image . $noscript, $buffer );
|
285 |
-
}
|
286 |
-
} // End foreach().
|
287 |
-
} // End if().
|
288 |
-
// Process background images on div elements.
|
289 |
-
$buffer = $this->parse_background_images( $buffer, 'div' );
|
290 |
-
// Process background images on li elements.
|
291 |
-
$buffer = $this->parse_background_images( $buffer, 'li' );
|
292 |
-
// Process background images on li elements.
|
293 |
-
$buffer = $this->parse_background_images( $buffer, 'span' );
|
294 |
-
// Images listed as picture/source elements. Mostly for NextGEN, but should work anywhere.
|
295 |
-
$pictures = $this->get_picture_tags_from_html( $buffer );
|
296 |
-
if ( ewww_image_optimizer_iterable( $pictures ) ) {
|
297 |
-
foreach ( $pictures as $index => $picture ) {
|
298 |
-
$sources = $this->get_elements_from_html( $picture, 'source' );
|
299 |
-
if ( ewww_image_optimizer_iterable( $sources ) ) {
|
300 |
-
foreach ( $sources as $source ) {
|
301 |
-
if ( false !== strpos( $source, 'data-src' ) ) {
|
302 |
-
continue;
|
303 |
-
}
|
304 |
-
ewwwio_debug_message( "parsing a picture source: $source" );
|
305 |
-
$srcset = $this->get_attribute( $source, 'srcset' );
|
306 |
-
if ( $srcset ) {
|
307 |
-
ewwwio_debug_message( 'found srcset in source' );
|
308 |
-
$lazy_source = $source;
|
309 |
-
$this->set_attribute( $lazy_source, 'data-srcset', $srcset );
|
310 |
-
$this->set_attribute( $lazy_source, 'srcset', $this->placeholder_src, true );
|
311 |
-
$picture = str_replace( $source, $lazy_source, $picture );
|
312 |
-
}
|
313 |
-
}
|
314 |
-
if ( $picture !== $pictures[ $index ] ) {
|
315 |
-
ewwwio_debug_message( 'lazified sources for picture element' );
|
316 |
-
$buffer = str_replace( $pictures[ $index ], $picture, $buffer );
|
317 |
-
}
|
318 |
-
}
|
319 |
-
}
|
320 |
-
}
|
321 |
-
// Video elements, looking for poster attributes that are images.
|
322 |
-
/* $videos = $this->get_elements_from_html( $buffer, 'video' ); */
|
323 |
-
$videos = '';
|
324 |
-
if ( ewww_image_optimizer_iterable( $videos ) ) {
|
325 |
-
foreach ( $videos as $index => $video ) {
|
326 |
-
ewwwio_debug_message( 'parsing a video element' );
|
327 |
-
$file = $this->get_attribute( $video, 'poster' );
|
328 |
-
if ( $file ) {
|
329 |
-
ewwwio_debug_message( "checking webp for video poster: $file" );
|
330 |
-
if ( $this->validate_image_tag( $file ) ) {
|
331 |
-
$this->set_attribute( $video, 'data-poster-webp', $this->placeholder_src );
|
332 |
-
$this->set_attribute( $video, 'data-poster-image', $file );
|
333 |
-
$this->remove_attribute( $video, 'poster' );
|
334 |
-
ewwwio_debug_message( "found webp for video poster: $file" );
|
335 |
-
$buffer = str_replace( $videos[ $index ], $video, $buffer );
|
336 |
-
}
|
337 |
-
}
|
338 |
-
}
|
339 |
-
}
|
340 |
-
ewwwio_debug_message( 'all done parsing page for lazy' );
|
341 |
-
if ( true ) { // Set to true for extra logging.
|
342 |
-
ewww_image_optimizer_debug_log();
|
343 |
-
}
|
344 |
-
return $buffer;
|
345 |
-
}
|
346 |
-
|
347 |
-
/**
|
348 |
-
* Parse elements of a given type for inline CSS background images.
|
349 |
-
*
|
350 |
-
* @param string $buffer The HTML content to parse.
|
351 |
-
* @param string $tag_type The type of HTML tag to look for.
|
352 |
-
* @return string The modified content with LL markup.
|
353 |
-
*/
|
354 |
-
function parse_background_images( $buffer, $tag_type ) {
|
355 |
-
$elements = $this->get_elements_from_html( $buffer, $tag_type );
|
356 |
-
if ( ewww_image_optimizer_iterable( $elements ) ) {
|
357 |
-
foreach ( $elements as $index => $element ) {
|
358 |
-
ewwwio_debug_message( "parsing a $tag_type" );
|
359 |
-
if ( false === strpos( $element, 'background:' ) && false === strpos( $element, 'background-image:' ) ) {
|
360 |
-
continue;
|
361 |
-
}
|
362 |
-
ewwwio_debug_message( 'element contains background/background-image:' );
|
363 |
-
if ( ! $this->validate_bgimage_tag( $element ) ) {
|
364 |
-
continue;
|
365 |
-
}
|
366 |
-
ewwwio_debug_message( 'element is valid' );
|
367 |
-
$style = $this->get_attribute( $element, 'style' );
|
368 |
-
if ( empty( $style ) ) {
|
369 |
-
continue;
|
370 |
-
}
|
371 |
-
ewwwio_debug_message( "checking style attr for background-image: $style" );
|
372 |
-
$bg_image_url = $this->get_background_image_url( $style );
|
373 |
-
if ( $bg_image_url ) {
|
374 |
-
ewwwio_debug_message( 'bg-image url found' );
|
375 |
-
$new_style = $this->remove_background_image( $style );
|
376 |
-
if ( $style !== $new_style ) {
|
377 |
-
ewwwio_debug_message( 'style modified, continuing' );
|
378 |
-
$this->set_attribute( $element, 'class', $this->get_attribute( $element, 'class' ) . ' lazyload', true );
|
379 |
-
$this->set_attribute( $element, 'data-bg', $bg_image_url );
|
380 |
-
$element = str_replace( $style, $new_style, $element );
|
381 |
-
}
|
382 |
-
}
|
383 |
-
if ( $element !== $elements[ $index ] ) {
|
384 |
-
ewwwio_debug_message( "$tag_type modified, replacing in html source" );
|
385 |
-
$buffer = str_replace( $elements[ $index ], $element, $buffer );
|
386 |
-
}
|
387 |
-
}
|
388 |
-
}
|
389 |
-
return $buffer;
|
390 |
-
}
|
391 |
-
|
392 |
-
/**
|
393 |
-
* Checks if the tag is allowed to be lazy loaded.
|
394 |
-
*
|
395 |
-
* @param string $image The image (img) tag.
|
396 |
-
* @return bool True if the tag is allowed, false otherwise.
|
397 |
-
*/
|
398 |
-
function validate_image_tag( $image ) {
|
399 |
-
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
400 |
-
if (
|
401 |
-
strpos( $image, 'base64,R0lGOD' ) ||
|
402 |
-
strpos( $image, 'lazy-load/images/1x1' ) ||
|
403 |
-
strpos( $image, '/assets/images/' )
|
404 |
-
) {
|
405 |
-
ewwwio_debug_message( 'lazy load placeholder detected' );
|
406 |
-
return false;
|
407 |
-
}
|
408 |
-
|
409 |
-
// Skip inline data URIs.
|
410 |
-
$image_src = $this->get_attribute( $image, 'src' );
|
411 |
-
if ( false !== strpos( $image_src, 'data:image' ) ) {
|
412 |
-
return false;
|
413 |
-
}
|
414 |
-
// Ignore 0-size Pinterest schema images.
|
415 |
-
if ( strpos( $image, 'data-pin-description=' ) && strpos( $image, 'width="0" height="0"' ) ) {
|
416 |
-
return false;
|
417 |
-
}
|
418 |
-
|
419 |
-
// Ignore native lazy loading images.
|
420 |
-
$loading_attr = $this->get_attribute( $image, 'loading' );
|
421 |
-
if ( $loading_attr && in_array( trim( $loading_attr ), array( 'auto', 'eager', 'lazy' ), true ) ) {
|
422 |
-
return false;
|
423 |
-
}
|
424 |
-
|
425 |
-
$exclusions = apply_filters(
|
426 |
-
'ewww_image_optimizer_lazy_exclusions',
|
427 |
-
array(
|
428 |
-
'class="ls-bg',
|
429 |
-
'class="ls-l',
|
430 |
-
'class="rev-slidebg',
|
431 |
-
'data-bgposition=',
|
432 |
-
'data-envira-src=',
|
433 |
-
'data-lazy=',
|
434 |
-
'data-lazy-original=',
|
435 |
-
'data-lazy-src=',
|
436 |
-
'data-lazy-srcset=',
|
437 |
-
'data-lazyload=',
|
438 |
-
'data-lazysrc=',
|
439 |
-
'data-no-lazy=',
|
440 |
-
'data-src=',
|
441 |
-
'data-srcset=',
|
442 |
-
'ewww_webp_lazy_load',
|
443 |
-
'fullurl=',
|
444 |
-
'gazette-featured-content-thumbnail',
|
445 |
-
'lazy-slider-img=',
|
446 |
-
'mgl-lazy',
|
447 |
-
'skip-lazy',
|
448 |
-
'timthumb.php?',
|
449 |
-
'wpcf7_captcha/',
|
450 |
-
),
|
451 |
-
$image
|
452 |
-
);
|
453 |
-
foreach ( $exclusions as $exclusion ) {
|
454 |
-
if ( false !== strpos( $image, $exclusion ) ) {
|
455 |
-
return false;
|
456 |
-
}
|
457 |
-
}
|
458 |
-
return true;
|
459 |
-
}
|
460 |
-
|
461 |
-
/**
|
462 |
-
* Checks if a tag with a background image is allowed to be lazy loaded.
|
463 |
-
*
|
464 |
-
* @param string $tag The tag.
|
465 |
-
* @return bool True if the tag is allowed, false otherwise.
|
466 |
-
*/
|
467 |
-
function validate_bgimage_tag( $tag ) {
|
468 |
-
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
469 |
-
$exclusions = apply_filters(
|
470 |
-
'ewww_image_optimizer_lazy_bg_image_exclusions',
|
471 |
-
array(
|
472 |
-
'data-no-lazy=',
|
473 |
-
'header-gallery-wrapper ',
|
474 |
-
'lazyload',
|
475 |
-
'skip-lazy',
|
476 |
-
),
|
477 |
-
$tag
|
478 |
-
);
|
479 |
-
foreach ( $exclusions as $exclusion ) {
|
480 |
-
if ( false !== strpos( $tag, $exclusion ) ) {
|
481 |
-
return false;
|
482 |
-
}
|
483 |
-
}
|
484 |
-
return true;
|
485 |
-
}
|
486 |
-
|
487 |
-
/**
|
488 |
-
* Build a PNG inline image placeholder.
|
489 |
-
*
|
490 |
-
* @param int $width The width of the placeholder image.
|
491 |
-
* @param int $height The height of the placeholder image.
|
492 |
-
* @return string The PNG placeholder link.
|
493 |
-
*/
|
494 |
-
function create_piip( $width = 1, $height = 1 ) {
|
495 |
-
$width = (int) $width;
|
496 |
-
$height = (int) $height;
|
497 |
-
if ( 1 === $width && 1 === $height ) {
|
498 |
-
return $this->placeholder_src;
|
499 |
-
}
|
500 |
-
|
501 |
-
$piip_path = $this->piip_folder . 'placeholder-' . $width . 'x' . $height . '.png';
|
502 |
-
if ( ! is_file( $piip_path ) ) {
|
503 |
-
$img = imagecreatetruecolor( $width, $height );
|
504 |
-
$color = imagecolorallocatealpha( $img, 0, 0, 0, 127 );
|
505 |
-
imagefill( $img, 0, 0, $color );
|
506 |
-
imagesavealpha( $img, true );
|
507 |
-
imagecolortransparent( $img, imagecolorat( $img, 0, 0 ) );
|
508 |
-
imagetruecolortopalette( $img, false, 1 );
|
509 |
-
imagepng( $img, $piip_path, 9 );
|
510 |
-
}
|
511 |
-
if ( is_file( $piip_path ) ) {
|
512 |
-
return content_url( 'ewww/lazy/placeholder-' . $width . 'x' . $height . '.png' );
|
513 |
-
}
|
514 |
-
return $this->placeholder_src;
|
515 |
-
}
|
516 |
-
/**
|
517 |
-
* Allow lazy loading of images for some admin-ajax requests.
|
518 |
-
*
|
519 |
-
* @param bool $allow Will normally be false, unless already modified by another function.
|
520 |
-
* @return bool True if it's an allowable admin-ajax request, false for all other admin requests.
|
521 |
-
*/
|
522 |
-
function allow_admin_lazyload( $allow ) {
|
523 |
-
if ( ! wp_doing_ajax() ) {
|
524 |
-
return $allow;
|
525 |
-
}
|
526 |
-
if ( ! empty( $_POST['action'] ) && 'vc_get_vc_grid_data' === $_POST['action'] ) {
|
527 |
-
ewwwio_debug_message( 'allowing lazy on vc grid' );
|
528 |
-
return true;
|
529 |
-
}
|
530 |
-
if ( ! empty( $_POST['action'] ) && 'Essential_Grid_Front_request_ajax' === $_POST['action'] ) {
|
531 |
-
/* return true; */
|
532 |
-
}
|
533 |
-
return $allow;
|
534 |
-
}
|
535 |
-
|
536 |
-
/**
|
537 |
-
* Check if LQIP should be used, but allow filters to alter the option.
|
538 |
-
*
|
539 |
-
* @param bool $use_lqip Whether LL should use low-quality image placeholders.
|
540 |
-
* @return bool True to use LQIP, false to skip them.
|
541 |
-
*/
|
542 |
-
function maybe_lqip( $use_lqip ) {
|
543 |
-
if ( defined( 'EWWW_IMAGE_OPTIMIZER_USE_LQIP' ) && ! EWWW_IMAGE_OPTIMIZER_USE_LQIP ) {
|
544 |
-
return false;
|
545 |
-
}
|
546 |
-
return $use_lqip;
|
547 |
-
}
|
548 |
-
|
549 |
-
/**
|
550 |
-
* Check if PIIP should be used, but allow filters to alter the option.
|
551 |
-
*
|
552 |
-
* @param bool $use_piip Whether LL should use PNG inline image placeholders.
|
553 |
-
* @return bool True to use PIIP, false to skip them.
|
554 |
-
*/
|
555 |
-
function maybe_piip( $use_piip ) {
|
556 |
-
if ( defined( 'EWWW_IMAGE_OPTIMIZER_USE_PIIP' ) && ! EWWW_IMAGE_OPTIMIZER_USE_PIIP ) {
|
557 |
-
return false;
|
558 |
-
}
|
559 |
-
return $use_piip;
|
560 |
-
}
|
561 |
-
|
562 |
-
/**
|
563 |
-
* Check if SIIP should be used, but allow filters to alter the option.
|
564 |
-
*
|
565 |
-
* @param bool $use_siip Whether LL should use SVG inline image placeholders.
|
566 |
-
* @return bool True to use SIIP, false to skip them.
|
567 |
-
*/
|
568 |
-
function maybe_siip( $use_siip ) {
|
569 |
-
if ( defined( 'EWWW_IMAGE_OPTIMIZER_USE_SIIP' ) && ! EWWW_IMAGE_OPTIMIZER_USE_SIIP ) {
|
570 |
-
return false;
|
571 |
-
}
|
572 |
-
return $use_siip;
|
573 |
-
}
|
574 |
-
|
575 |
-
/**
|
576 |
-
* Adds a small CSS block to hide lazyload elements for no-JS browsers.
|
577 |
-
*/
|
578 |
-
function no_js_css() {
|
579 |
-
echo '<noscript><style>.lazyload[data-src]{display:none !important;}</style></noscript>';
|
580 |
-
}
|
581 |
-
|
582 |
-
/**
|
583 |
-
* Load full lazysizes script when SCRIPT_DEBUG is enabled.
|
584 |
-
*/
|
585 |
-
function debug_script() {
|
586 |
-
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
587 |
-
if ( ewww_image_optimizer_is_amp() ) {
|
588 |
-
return;
|
589 |
-
}
|
590 |
-
wp_enqueue_script( 'ewww-lazy-load-pre', plugins_url( '/includes/lazysizes-pre.js', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ), array(), EWWW_IMAGE_OPTIMIZER_VERSION );
|
591 |
-
wp_enqueue_script( 'ewww-lazy-load', plugins_url( '/includes/lazysizes.js', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ), array(), EWWW_IMAGE_OPTIMIZER_VERSION );
|
592 |
-
wp_enqueue_script( 'ewww-lazy-load-post', plugins_url( '/includes/lazysizes-post.js', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ), array(), EWWW_IMAGE_OPTIMIZER_VERSION );
|
593 |
-
wp_enqueue_script( 'ewww-lazy-load-uvh', plugins_url( '/includes/ls.unveilhooks.js', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ), array(), EWWW_IMAGE_OPTIMIZER_VERSION );
|
594 |
-
wp_localize_script(
|
595 |
-
'ewww-lazy-load',
|
596 |
-
'ewww_lazy_vars',
|
597 |
-
array(
|
598 |
-
'exactdn_domain' => ( $this->parsing_exactdn ? $this->exactdn_domain : '' ),
|
599 |
-
)
|
600 |
-
);
|
601 |
-
}
|
602 |
-
|
603 |
-
/**
|
604 |
-
* Load minified lazysizes script.
|
605 |
-
*/
|
606 |
-
function min_script() {
|
607 |
-
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
608 |
-
if ( ewww_image_optimizer_is_amp() ) {
|
609 |
-
return;
|
610 |
-
}
|
611 |
-
wp_enqueue_script( 'ewww-lazy-load', plugins_url( '/includes/lazysizes.min.js', EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE ), array(), EWWW_IMAGE_OPTIMIZER_VERSION );
|
612 |
-
wp_localize_script(
|
613 |
-
'ewww-lazy-load',
|
614 |
-
'ewww_lazy_vars',
|
615 |
-
array(
|
616 |
-
'exactdn_domain' => ( $this->parsing_exactdn ? $this->exactdn_domain : '' ),
|
617 |
-
)
|
618 |
-
);
|
619 |
-
}
|
620 |
-
}
|
621 |
-
|
622 |
-
global $ewwwio_lazy_load;
|
623 |
-
$ewwwio_lazy_load = new EWWWIO_Lazy_Load();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
classes/class-ewwwio-page-parser.php
DELETED
@@ -1,318 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Implements basic page parsing functions.
|
4 |
-
*
|
5 |
-
* @link https://ewww.io
|
6 |
-
* @package EWWW_Image_Optimizer
|
7 |
-
*/
|
8 |
-
|
9 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
10 |
-
exit;
|
11 |
-
}
|
12 |
-
/**
|
13 |
-
* HTML element and attribute parsing, replacing, etc.
|
14 |
-
*/
|
15 |
-
class EWWWIO_Page_Parser {
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Allowed image extensions.
|
19 |
-
*
|
20 |
-
* @access private
|
21 |
-
* @var array $extensions
|
22 |
-
*/
|
23 |
-
protected $extensions = array(
|
24 |
-
'gif',
|
25 |
-
'jpg',
|
26 |
-
'jpeg',
|
27 |
-
'jpe',
|
28 |
-
'png',
|
29 |
-
);
|
30 |
-
|
31 |
-
/**
|
32 |
-
* Match all images and any relevant <a> tags in a block of HTML.
|
33 |
-
*
|
34 |
-
* The hyperlinks param implies that the src attribute is required, but not the other way around.
|
35 |
-
*
|
36 |
-
* @param string $content Some HTML.
|
37 |
-
* @param bool $hyperlinks Default true. Should we include encasing hyperlinks in our search.
|
38 |
-
* @param bool $src_required Default true. Should we look only for images with src attributes.
|
39 |
-
* @return array An array of $images matches, where $images[0] is
|
40 |
-
* an array of full matches, and the link_url, img_tag,
|
41 |
-
* and img_url keys are arrays of those matches.
|
42 |
-
*/
|
43 |
-
function get_images_from_html( $content, $hyperlinks = true, $src_required = true ) {
|
44 |
-
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
45 |
-
$images = array();
|
46 |
-
$unquoted_images = array();
|
47 |
-
|
48 |
-
$unquoted_pattern = '';
|
49 |
-
$search_pattern = '#(?P<img_tag><img\s[^>]*?>)#is';
|
50 |
-
if ( $hyperlinks ) {
|
51 |
-
ewwwio_debug_message( 'using figure+hyperlink(a) patterns with src required' );
|
52 |
-
$search_pattern = '#(?:<figure[^>]*?\s+?class\s*=\s*["\'](?P<figure_class>[\w\s-]+?)["\'][^>]*?>\s*)?(?:<a[^>]*?\s+?href\s*=\s*["\'](?P<link_url>[^\s]+?)["\'][^>]*?>\s*)?(?P<img_tag><img[^>]*?\s+?src\s*=\s*("|\')(?P<img_url>(?!\4).+?)\4[^>]*?>){1}(?:\s*</a>)?#is';
|
53 |
-
$unquoted_pattern = '#(?:<figure[^>]*?\s+?class\s*=\s*(?P<figure_class>[\w-]+)[^>]*?>\s*)?(?:<a[^>]*?\s+?href\s*=\s*(?P<link_url>[^"\'][^\s>]+)[^>]*?>\s*)?(?P<img_tag><img[^>]*?\s+?src\s*=\s*(?P<img_url>[^"\'][^\s>]+)[^>]*?>){1}(?:\s*</a>)?#is';
|
54 |
-
} elseif ( $src_required ) {
|
55 |
-
ewwwio_debug_message( 'using plain img pattern, src still required' );
|
56 |
-
$search_pattern = '#(?P<img_tag><img[^>]*?\s+?src\s*=\s*("|\')(?P<img_url>(?!\2).+?)\2[^>]*?>)#is';
|
57 |
-
$unquoted_pattern = '#(?P<img_tag><img[^>]*?\s+?src\s*=\s*(?P<img_url>[^"\'][^\s>]+)[^>]*?>)#is';
|
58 |
-
}
|
59 |
-
if ( preg_match_all( $search_pattern, $content, $images ) ) {
|
60 |
-
ewwwio_debug_message( 'found ' . count( $images[0] ) . ' image elements with quoted pattern' );
|
61 |
-
foreach ( $images as $key => $unused ) {
|
62 |
-
// Simplify the output as much as possible.
|
63 |
-
if ( is_numeric( $key ) && $key > 0 ) {
|
64 |
-
unset( $images[ $key ] );
|
65 |
-
}
|
66 |
-
}
|
67 |
-
/* ewwwio_debug_message( print_r( $images, true ) ); */
|
68 |
-
}
|
69 |
-
$images = array_filter( $images );
|
70 |
-
if ( $unquoted_pattern && preg_match_all( $unquoted_pattern, $content, $unquoted_images ) ) {
|
71 |
-
ewwwio_debug_message( 'found ' . count( $unquoted_images[0] ) . ' image elements with unquoted pattern' );
|
72 |
-
foreach ( $unquoted_images as $key => $unused ) {
|
73 |
-
// Simplify the output as much as possible.
|
74 |
-
if ( is_numeric( $key ) && $key > 0 ) {
|
75 |
-
unset( $unquoted_images[ $key ] );
|
76 |
-
}
|
77 |
-
}
|
78 |
-
/* ewwwio_debug_message( print_r( $unquoted_images, true ) ); */
|
79 |
-
}
|
80 |
-
$unquoted_images = array_filter( $unquoted_images );
|
81 |
-
if ( ! empty( $images ) && ! empty( $unquoted_images ) ) {
|
82 |
-
ewwwio_debug_message( 'both patterns found results, merging' );
|
83 |
-
/* ewwwio_debug_message( print_r( $images, true ) ); */
|
84 |
-
$images = array_merge_recursive( $images, $unquoted_images );
|
85 |
-
/* ewwwio_debug_message( print_r( $images, true ) ); */
|
86 |
-
if ( ! empty( $images[0] ) && ! empty( $images[1] ) ) {
|
87 |
-
$images[0] = array_merge( $images[0], $images[1] );
|
88 |
-
unset( $images[1] );
|
89 |
-
}
|
90 |
-
} elseif ( empty( $images ) && ! empty( $unquoted_images ) ) {
|
91 |
-
ewwwio_debug_message( 'unquoted results only, subbing in' );
|
92 |
-
$images = $unquoted_images;
|
93 |
-
}
|
94 |
-
/* ewwwio_debug_message( print_r( $images, true ) ); */
|
95 |
-
return $images;
|
96 |
-
}
|
97 |
-
|
98 |
-
/**
|
99 |
-
* Match all images wrapped in <noscript> tags in a block of HTML.
|
100 |
-
*
|
101 |
-
* @param string $content Some HTML.
|
102 |
-
* @return array An array of $images matches, where $images[0] is
|
103 |
-
* an array of full matches, and the noscript_tag, img_tag,
|
104 |
-
* and img_url keys are arrays of those matches.
|
105 |
-
*/
|
106 |
-
function get_noscript_images_from_html( $content ) {
|
107 |
-
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
108 |
-
$images = array();
|
109 |
-
|
110 |
-
if ( preg_match_all( '#(?P<noscript_tag><noscript[^>]*?>\s*)(?P<img_tag><img[^>]*?\s+?src\s*=\s*["\'](?P<img_url>[^\s]+?)["\'][^>]*?>){1}(?:\s*</noscript>)?#is', $content, $images ) ) {
|
111 |
-
foreach ( $images as $key => $unused ) {
|
112 |
-
// Simplify the output as much as possible, mostly for confirming test results.
|
113 |
-
if ( is_numeric( $key ) && $key > 0 ) {
|
114 |
-
unset( $images[ $key ] );
|
115 |
-
}
|
116 |
-
}
|
117 |
-
return $images;
|
118 |
-
}
|
119 |
-
return array();
|
120 |
-
}
|
121 |
-
|
122 |
-
/**
|
123 |
-
* Match all sources wrapped in <picture> tags in a block of HTML.
|
124 |
-
*
|
125 |
-
* @param string $content Some HTML.
|
126 |
-
* @return array An array of $pictures matches, containing full elements with ending tags.
|
127 |
-
*/
|
128 |
-
function get_picture_tags_from_html( $content ) {
|
129 |
-
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
130 |
-
$pictures = array();
|
131 |
-
if ( preg_match_all( '#(?:<picture[^>]*?>\s*)(?:<source[^>]*?>)+(?:.*?</picture>)?#is', $content, $pictures ) ) {
|
132 |
-
return $pictures[0];
|
133 |
-
}
|
134 |
-
return array();
|
135 |
-
}
|
136 |
-
|
137 |
-
/**
|
138 |
-
* Match all elements by tag name in a block of HTML. Does not retrieve contents or closing tags.
|
139 |
-
*
|
140 |
-
* @param string $content Some HTML.
|
141 |
-
* @param string $tag_name The name of the elements to retrieve.
|
142 |
-
* @return array An array of $elements.
|
143 |
-
*/
|
144 |
-
function get_elements_from_html( $content, $tag_name ) {
|
145 |
-
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
146 |
-
if ( ! ctype_alpha( $tag_name ) ) {
|
147 |
-
return array();
|
148 |
-
}
|
149 |
-
if ( preg_match_all( '#<' . $tag_name . '\s[^>]+?>#is', $content, $elements ) ) {
|
150 |
-
return $elements[0];
|
151 |
-
}
|
152 |
-
return array();
|
153 |
-
}
|
154 |
-
|
155 |
-
/**
|
156 |
-
* Try to determine height and width from strings WP appends to resized image filenames.
|
157 |
-
*
|
158 |
-
* @param string $src The image URL.
|
159 |
-
* @return array An array consisting of width and height.
|
160 |
-
*/
|
161 |
-
function get_dimensions_from_filename( $src ) {
|
162 |
-
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
163 |
-
$width_height_string = array();
|
164 |
-
ewwwio_debug_message( "looking for dimensions in $src" );
|
165 |
-
if ( preg_match( '#-(\d+)x(\d+)(@2x)?\.(?:' . implode( '|', $this->extensions ) . '){1}(?:\?.+)?$#i', $src, $width_height_string ) ) {
|
166 |
-
$width = (int) $width_height_string[1];
|
167 |
-
$height = (int) $width_height_string[2];
|
168 |
-
|
169 |
-
if ( strpos( $src, '@2x' ) ) {
|
170 |
-
$width = 2 * $width;
|
171 |
-
$height = 2 * $height;
|
172 |
-
}
|
173 |
-
if ( $width && $height ) {
|
174 |
-
ewwwio_debug_message( "found w$width h$height" );
|
175 |
-
return array( $width, $height );
|
176 |
-
}
|
177 |
-
}
|
178 |
-
return array( false, false );
|
179 |
-
}
|
180 |
-
|
181 |
-
/**
|
182 |
-
* Get the width from an image element.
|
183 |
-
*
|
184 |
-
* @param string $img The full image element.
|
185 |
-
* @return string The width found or an empty string.
|
186 |
-
*/
|
187 |
-
public function get_img_width( $img ) {
|
188 |
-
$width = $this->get_attribute( $img, 'width' );
|
189 |
-
// Then check for an inline max-width directive.
|
190 |
-
$style = $this->get_attribute( $img, 'style' );
|
191 |
-
if ( $style && preg_match( '#max-width:\s?(\d+)px#', $style, $max_width_string ) ) {
|
192 |
-
if ( $max_width_string[1] && ( ! $width || $max_width_string[1] < $width ) ) {
|
193 |
-
$width = $max_width_string[1];
|
194 |
-
}
|
195 |
-
}
|
196 |
-
return $width;
|
197 |
-
}
|
198 |
-
|
199 |
-
/**
|
200 |
-
* Get an attribute from an HTML element.
|
201 |
-
*
|
202 |
-
* @param string $element The HTML element to parse.
|
203 |
-
* @param string $name The name of the attribute to search for.
|
204 |
-
* @return string The value of the attribute, or an empty string if not found.
|
205 |
-
*/
|
206 |
-
function get_attribute( $element, $name ) {
|
207 |
-
// Don't forget, back references cannot be used in character classes.
|
208 |
-
if ( preg_match( '#\s' . $name . '\s*=\s*("|\')((?!\1).+?)\1#is', $element, $attr_matches ) ) {
|
209 |
-
if ( ! empty( $attr_matches[2] ) ) {
|
210 |
-
return $attr_matches[2];
|
211 |
-
}
|
212 |
-
}
|
213 |
-
// If there were not any matches with quotes, look for unquoted attributes, no spaces or quotes allowed.
|
214 |
-
if ( preg_match( '#\s' . $name . '\s*=\s*([^"\'][^\s>]+)#is', $element, $attr_matches ) ) {
|
215 |
-
if ( ! empty( $attr_matches[1] ) ) {
|
216 |
-
return $attr_matches[1];
|
217 |
-
}
|
218 |
-
}
|
219 |
-
return '';
|
220 |
-
}
|
221 |
-
|
222 |
-
/**
|
223 |
-
* Get a CSS background-image URL.
|
224 |
-
*
|
225 |
-
* @param string $attribute An element's style attribute. Do not pass a full HTML element.
|
226 |
-
* @return string The URL from the background/background-image property.
|
227 |
-
*/
|
228 |
-
function get_background_image_url( $attribute ) {
|
229 |
-
if ( ( false !== strpos( $attribute, 'background:' ) || false !== strpos( $attribute, 'background-image:' ) ) && false !== strpos( $attribute, 'url(' ) ) {
|
230 |
-
if ( preg_match( '#url\(([^)]+)\)#', $attribute, $prop_match ) ) {
|
231 |
-
return trim( $prop_match[1], "'\"\t\n\r " );
|
232 |
-
}
|
233 |
-
}
|
234 |
-
return '';
|
235 |
-
}
|
236 |
-
|
237 |
-
/**
|
238 |
-
* Set an attribute on an HTML element.
|
239 |
-
*
|
240 |
-
* @param string $element The HTML element to modify. Passed by reference.
|
241 |
-
* @param string $name The name of the attribute to set.
|
242 |
-
* @param string $value The value of the attribute to set.
|
243 |
-
* @param bool $replace Default false. True to replace, false to append.
|
244 |
-
*/
|
245 |
-
function set_attribute( &$element, $name, $value, $replace = false ) {
|
246 |
-
if ( 'class' === $name ) {
|
247 |
-
$element = preg_replace( "#\s$name\s+[^=]#", ' ', $element );
|
248 |
-
}
|
249 |
-
$element = preg_replace( "#\s$name=\"\"#", ' ', $element );
|
250 |
-
$value = trim( $value );
|
251 |
-
if ( $replace ) {
|
252 |
-
// Don't forget, back references cannot be used in character classes.
|
253 |
-
$new_element = preg_replace( '#\s' . $name . '\s*=\s*("|\')(?!\1).*?\1#is', " $name=$1$value$1", $element );
|
254 |
-
if ( strpos( $new_element, "$name=" ) ) {
|
255 |
-
$element = $new_element;
|
256 |
-
return;
|
257 |
-
}
|
258 |
-
$element = preg_replace( '#\s' . $name . '\s*=\s*[^"\'][^\s>]+#is', ' ', $element );
|
259 |
-
}
|
260 |
-
$closing = ' />';
|
261 |
-
if ( false === strpos( $element, '/>' ) ) {
|
262 |
-
$closing = '>';
|
263 |
-
}
|
264 |
-
if ( false === strpos( $value, '"' ) ) {
|
265 |
-
$element = rtrim( $element, $closing ) . " $name=\"$value\"$closing";
|
266 |
-
return;
|
267 |
-
}
|
268 |
-
$element = rtrim( $element, $closing ) . " $name='$value'$closing";
|
269 |
-
}
|
270 |
-
|
271 |
-
/**
|
272 |
-
* Remove an attribute from an HTML element.
|
273 |
-
*
|
274 |
-
* @param string $element The HTML element to modify. Passed by reference.
|
275 |
-
* @param string $name The name of the attribute to remove.
|
276 |
-
*/
|
277 |
-
function remove_attribute( &$element, $name ) {
|
278 |
-
// Don't forget, back references cannot be used in character classes.
|
279 |
-
$element = preg_replace( '#\s' . $name . '\s*=\s*("|\')(?!\1).+?\1#is', ' ', $element );
|
280 |
-
$element = preg_replace( '#\s' . $name . '\s*=\s*[^"\'][^\s>]+#is', ' ', $element );
|
281 |
-
}
|
282 |
-
|
283 |
-
/**
|
284 |
-
* Remove the background image URL from a style attribute.
|
285 |
-
*
|
286 |
-
* @param string $attribute The element's style attribute to modify.
|
287 |
-
* @return string The style attribute with any image url removed.
|
288 |
-
*/
|
289 |
-
function remove_background_image( $attribute ) {
|
290 |
-
if ( false !== strpos( $attribute, 'background:' ) && false !== strpos( $attribute, 'url(' ) ) {
|
291 |
-
$attribute = preg_replace( '#\s?url\([^)]+\)#', '', $attribute );
|
292 |
-
}
|
293 |
-
if ( false !== strpos( $attribute, 'background-image:' ) && false !== strpos( $attribute, 'url(' ) ) {
|
294 |
-
$attribute = preg_replace( '#background-image:\s*url\([^)]+\);?#', '', $attribute );
|
295 |
-
}
|
296 |
-
return $attribute;
|
297 |
-
}
|
298 |
-
|
299 |
-
/**
|
300 |
-
* A wrapper for PHP's parse_url, prepending assumed scheme for network path
|
301 |
-
* URLs. PHP versions 5.4.6 and earlier do not correctly parse without scheme.
|
302 |
-
*
|
303 |
-
* @param string $url The URL to parse.
|
304 |
-
* @param integer $component Retrieve specific URL component.
|
305 |
-
* @return mixed Result of parse_url.
|
306 |
-
*/
|
307 |
-
function parse_url( $url, $component = -1 ) {
|
308 |
-
if ( 0 === strpos( $url, '//' ) ) {
|
309 |
-
$url = ( is_ssl() ? 'https:' : 'http:' ) . $url;
|
310 |
-
}
|
311 |
-
if ( false === strpos( $url, 'http' ) && '/' !== substr( $url, 0, 1 ) ) {
|
312 |
-
$url = ( is_ssl() ? 'https://' : 'http://' ) . $url;
|
313 |
-
}
|
314 |
-
// Because encoded ampersands in the filename break things.
|
315 |
-
$url = str_replace( '&', '&', $url );
|
316 |
-
return parse_url( $url, $component );
|
317 |
-
}
|
318 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
classes/class-exactdn.php
CHANGED
@@ -3,2713 +3,2699 @@
|
|
3 |
* Class and methods to implement ExactDN (based on Photon implementation).
|
4 |
*
|
5 |
* @link https://ewww.io
|
6 |
-
* @package
|
7 |
*/
|
8 |
|
9 |
if ( ! defined( 'ABSPATH' ) ) {
|
10 |
exit;
|
11 |
}
|
12 |
|
13 |
-
|
14 |
-
* Enables EWWW IO to filter the page content and replace image urls with ExactDN urls.
|
15 |
-
*/
|
16 |
-
class ExactDN extends EWWWIO_Page_Parser {
|
17 |
-
|
18 |
/**
|
19 |
-
*
|
20 |
-
*
|
21 |
-
* @access protected
|
22 |
-
* @var array $user_exclusions
|
23 |
*/
|
24 |
-
|
25 |
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
return 'you are doing it wrong';
|
106 |
-
}
|
107 |
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
112 |
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
if ( strpos( $site_url, 'https://' ) !== false ) {
|
117 |
-
$scheme = 'https';
|
118 |
}
|
119 |
-
$this->scheme = $scheme;
|
120 |
-
}
|
121 |
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
|
|
|
|
|
|
|
|
126 |
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
ewwwio_debug_message( 'aq_resize detected, image_downsize filter disabled' );
|
132 |
-
}
|
133 |
-
// Disable image_downsize filter during themify_get_image().
|
134 |
-
add_action( 'themify_before_post_image', array( $this, 'disable_image_downsize' ) );
|
135 |
-
if ( defined( 'EXACTDN_IMAGE_DOWNSIZE_SCALE' ) && EXACTDN_IMAGE_DOWNSIZE_SCALE ) {
|
136 |
-
add_action( 'exactdn_image_downsize_array', array( $this, 'image_downsize_scale' ) );
|
137 |
-
}
|
138 |
|
139 |
-
|
140 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
141 |
|
142 |
-
|
143 |
-
|
144 |
-
// Overrides for "pass through" images.
|
145 |
-
add_filter( 'exactdn_pre_args', array( $this, 'exactdn_remove_args' ), 10, 3 );
|
146 |
-
// Overrides for user exclusions.
|
147 |
-
add_filter( 'exactdn_skip_image', array( $this, 'exactdn_skip_user_exclusions' ), 9, 2 );
|
148 |
-
add_filter( 'exactdn_skip_for_url', array( $this, 'exactdn_skip_user_exclusions' ), 9, 2 );
|
149 |
|
150 |
-
|
151 |
-
|
152 |
-
|
|
|
|
|
|
|
|
|
153 |
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
|
158 |
-
|
159 |
-
|
|
|
160 |
|
161 |
-
|
162 |
-
|
163 |
|
164 |
-
|
165 |
-
|
166 |
-
add_filter( 'style_loader_src', array( $this, 'parse_enqueue' ), 20 );
|
167 |
-
add_filter( 'script_loader_src', array( $this, 'parse_enqueue' ), 20 );
|
168 |
-
}
|
169 |
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
if ( empty( $ao_cdn_url ) ) {
|
181 |
-
ewww_image_optimizer_set_option( 'autoptimize_cdn_url', '//' . $this->exactdn_domain );
|
182 |
-
} elseif ( strpos( $ao_cdn_url, 'exactdn' ) && '//' . $this->exactdn_domain !== $ao_cdn_url ) {
|
183 |
-
ewww_image_optimizer_set_option( 'autoptimize_cdn_url', '//' . $this->exactdn_domain );
|
184 |
}
|
185 |
-
}
|
186 |
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
$
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
$
|
|
|
|
|
|
|
|
|
197 |
}
|
198 |
-
}
|
199 |
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
}
|
207 |
-
$upload_url_parts = defined( 'EXACTDN_LOCAL_DOMAIN' ) && EXACTDN_LOCAL_DOMAIN ? $this->parse_url( EXACTDN_LOCAL_DOMAIN ) : $this->parse_url( $upload_dir['baseurl'] );
|
208 |
-
if ( empty( $upload_url_parts ) ) {
|
209 |
-
return;
|
210 |
-
}
|
211 |
-
$this->upload_domain = $upload_url_parts['host'];
|
212 |
-
ewwwio_debug_message( "allowing images from here: $this->upload_domain" );
|
213 |
-
if ( strpos( $this->upload_domain, 'amazonaws.com' ) && ! empty( $upload_url_parts['path'] ) ) {
|
214 |
-
$this->remove_path = rtrim( $upload_url_parts['path'], '/' );
|
215 |
-
ewwwio_debug_message( "removing this from urls: $this->remove_path" );
|
216 |
-
}
|
217 |
-
$this->allowed_domains[] = $this->upload_domain;
|
218 |
-
if ( ! $s3_active && strpos( $this->upload_domain, 'www' ) === false ) {
|
219 |
-
$this->allowed_domains[] = 'www.' . $this->upload_domain;
|
220 |
-
} else {
|
221 |
-
$nonwww = ltrim( 'www.', $this->upload_domain );
|
222 |
-
if ( $nonwww !== $this->upload_domain ) {
|
223 |
-
$this->allowed_domains[] = $nonwww;
|
224 |
}
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
$this->
|
230 |
-
|
231 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
232 |
}
|
|
|
|
|
|
|
233 |
}
|
234 |
-
$this->allowed_domains = apply_filters( 'exactdn_allowed_domains', $this->allowed_domains );
|
235 |
-
ewwwio_debug_message( 'allowed domains: ' . implode( ',', $this->allowed_domains ) );
|
236 |
-
$this->validate_user_exclusions();
|
237 |
-
}
|
238 |
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
$
|
255 |
-
$failures++;
|
256 |
-
ewwwio_debug_message( "could not activate ExactDN, failures: $failures" );
|
257 |
-
update_option( 'ewww_image_optimizer_exactdn_failures', $failures );
|
258 |
return false;
|
259 |
}
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
delete_option( '
|
268 |
-
$this->
|
269 |
-
|
270 |
-
|
271 |
-
} elseif ( $this->get_exactdn_option( 'checkin' ) < time() - 5 && get_option( 'ewww_image_optimizer_exactdn_failures' ) < 10 ) {
|
272 |
-
$failures = (int) get_option( 'ewww_image_optimizer_exactdn_failures' );
|
273 |
-
$failures++;
|
274 |
-
ewwwio_debug_message( "could not verify existing exactDN domain, failures: $failures" );
|
275 |
-
update_option( 'ewww_image_optimizer_exactdn_failures', $failures );
|
276 |
-
$this->set_exactdn_option( 'checkin', time() + 300 );
|
277 |
-
return false;
|
278 |
-
} elseif ( get_option( 'ewww_image_optimizer_exactdn_failures' ) < 10 ) {
|
279 |
-
$failures = (int) get_option( 'ewww_image_optimizer_exactdn_failures' );
|
280 |
-
ewwwio_debug_message( 'could not verify existing exactDN domain, waiting for ' . $this->human_time_diff( $this->get_exactdn_option( 'checkin' ) ) );
|
281 |
-
ewwwio_debug_message( 10 - $failures . ' attempts remaining' );
|
282 |
return false;
|
283 |
}
|
284 |
-
delete_option( 'ewww_image_optimizer_exactdn_domain' );
|
285 |
-
delete_option( 'ewww_image_optimizer_exactdn_verified' );
|
286 |
-
delete_site_option( 'ewww_image_optimizer_exactdn_domain' );
|
287 |
-
delete_site_option( 'ewww_image_optimizer_exactdn_verified' );
|
288 |
-
return false;
|
289 |
-
}
|
290 |
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
|
|
306 |
}
|
307 |
-
}
|
308 |
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
342 |
}
|
343 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
344 |
}
|
345 |
-
} elseif ( ! empty( $result['body'] ) && strpos( $result['body'], 'error' ) !== false ) {
|
346 |
-
$response = json_decode( $result['body'], true );
|
347 |
-
$error_message = $response['error'];
|
348 |
-
ewwwio_debug_message( "exactdn activation request failed: $error_message" );
|
349 |
return false;
|
350 |
}
|
351 |
-
return false;
|
352 |
-
}
|
353 |
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
371 |
return false;
|
372 |
}
|
373 |
-
return true;
|
374 |
-
}
|
375 |
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
390 |
return false;
|
391 |
-
} elseif ( ! empty( $
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
$this->set_exactdn_option( 'checkin', time() + 3600 );
|
396 |
$this->set_exactdn_option( 'verified', 1, false );
|
397 |
-
$this->
|
398 |
return true;
|
399 |
}
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
$url = 'http://optimize.exactlywww.com/exactdn/verify.php';
|
408 |
-
$ssl = wp_http_supports( array( 'ssl' ) );
|
409 |
-
if ( $ssl ) {
|
410 |
-
$url = set_url_scheme( $url, 'https' );
|
411 |
-
}
|
412 |
-
add_filter( 'http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX );
|
413 |
-
$result = wp_remote_post(
|
414 |
-
$url,
|
415 |
-
array(
|
416 |
-
'timeout' => 10,
|
417 |
-
'body' => array(
|
418 |
-
'alias' => $domain,
|
419 |
-
),
|
420 |
-
)
|
421 |
-
);
|
422 |
-
if ( is_wp_error( $result ) ) {
|
423 |
-
$error_message = $result->get_error_message();
|
424 |
-
ewwwio_debug_message( "exactdn verification request failed: $error_message" );
|
425 |
-
$this->set_exactdn_option( 'suspended', 1 );
|
426 |
-
return false;
|
427 |
-
} elseif ( ! empty( $result['body'] ) && strpos( $result['body'], 'error' ) === false ) {
|
428 |
-
$response = json_decode( $result['body'], true );
|
429 |
-
if ( ! empty( $response['success'] ) ) {
|
430 |
-
ewwwio_debug_message( 'exactdn (secondary) verification succeeded' );
|
431 |
-
$this->set_exactdn_option( 'checkin', time() + 3600 );
|
432 |
-
$this->set_exactdn_option( 'verified', 1, false );
|
433 |
-
$this->set_exactdn_option( 'suspended', 0 );
|
434 |
-
return true;
|
435 |
}
|
436 |
-
|
437 |
-
$response = json_decode( $result['body'], true );
|
438 |
-
$error_message = $response['error'];
|
439 |
-
ewwwio_debug_message( "exactdn verification request failed: $error_message" );
|
440 |
-
$this->set_exactdn_option( 'suspended', 1 );
|
441 |
return false;
|
442 |
}
|
443 |
-
$this->set_exactdn_option( 'suspended', 1 );
|
444 |
-
return false;
|
445 |
-
}
|
446 |
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
|
|
465 |
}
|
|
|
|
|
466 |
}
|
467 |
-
ewwwio_debug_message( 'exactdn (simulated) verification request failed, error unknown' );
|
468 |
-
$this->set_exactdn_option( 'verify_method', -1, false );
|
469 |
}
|
470 |
-
}
|
471 |
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
|
|
|
|
490 |
}
|
491 |
-
return $domain;
|
492 |
-
}
|
493 |
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
|
|
506 |
}
|
|
|
507 |
}
|
508 |
-
return $this->sanitize_domain( get_option( 'ewww_image_optimizer_exactdn_domain' ) );
|
509 |
-
}
|
510 |
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
}
|
521 |
-
/**
|
522 |
-
* Get the ExactDN option.
|
523 |
-
*
|
524 |
-
* @param string $option_name The name of the ExactDN option.
|
525 |
-
* @return int The numerical value of the option.
|
526 |
-
*/
|
527 |
-
function get_exactdn_option( $option_name ) {
|
528 |
-
if ( defined( 'EXACTDN_DOMAIN' ) && EXACTDN_DOMAIN ) {
|
529 |
-
return (int) get_option( 'ewww_image_optimizer_exactdn_' . $option_name );
|
530 |
}
|
531 |
-
|
532 |
-
|
533 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
534 |
}
|
|
|
535 |
}
|
536 |
-
return (int) get_option( 'ewww_image_optimizer_exactdn_' . $option_name );
|
537 |
-
}
|
538 |
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
|
|
557 |
}
|
|
|
|
|
558 |
}
|
559 |
-
update_option( 'ewww_image_optimizer_exactdn_domain', $domain );
|
560 |
-
return $domain;
|
561 |
-
}
|
562 |
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
|
|
578 |
}
|
|
|
579 |
}
|
580 |
-
return update_option( 'ewww_image_optimizer_exactdn_' . $option_name, $option_value, $autoload );
|
581 |
-
}
|
582 |
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
|
|
|
|
598 |
}
|
599 |
-
$this->user_exclusions[] = ltrim( $exclusion, '/' );
|
600 |
}
|
601 |
}
|
602 |
}
|
603 |
-
}
|
604 |
|
605 |
-
/**
|
606 |
-
* Get $content_width, with a filter.
|
607 |
-
*
|
608 |
-
* @return bool|string The content width, if set. Default false.
|
609 |
-
*/
|
610 |
-
function get_content_width() {
|
611 |
-
$content_width = isset( $GLOBALS['content_width'] ) && is_numeric( $GLOBALS['content_width'] ) && $GLOBALS['content_width'] > 100 ? $GLOBALS['content_width'] : 1920;
|
612 |
-
if ( function_exists( 'twentynineteen_setup' ) && 640 === (int) $content_width ) {
|
613 |
-
$content_width = 932;
|
614 |
-
}
|
615 |
/**
|
616 |
-
*
|
617 |
*
|
618 |
-
* @
|
619 |
*/
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
* Get width within an ExactDN url.
|
625 |
-
*
|
626 |
-
* @param string $url The ExactDN url to parse.
|
627 |
-
* @return string The width, if found.
|
628 |
-
*/
|
629 |
-
public function get_exactdn_width_from_url( $url ) {
|
630 |
-
$url_args = $this->parse_url( $url, PHP_URL_QUERY );
|
631 |
-
if ( ! $url_args ) {
|
632 |
-
return '';
|
633 |
-
}
|
634 |
-
$args = explode( '&', $url_args );
|
635 |
-
foreach ( $args as $arg ) {
|
636 |
-
if ( preg_match( '#w=(\d+)#', $arg, $width_match ) ) {
|
637 |
-
return $width_match[1];
|
638 |
}
|
639 |
-
|
640 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
641 |
}
|
642 |
-
|
643 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
644 |
}
|
|
|
645 |
}
|
646 |
-
return '';
|
647 |
-
}
|
648 |
-
|
649 |
-
/**
|
650 |
-
* Identify images in page content, and if images are local (uploaded to the current site), pass through ExactDN.
|
651 |
-
*
|
652 |
-
* @param string $content The page/post content.
|
653 |
-
* @return string The content with ExactDN image urls.
|
654 |
-
*/
|
655 |
-
function filter_page_output( $content ) {
|
656 |
-
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
657 |
-
$this->filtering_the_page = true;
|
658 |
-
|
659 |
-
$content = $this->filter_the_content( $content );
|
660 |
|
661 |
/**
|
662 |
-
*
|
663 |
*
|
664 |
-
* @param string $content The
|
|
|
665 |
*/
|
666 |
-
|
|
|
|
|
667 |
|
668 |
-
|
669 |
-
ewwwio_debug_message( "parsing page took $this->elapsed_time seconds" );
|
670 |
-
return $content;
|
671 |
-
}
|
672 |
-
|
673 |
-
/**
|
674 |
-
* Identify images in the content, and if images are local (uploaded to the current site), pass through ExactDN.
|
675 |
-
*
|
676 |
-
* @param string $content The page/post content.
|
677 |
-
* @return string The content with ExactDN image urls.
|
678 |
-
*/
|
679 |
-
function filter_the_content( $content ) {
|
680 |
-
$started = microtime( true );
|
681 |
-
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
682 |
-
$images = $this->get_images_from_html( $content, true );
|
683 |
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
$content_width = $this->get_content_width();
|
691 |
-
}
|
692 |
-
$resize_existing = defined( 'EXACTDN_RESIZE_EXISTING' ) && EXACTDN_RESIZE_EXISTING;
|
693 |
-
|
694 |
-
$image_sizes = $this->image_sizes();
|
695 |
-
|
696 |
-
foreach ( $images[0] as $index => $tag ) {
|
697 |
-
// Default to resize, though fit may be used in certain cases where a dimension cannot be ascertained.
|
698 |
-
$transform = 'resize';
|
699 |
-
|
700 |
-
// Start with a clean slate each time.
|
701 |
-
$attachment_id = false;
|
702 |
-
$exactdn_url = false;
|
703 |
-
$width = false;
|
704 |
-
$lazy = false;
|
705 |
-
$srcset_fill = false;
|
706 |
-
|
707 |
-
// Flag if we need to munge a fullsize URL.
|
708 |
-
$fullsize_url = false;
|
709 |
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
724 |
}
|
|
|
725 |
|
726 |
-
|
727 |
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
}
|
732 |
|
733 |
-
|
734 |
-
|
735 |
-
$
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
*
|
740 |
-
* @param array|string $args Array of ExactDN arguments.
|
741 |
-
* @param string $image_url Image URL.
|
742 |
-
* @param string|null $scheme Image scheme. Default to null.
|
743 |
-
*/
|
744 |
-
$args = apply_filters( 'exactdn_pre_args', array( 'test' => 'lazy-test' ), $src, null );
|
745 |
-
if ( empty( $args ) ) {
|
746 |
-
$srcset_fill = false;
|
747 |
-
}
|
748 |
-
// Support Lazy Load plugins.
|
749 |
-
// Don't modify $tag yet as we need unmodified version later.
|
750 |
-
$lazy_load_src = $this->get_attribute( $images['img_tag'][ $index ], 'data-lazy-src' );
|
751 |
-
if ( $lazy_load_src ) {
|
752 |
-
$placeholder_src = $src;
|
753 |
-
$placeholder_src_orig = $src;
|
754 |
-
$src = $lazy_load_src;
|
755 |
-
$src_orig = $lazy_load_src;
|
756 |
-
$this->srcset_attr = 'data-lazy-srcset';
|
757 |
-
$lazy = true;
|
758 |
-
$srcset_fill = true;
|
759 |
-
}
|
760 |
-
// Must be a legacy Jetpack thing as far as I can tell, no matches found in any currently installed plugins.
|
761 |
-
$lazy_load_src = $this->get_attribute( $images['img_tag'][ $index ], 'data-lazy-original' );
|
762 |
-
if ( ! $lazy && $lazy_load_src ) {
|
763 |
-
$placeholder_src = $src;
|
764 |
-
$placeholder_src_orig = $src;
|
765 |
-
$src = $lazy_load_src;
|
766 |
-
$src_orig = $lazy_load_src;
|
767 |
-
$lazy = true;
|
768 |
-
}
|
769 |
-
if ( ! $lazy && strpos( $images['img_tag'][ $index ], 'a3-lazy-load/assets/images/lazy_placeholder' ) ) {
|
770 |
-
$lazy_load_src = $this->get_attribute( $images['img_tag'][ $index ], 'data-src' );
|
771 |
-
}
|
772 |
-
if (
|
773 |
-
! $lazy &&
|
774 |
-
strpos( $images['img_tag'][ $index ], ' data-src=' ) &&
|
775 |
-
strpos( $images['img_tag'][ $index ], 'lazyload' ) &&
|
776 |
-
(
|
777 |
-
strpos( $images['img_tag'][ $index ], 'data:image/gif' ) ||
|
778 |
-
strpos( $images['img_tag'][ $index ], 'data:image/svg' )
|
779 |
-
)
|
780 |
-
) {
|
781 |
-
$lazy_load_src = $this->get_attribute( $images['img_tag'][ $index ], 'data-src' );
|
782 |
-
ewwwio_debug_message( "found ewwwio ll src: $lazy_load_src" );
|
783 |
-
}
|
784 |
-
if ( ! $lazy && $lazy_load_src ) {
|
785 |
-
$placeholder_src = $src;
|
786 |
-
$placeholder_src_orig = $src;
|
787 |
-
$src = $lazy_load_src;
|
788 |
-
$src_orig = $lazy_load_src;
|
789 |
-
$this->srcset_attr = 'data-srcset';
|
790 |
-
$lazy = true;
|
791 |
-
$srcset_fill = true;
|
792 |
-
}
|
793 |
-
if ( ! $lazy && strpos( $images['img_tag'][ $index ], 'revslider/admin/assets/images/dummy' ) ) {
|
794 |
-
$lazy_load_src = $this->get_attribute( $images['img_tag'][ $index ], 'data-lazyload' );
|
795 |
-
}
|
796 |
-
if ( ! $lazy && $lazy_load_src ) {
|
797 |
-
$placeholder_src = $src;
|
798 |
-
$placeholder_src_orig = $src;
|
799 |
-
$src = $lazy_load_src;
|
800 |
-
$src_orig = $lazy_load_src;
|
801 |
-
$lazy = true;
|
802 |
-
}
|
803 |
|
804 |
-
|
805 |
-
|
806 |
-
'/' === substr( $src, 0, 1 ) &&
|
807 |
-
'/' !== substr( $src, 1, 1 ) &&
|
808 |
-
false === strpos( $this->upload_domain, 'amazonaws.com' ) &&
|
809 |
-
false === strpos( $this->upload_domain, 'digitaloceanspaces.com' )
|
810 |
-
) {
|
811 |
-
$src = '//' . $this->upload_domain . $src;
|
812 |
-
}
|
813 |
|
814 |
-
|
815 |
-
|
816 |
-
|
817 |
-
|
818 |
-
|
819 |
-
|
820 |
-
|
821 |
-
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
if (
|
827 |
-
|
828 |
-
$height = false;
|
829 |
}
|
830 |
|
831 |
-
|
832 |
-
if ( preg_match( '#class=["|\']?[^"\']*size-([^"\'\s]+)[^"\']*["|\']?#i', $images['img_tag'][ $index ], $size ) ) {
|
833 |
-
$size = array_pop( $size );
|
834 |
|
835 |
-
|
836 |
-
|
837 |
-
|
838 |
-
$height = (int) $image_sizes[ $size ]['height'];
|
839 |
-
$transform = $image_sizes[ $size ]['crop'] ? 'resize' : 'fit';
|
840 |
-
}
|
841 |
-
} else {
|
842 |
-
unset( $size );
|
843 |
}
|
844 |
|
845 |
-
|
846 |
-
if (
|
847 |
-
$
|
848 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
849 |
}
|
850 |
-
//
|
851 |
-
$
|
852 |
-
if (
|
853 |
-
|
854 |
-
|
|
|
|
|
|
|
855 |
}
|
856 |
-
if ( !
|
857 |
-
|
858 |
-
$attachment_id = attachment_url_to_postid( $src );
|
859 |
}
|
860 |
-
if (
|
861 |
-
|
862 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
863 |
}
|
864 |
-
|
865 |
-
|
866 |
-
|
867 |
-
|
868 |
-
|
869 |
-
|
870 |
-
|
871 |
-
|
872 |
-
|
873 |
-
|
874 |
-
|
875 |
-
|
876 |
-
|
877 |
-
|
878 |
-
|
879 |
-
|
880 |
-
|
881 |
-
|
882 |
-
|
883 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
884 |
$src_per_wp = false;
|
885 |
}
|
886 |
-
} else {
|
887 |
-
$src_per_wp = false;
|
888 |
}
|
889 |
-
}
|
890 |
|
891 |
-
|
892 |
-
|
893 |
-
|
894 |
-
|
895 |
-
|
896 |
-
|
897 |
-
|
898 |
|
899 |
-
|
900 |
-
|
901 |
-
|
902 |
-
|
903 |
-
|
904 |
-
|
905 |
|
906 |
-
|
907 |
-
|
908 |
-
|
909 |
-
|
910 |
-
|
911 |
-
|
912 |
-
|
913 |
-
|
914 |
-
|
915 |
-
|
|
|
916 |
}
|
|
|
|
|
|
|
917 |
}
|
918 |
-
} else {
|
919 |
-
unset( $attachment_id );
|
920 |
-
unset( $attachment );
|
921 |
}
|
922 |
}
|
923 |
-
|
924 |
-
|
925 |
-
|
926 |
-
$
|
927 |
-
|
928 |
-
$constrain_width = (int) apply_filters( 'exactdn_wide_align_image_width', max( 1500, $content_width ) );
|
929 |
-
}
|
930 |
-
// If width is available, constrain to $content_width.
|
931 |
-
if ( false !== $width && false === strpos( $width, '%' ) && is_numeric( $constrain_width ) ) {
|
932 |
-
if ( $width > $constrain_width && false !== $height && false === strpos( $height, '%' ) ) {
|
933 |
-
ewwwio_debug_message( 'constraining to content width' );
|
934 |
-
$height = round( ( $constrain_width * $height ) / $width );
|
935 |
-
$width = $constrain_width;
|
936 |
-
} elseif ( $width > $constrain_width ) {
|
937 |
-
ewwwio_debug_message( 'constraining to content width' );
|
938 |
-
$width = $constrain_width;
|
939 |
}
|
940 |
-
|
941 |
-
|
942 |
-
|
943 |
-
|
944 |
-
|
945 |
-
|
946 |
-
|
947 |
-
|
948 |
-
|
|
|
949 |
}
|
950 |
-
}
|
951 |
|
952 |
-
|
953 |
-
|
954 |
-
$
|
955 |
-
|
956 |
|
957 |
-
|
958 |
-
|
|
|
|
|
959 |
|
960 |
-
|
961 |
-
|
962 |
-
|
963 |
-
|
964 |
-
} elseif ( false !== $height ) {
|
965 |
-
$args['h'] = $height;
|
966 |
-
}
|
967 |
|
968 |
-
|
969 |
-
ewwwio_debug_message( 'preventing resize' );
|
970 |
$args = array();
|
971 |
-
} elseif ( ! $fullsize_url ) {
|
972 |
-
// Build URL, first maybe removing WP's resized string so we pass the original image to ExactDN (for higher quality).
|
973 |
-
$src = $this->strip_image_dimensions_maybe( $src );
|
974 |
-
}
|
975 |
-
|
976 |
-
if ( ! ewww_image_optimizer_get_option( 'exactdn_prevent_db_queries' ) && ! empty( $attachment_id ) ) {
|
977 |
-
ewwwio_debug_message( 'using attachment id to check smart crop' );
|
978 |
-
$args = $this->maybe_smart_crop( $args, $attachment_id );
|
979 |
-
}
|
980 |
-
|
981 |
-
/**
|
982 |
-
* Filter the array of ExactDN arguments added to an image.
|
983 |
-
* By default, only includes width and height values.
|
984 |
-
*
|
985 |
-
* @param array $args Array of ExactDN Arguments.
|
986 |
-
* @param array $args {
|
987 |
-
* Array of image details.
|
988 |
-
*
|
989 |
-
* @type $tag Image tag (Image HTML output).
|
990 |
-
* @type $src Image URL.
|
991 |
-
* @type $src_orig Original Image URL.
|
992 |
-
* @type $width Image width.
|
993 |
-
* @type $height Image height.
|
994 |
-
* }
|
995 |
-
*/
|
996 |
-
$args = apply_filters( 'exactdn_post_image_args', $args, compact( 'tag', 'src', 'src_orig', 'width', 'height' ) );
|
997 |
-
ewwwio_debug_message( "width $width" );
|
998 |
-
ewwwio_debug_message( "height $height" );
|
999 |
-
ewwwio_debug_message( "transform $transform" );
|
1000 |
|
1001 |
-
|
1002 |
-
|
|
|
|
|
|
|
|
|
|
|
1003 |
|
1004 |
-
|
1005 |
-
|
1006 |
-
|
1007 |
-
$
|
|
|
|
|
|
|
1008 |
|
1009 |
-
|
1010 |
-
|
1011 |
-
$
|
1012 |
}
|
1013 |
|
1014 |
-
|
1015 |
-
|
1016 |
-
|
1017 |
-
|
1018 |
-
|
1019 |
-
|
1020 |
-
|
1021 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1022 |
}
|
1023 |
-
}
|
1024 |
|
1025 |
-
|
1026 |
-
|
1027 |
-
|
1028 |
-
|
1029 |
-
|
1030 |
-
$
|
|
|
|
|
|
|
1031 |
}
|
1032 |
-
}
|
1033 |
|
1034 |
-
|
1035 |
-
|
1036 |
-
|
1037 |
-
|
1038 |
-
|
|
|
|
|
|
|
1039 |
|
1040 |
-
|
1041 |
-
|
1042 |
-
|
|
|
|
|
1043 |
|
1044 |
-
|
1045 |
-
|
1046 |
-
|
1047 |
|
1048 |
-
|
1049 |
-
|
|
|
1050 |
|
1051 |
-
|
1052 |
-
$content = str_replace( $tag, $new_tag, $content );
|
1053 |
-
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) && strpos( $content, $exactdn_url ) ) {
|
1054 |
-
ewwwio_debug_message( 'new image properly inserted' );
|
1055 |
-
} elseif ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
|
1056 |
-
ewwwio_debug_message( 'new url NOT found' );
|
1057 |
-
}
|
1058 |
-
}
|
1059 |
-
} elseif ( ! $lazy && $this->validate_image_url( $src, true ) ) {
|
1060 |
-
ewwwio_debug_message( "found a potential exactdn src url to insert into srcset: $src" );
|
1061 |
-
// Find the width attribute.
|
1062 |
-
$width = $this->get_img_width( $images['img_tag'][ $index ] );
|
1063 |
-
if ( $width ) {
|
1064 |
-
ewwwio_debug_message( 'found the width' );
|
1065 |
-
// Insert new image src into the srcset as well, if we have a width.
|
1066 |
-
if (
|
1067 |
-
false !== $width &&
|
1068 |
-
false === strpos( $width, '%' ) &&
|
1069 |
-
false !== strpos( $src, $width ) &&
|
1070 |
-
false !== strpos( $src, $this->exactdn_domain )
|
1071 |
-
) {
|
1072 |
-
$new_tag = $tag;
|
1073 |
-
$exactdn_url = $src;
|
1074 |
-
ewwwio_debug_message( 'checking to see if srcset width already exists' );
|
1075 |
-
$srcset_url = $exactdn_url . ' ' . (int) $width . 'w, ';
|
1076 |
-
$new_srcset_attr = $this->get_attribute( $new_tag, $this->srcset_attr );
|
1077 |
-
if ( $new_srcset_attr && false === strpos( $new_srcset_attr, ' ' . (int) $width . 'w' ) && ! preg_match( '/\s(1|2|3)x/', $new_srcset_attr ) ) {
|
1078 |
-
ewwwio_debug_message( 'src not in srcset, adding' );
|
1079 |
-
$this->set_attribute( $new_tag, $this->srcset_attr, $srcset_url . $new_srcset_attr, true );
|
1080 |
-
// Replace original tag with modified version.
|
1081 |
-
$content = str_replace( $tag, $new_tag, $content );
|
1082 |
}
|
1083 |
-
}
|
1084 |
-
}
|
1085 |
-
} elseif ( $lazy && ! empty( $placeholder_src ) && $this->validate_image_url( $placeholder_src ) ) {
|
1086 |
-
$new_tag = $tag;
|
1087 |
-
// If Lazy Load is in use, pass placeholder image through ExactDN.
|
1088 |
-
$placeholder_src = $this->generate_url( $placeholder_src );
|
1089 |
-
if ( $placeholder_src !== $placeholder_src_orig ) {
|
1090 |
-
$new_tag = str_replace( $placeholder_src_orig, str_replace( '&', '&', esc_url( $placeholder_src ) ), $new_tag );
|
1091 |
-
// Replace original tag with modified version.
|
1092 |
-
$content = str_replace( $tag, $new_tag, $content );
|
1093 |
-
}
|
1094 |
-
unset( $placeholder_src );
|
1095 |
-
} // End if().
|
1096 |
|
1097 |
-
|
1098 |
-
|
1099 |
-
$src = $exactdn_url;
|
1100 |
-
}
|
1101 |
-
if ( $srcset_fill && ( ! defined( 'EXACTDN_PREVENT_SRCSET_FILL' ) || ! EXACTDN_PREVENT_SRCSET_FILL ) && false !== strpos( $src, $this->exactdn_domain ) ) {
|
1102 |
-
if ( ! $this->get_attribute( $images['img_tag'][ $index ], $this->srcset_attr ) && ! $this->get_attribute( $images['img_tag'][ $index ], 'sizes' ) ) {
|
1103 |
-
ewwwio_debug_message( "srcset filling with $src" );
|
1104 |
-
$zoom = false;
|
1105 |
-
// If $width is empty, we'll search the url for a width param, then we try searching the img element, with fall back to the filename.
|
1106 |
-
if ( empty( $width ) || ! is_numeric( $width ) ) {
|
1107 |
-
// This only searches for w, resize, or fit flags, others are ignored.
|
1108 |
-
$width = $this->get_exactdn_width_from_url( $src );
|
1109 |
-
if ( $width ) {
|
1110 |
-
$zoom = true;
|
1111 |
-
}
|
1112 |
-
}
|
1113 |
-
if ( empty( $width ) || ! is_numeric( $width ) ) {
|
1114 |
-
$width = $this->get_img_width( $images['img_tag'][ $index ] );
|
1115 |
}
|
1116 |
-
|
1117 |
-
|
1118 |
-
|
1119 |
-
|
1120 |
-
if (
|
1121 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1122 |
}
|
1123 |
-
|
1124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
1125 |
}
|
1126 |
-
|
1127 |
-
|
1128 |
-
|
1129 |
-
|
1130 |
-
|
1131 |
-
|
1132 |
-
|
1133 |
-
|
1134 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1135 |
}
|
1136 |
}
|
1137 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1138 |
}
|
1139 |
-
} // End foreach().
|
1140 |
-
} // End if();
|
1141 |
-
$content = $this->filter_bg_images( $content );
|
1142 |
-
if ( $this->filtering_the_page ) {
|
1143 |
-
$content = $this->filter_prz_thumb( $content );
|
1144 |
-
}
|
1145 |
-
if ( $this->filtering_the_page && ewww_image_optimizer_get_option( 'exactdn_all_the_things' ) ) {
|
1146 |
-
ewwwio_debug_message( 'rewriting all other wp_content urls' );
|
1147 |
-
if ( $this->exactdn_domain && $this->upload_domain ) {
|
1148 |
-
$escaped_upload_domain = str_replace( '.', '\.', ltrim( $this->upload_domain, 'w.' ) );
|
1149 |
-
ewwwio_debug_message( $escaped_upload_domain );
|
1150 |
-
if ( ! empty( $this->user_exclusions ) ) {
|
1151 |
-
$content = preg_replace( '#(https?:)?//(?:www\.)?' . $escaped_upload_domain . '([^"\'?>]+?)?/wp-content/([^"\'?>]+?)?(' . implode( '|', $this->user_exclusions ) . ')#i', '$1//' . $this->upload_domain . '$2/?wpcontent-bypass?/$3$4', $content );
|
1152 |
-
}
|
1153 |
-
if ( strpos( $content, '<use ' ) ) {
|
1154 |
-
// Pre-empt rewriting of files within <use> tags, particularly to prevent security errors for SVGs.
|
1155 |
-
$content = preg_replace( '#(<use.+?href=["\'])(https?:)?//(?:www\.)?' . $escaped_upload_domain . '([^"\'?>]+?)/wp-content/#is', '$1$2//' . $this->upload_domain . '$3/?wpcontent-bypass?/', $content );
|
1156 |
-
}
|
1157 |
-
// Pre-empt rewriting of wp-includes and wp-content if the extension is not allowed by using a temporary placeholder.
|
1158 |
-
$content = preg_replace( '#(https?:)?//(?:www\.)?' . $escaped_upload_domain . '([^"\'?>]+?)?/wp-content/([^"\'?>]+?)\.(htm|html|php|ashx|m4v|mov|wvm|qt|webm|ogv|mp4|m4p|mpg|mpeg|mpv)#i', '$1//' . $this->upload_domain . '$2/?wpcontent-bypass?/$3.$4', $content );
|
1159 |
-
$content = str_replace( 'wp-content/themes/jupiter"', '?wpcontent-bypass?/themes/jupiter"', $content );
|
1160 |
-
$content = str_replace( 'wp-content/plugins/anti-captcha/', '?wpcontent-bypass?/plugins/anti-captcha', $content );
|
1161 |
-
if ( strpos( $this->upload_domain, 'amazonaws.com' ) || strpos( $this->upload_domain, 'digitaloceanspaces.com' ) ) {
|
1162 |
-
$content = preg_replace( '#(https?:)?//(?:www\.)?' . $escaped_upload_domain . $this->remove_path . '/#i', '$1//' . $this->exactdn_domain . '/', $content );
|
1163 |
-
} else {
|
1164 |
-
$content = preg_replace( '#(https?:)?//(?:www\.)?' . $escaped_upload_domain . '/([^"\'?>]+?)?(nextgen-image|wp-includes|wp-content)/#i', '$1//' . $this->exactdn_domain . '/$2$3/', $content );
|
1165 |
-
}
|
1166 |
-
$content = str_replace( '?wpcontent-bypass?', 'wp-content', $content );
|
1167 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1168 |
}
|
1169 |
-
ewwwio_debug_message( 'done parsing page' );
|
1170 |
-
$this->filtering_the_content = false;
|
1171 |
-
|
1172 |
-
$elapsed_time = microtime( true ) - $started;
|
1173 |
-
ewwwio_debug_message( "parsing the_content took $elapsed_time seconds" );
|
1174 |
-
$this->elapsed_time += microtime( true ) - $started;
|
1175 |
-
ewwwio_debug_message( "parsing the page took $this->elapsed_time seconds so far" );
|
1176 |
-
if ( ! ewww_image_optimizer_get_option( 'exactdn_prevent_db_queries' ) && $this->elapsed_time > .5 ) {
|
1177 |
-
ewww_image_optimizer_set_option( 'exactdn_prevent_db_queries', true );
|
1178 |
-
}
|
1179 |
-
return $content;
|
1180 |
-
}
|
1181 |
|
1182 |
-
|
1183 |
-
|
1184 |
-
|
1185 |
-
|
1186 |
-
|
1187 |
-
|
1188 |
-
|
1189 |
-
|
1190 |
-
|
1191 |
-
|
1192 |
-
|
1193 |
-
|
1194 |
-
|
1195 |
-
|
1196 |
-
|
1197 |
-
|
1198 |
-
|
1199 |
-
|
1200 |
-
|
1201 |
-
|
1202 |
-
}
|
1203 |
-
$style = $this->get_attribute( $div, 'style' );
|
1204 |
-
if ( empty( $style ) ) {
|
1205 |
-
continue;
|
1206 |
-
}
|
1207 |
-
ewwwio_debug_message( "checking style attr for background-image: $style" );
|
1208 |
-
$bg_image_url = $this->get_background_image_url( $style );
|
1209 |
-
if ( $this->validate_image_url( $bg_image_url ) ) {
|
1210 |
-
/** This filter is already documented in class-exactdn.php */
|
1211 |
-
if ( apply_filters( 'exactdn_skip_image', false, $bg_image_url, $div ) ) {
|
1212 |
continue;
|
1213 |
}
|
1214 |
-
$
|
1215 |
-
|
1216 |
-
|
1217 |
-
$args['w'] = apply_filters( 'exactdn_full_align_bgimage_width', 1920, $bg_image_url );
|
1218 |
-
} elseif ( false !== strpos( $div_class, 'alignwide' ) && current_theme_supports( 'align-wide' ) ) {
|
1219 |
-
$args['w'] = apply_filters( 'exactdn_wide_align_bgimage_width', 1500, $bg_image_url );
|
1220 |
-
} elseif ( $content_width ) {
|
1221 |
-
$args['w'] = apply_filters( 'exactdn_content_bgimage_width', $content_width, $bg_image_url );
|
1222 |
}
|
1223 |
-
|
1224 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1225 |
}
|
1226 |
-
|
1227 |
-
|
1228 |
-
$new_style = str_replace( $bg_image_url, $exactdn_bg_image_url, $style );
|
1229 |
-
$div = str_replace( $style, $new_style, $div );
|
1230 |
}
|
1231 |
}
|
1232 |
-
if ( $div !== $divs[ $index ] ) {
|
1233 |
-
$content = str_replace( $divs[ $index ], $div, $content );
|
1234 |
-
}
|
1235 |
}
|
1236 |
-
}
|
1237 |
-
return $content;
|
1238 |
-
}
|
1239 |
-
|
1240 |
-
/**
|
1241 |
-
* Parse page content looking for thumburl from personalization.com.
|
1242 |
-
*
|
1243 |
-
* @param string $content The HTML content to parse.
|
1244 |
-
* @return string The filtered HTML content.
|
1245 |
-
*/
|
1246 |
-
function filter_prz_thumb( $content ) {
|
1247 |
-
if ( ! class_exists( 'WooCommerce' ) || false === strpos( $content, 'productDetailsForPrz' ) ) {
|
1248 |
return $content;
|
1249 |
}
|
1250 |
-
|
1251 |
-
|
1252 |
-
|
1253 |
-
|
1254 |
-
|
1255 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1256 |
}
|
|
|
1257 |
}
|
1258 |
-
return $content;
|
1259 |
-
}
|
1260 |
|
1261 |
-
|
1262 |
-
|
1263 |
-
|
1264 |
-
|
1265 |
-
|
1266 |
-
|
1267 |
-
|
1268 |
-
|
1269 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1270 |
return $allow;
|
1271 |
}
|
1272 |
-
if ( ! empty( $_POST['action'] ) && 'eddvbugm_viewport_downloads' === $_POST['action'] ) {
|
1273 |
-
return true;
|
1274 |
-
}
|
1275 |
-
if ( ! empty( $_POST['action'] ) && 'vc_get_vc_grid_data' === $_POST['action'] ) {
|
1276 |
-
return true;
|
1277 |
-
}
|
1278 |
-
if ( ! empty( $_POST['action'] ) && 'Essential_Grid_Front_request_ajax' === $_POST['action'] ) {
|
1279 |
-
return true;
|
1280 |
-
}
|
1281 |
-
if ( ! empty( $_POST['action'] ) && 'mabel-rpn-getnew-purchased-products' === $_POST['action'] ) {
|
1282 |
-
return true;
|
1283 |
-
}
|
1284 |
-
return $allow;
|
1285 |
-
}
|
1286 |
|
1287 |
-
|
1288 |
-
|
1289 |
-
|
1290 |
-
|
1291 |
-
|
1292 |
-
|
1293 |
-
|
1294 |
-
|
1295 |
-
|
1296 |
-
|
1297 |
-
|
1298 |
|
1299 |
-
|
1300 |
-
|
1301 |
-
|
1302 |
-
|
1303 |
-
|
1304 |
-
|
1305 |
|
1306 |
-
|
1307 |
-
|
1308 |
-
|
1309 |
-
|
1310 |
-
|
1311 |
-
|
1312 |
-
|
1313 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
1314 |
return $exactdn_args;
|
1315 |
}
|
1316 |
-
if ( ! empty( $exactdn_args['resize'] ) ) {
|
1317 |
-
$exactdn_args['fit'] = $exactdn_args['resize'];
|
1318 |
-
unset( $exactdn_args['resize'] );
|
1319 |
-
}
|
1320 |
-
return $exactdn_args;
|
1321 |
-
}
|
1322 |
|
1323 |
-
|
1324 |
-
|
1325 |
-
|
1326 |
-
|
1327 |
-
|
1328 |
-
|
1329 |
-
|
1330 |
-
|
1331 |
-
|
1332 |
-
|
1333 |
-
|
1334 |
-
|
1335 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1336 |
|
1337 |
-
// Don't foul up the admin side of things, unless a plugin wants to.
|
1338 |
-
if ( is_admin() &&
|
1339 |
/**
|
1340 |
-
* Provide plugins a way of
|
1341 |
-
*
|
1342 |
-
* Note: enabling this will result in ExactDN URLs added to your post content, which could make migrations across domains (and off ExactDN) a bit more challenging.
|
1343 |
*
|
1344 |
-
* @param bool false
|
1345 |
* @param array $args {
|
1346 |
* Array of image details.
|
1347 |
*
|
1348 |
-
* @type
|
1349 |
* @type int $attachment_id Attachment ID of the image.
|
1350 |
* @type array|string $size Image size. Can be a string (name of the image size, e.g. full) or an array of height and width.
|
1351 |
* }
|
1352 |
*/
|
1353 |
-
|
1354 |
-
|
1355 |
-
|
1356 |
-
}
|
1357 |
|
1358 |
-
|
1359 |
-
|
1360 |
-
|
1361 |
-
|
1362 |
-
* @param array $args {
|
1363 |
-
* Array of image details.
|
1364 |
-
*
|
1365 |
-
* @type string|bool $image Image URL or false.
|
1366 |
-
* @type int $attachment_id Attachment ID of the image.
|
1367 |
-
* @type array|string $size Image size. Can be a string (name of the image size, e.g. full) or an array of height and width.
|
1368 |
-
* }
|
1369 |
-
*/
|
1370 |
-
if ( apply_filters( 'exactdn_override_image_downsize', false, compact( 'image', 'attachment_id', 'size' ) ) ) {
|
1371 |
-
return $image;
|
1372 |
-
}
|
1373 |
|
1374 |
-
|
1375 |
-
|
1376 |
-
|
1377 |
-
}
|
1378 |
-
|
1379 |
-
if ( $this->filtering_the_content || $this->filtering_the_page ) {
|
1380 |
-
ewwwio_debug_message( 'end image_downsize early' );
|
1381 |
-
return $image;
|
1382 |
-
}
|
1383 |
-
|
1384 |
-
// Get the image URL and proceed with ExactDN replacement if successful.
|
1385 |
-
$image_url = wp_get_attachment_url( $attachment_id );
|
1386 |
-
/** This filter is already documented in class-exactdn.php */
|
1387 |
-
if ( apply_filters( 'exactdn_skip_image', false, $image_url, null ) ) {
|
1388 |
-
return $image;
|
1389 |
-
}
|
1390 |
-
ewwwio_debug_message( $image_url );
|
1391 |
-
ewwwio_debug_message( $attachment_id );
|
1392 |
-
if ( is_string( $size ) || is_int( $size ) ) {
|
1393 |
-
ewwwio_debug_message( $size );
|
1394 |
-
} elseif ( is_array( $size ) ) {
|
1395 |
-
foreach ( $size as $dimension ) {
|
1396 |
-
ewwwio_debug_message( 'dimension: ' . $dimension );
|
1397 |
}
|
1398 |
-
}
|
1399 |
-
// Set this to true later when we know we have size meta.
|
1400 |
-
$has_size_meta = false;
|
1401 |
|
1402 |
-
|
1403 |
-
|
1404 |
-
|
|
|
1405 |
return $image;
|
1406 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1407 |
|
1408 |
-
|
1409 |
-
|
|
|
|
|
|
|
1410 |
|
1411 |
-
|
1412 |
-
|
1413 |
-
$image_args = $this->image_sizes();
|
1414 |
-
$image_args = $image_args[ $size ];
|
1415 |
-
ewwwio_debug_message( "image args for $size: " . ewwwio_implode( ',', $image_args ) );
|
1416 |
|
1417 |
-
|
|
|
|
|
|
|
|
|
1418 |
|
1419 |
-
|
1420 |
|
1421 |
-
|
1422 |
-
if ( 'full' === $size ) {
|
1423 |
-
$image_meta = wp_get_attachment_metadata( $attachment_id );
|
1424 |
-
$intermediate = false;
|
1425 |
-
} elseif ( ! $image_meta ) {
|
1426 |
-
ewwwio_debug_message( 'still do not have meta, getting it now' );
|
1427 |
-
// If we still don't have any image meta at this point, it's probably from a custom thumbnail size
|
1428 |
-
// for an image that was uploaded before the custom image was added to the theme. Try to determine the size manually.
|
1429 |
-
$image_meta = wp_get_attachment_metadata( $attachment_id );
|
1430 |
|
1431 |
-
|
1432 |
-
|
1433 |
-
|
1434 |
-
|
1435 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1436 |
}
|
1437 |
}
|
1438 |
-
|
1439 |
-
|
1440 |
-
|
1441 |
-
$image_args['height'] = $image_meta['height'];
|
1442 |
-
|
1443 |
-
// NOTE: it will constrain an image to $content_width which is expected behavior in core, so far as I can see.
|
1444 |
-
list( $image_args['width'], $image_args['height'] ) = image_constrain_size_for_editor( $image_args['width'], $image_args['height'], $size, 'display' );
|
1445 |
-
|
1446 |
-
$has_size_meta = true;
|
1447 |
-
ewwwio_debug_message( 'image args constrained: ' . ewwwio_implode( ',', $image_args ) );
|
1448 |
-
}
|
1449 |
|
1450 |
-
|
|
|
1451 |
|
1452 |
-
|
1453 |
-
|
1454 |
-
if ( ! $image_args['width'] && 0 < $image_args['height'] ) {
|
1455 |
-
$exactdn_args['h'] = $image_args['height'];
|
1456 |
-
} elseif ( ! $image_args['height'] && 0 < $image_args['width'] ) {
|
1457 |
-
$exactdn_args['w'] = $image_args['width'];
|
1458 |
}
|
1459 |
-
} else {
|
1460 |
-
if ( ! isset( $image_meta['sizes'] ) ) {
|
1461 |
-
$size_meta = $image_meta;
|
1462 |
-
// Because we don't have the "real" meta, just the height/width for the specific size.
|
1463 |
-
ewwwio_debug_message( 'getting attachment meta now' );
|
1464 |
-
$image_meta = wp_get_attachment_metadata( $attachment_id );
|
1465 |
-
}
|
1466 |
-
if ( 'resize' === $transform && $image_meta && isset( $image_meta['width'], $image_meta['height'] ) ) {
|
1467 |
-
// Lets make sure that we don't upscale images since wp never upscales them as well.
|
1468 |
-
$smaller_width = ( ( $image_meta['width'] < $image_args['width'] ) ? $image_meta['width'] : $image_args['width'] );
|
1469 |
-
$smaller_height = ( ( $image_meta['height'] < $image_args['height'] ) ? $image_meta['height'] : $image_args['height'] );
|
1470 |
|
1471 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1472 |
} else {
|
1473 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1474 |
}
|
1475 |
-
}
|
1476 |
|
1477 |
-
|
1478 |
-
|
1479 |
-
|
1480 |
-
|
1481 |
-
|
1482 |
-
|
1483 |
-
|
1484 |
-
|
1485 |
-
|
1486 |
-
|
1487 |
-
}
|
1488 |
-
if ( ! empty( $image_meta['sizes'] ) && 'full' !== $size && ! empty( $image_meta['sizes'][ $size ]['file'] ) ) {
|
1489 |
-
$image_url_basename = wp_basename( $image_url );
|
1490 |
-
$intermediate_url = str_replace( $image_url_basename, $image_meta['sizes'][ $size ]['file'], $image_url );
|
1491 |
-
|
1492 |
-
if ( empty( $image_meta['width'] ) || empty( $image_meta['height'] ) ) {
|
1493 |
-
list( $filename_width, $filename_height ) = $this->get_dimensions_from_filename( $intermediate_url );
|
1494 |
}
|
1495 |
-
|
1496 |
-
|
1497 |
-
|
1498 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1499 |
} else {
|
1500 |
$resize_existing = true;
|
1501 |
}
|
1502 |
-
} else {
|
1503 |
-
$resize_existing = true;
|
1504 |
-
}
|
1505 |
-
|
1506 |
-
$exactdn_args = $resize_existing && 'full' !== $size ? $this->maybe_smart_crop( $exactdn_args, $attachment_id, $image_meta ) : array();
|
1507 |
|
1508 |
-
|
1509 |
-
* Filter the ExactDN arguments added to an image, when that image size is a string.
|
1510 |
-
* Image size will be a string (e.g. "full", "medium") when it is known to WordPress.
|
1511 |
-
*
|
1512 |
-
* @param array $exactdn_args ExactDN arguments.
|
1513 |
-
* @param array $args {
|
1514 |
-
* Array of image details.
|
1515 |
-
*
|
1516 |
-
* @type array $image_args Image arguments (width, height, crop).
|
1517 |
-
* @type string $image_url Image URL.
|
1518 |
-
* @type int $attachment_id Attachment ID of the image.
|
1519 |
-
* @type string $size Image size name.
|
1520 |
-
* @type string $transform Value can be resize or fit.
|
1521 |
-
* }
|
1522 |
-
*/
|
1523 |
-
$exactdn_args = apply_filters( 'exactdn_image_downsize_string', $exactdn_args, compact( 'image_args', 'image_url', 'attachment_id', 'size', 'transform' ) );
|
1524 |
-
|
1525 |
-
// Generate ExactDN URL.
|
1526 |
-
$image = array(
|
1527 |
-
$this->generate_url( $image_url, $exactdn_args ),
|
1528 |
-
$has_size_meta ? $image_args['width'] : false,
|
1529 |
-
$has_size_meta ? $image_args['height'] : false,
|
1530 |
-
$intermediate,
|
1531 |
-
);
|
1532 |
-
} elseif ( is_array( $size ) ) {
|
1533 |
-
// Pull width and height values from the provided array, if possible.
|
1534 |
-
$width = isset( $size[0] ) ? (int) $size[0] : false;
|
1535 |
-
$height = isset( $size[1] ) ? (int) $size[1] : false;
|
1536 |
|
1537 |
-
|
1538 |
-
|
1539 |
-
|
1540 |
-
|
1541 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1542 |
|
1543 |
-
|
1544 |
-
|
1545 |
-
|
1546 |
|
1547 |
-
|
1548 |
-
|
1549 |
-
|
1550 |
-
|
1551 |
-
|
1552 |
-
|
1553 |
-
|
1554 |
-
|
|
|
|
|
1555 |
}
|
1556 |
-
$has_size_meta = true;
|
1557 |
-
}
|
1558 |
|
1559 |
-
|
1560 |
-
|
1561 |
|
1562 |
-
|
1563 |
-
|
1564 |
-
|
1565 |
-
|
1566 |
|
1567 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1568 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1569 |
/**
|
1570 |
-
*
|
1571 |
*
|
1572 |
-
* @param
|
1573 |
* @param array $args {
|
1574 |
* Array of image details.
|
1575 |
*
|
1576 |
-
* @type
|
1577 |
-
* @type int
|
1578 |
-
* @type string $image_url Image URL.
|
1579 |
-
* @type int $attachment_id Attachment ID of the image.
|
1580 |
* }
|
1581 |
*/
|
1582 |
-
|
1583 |
-
|
1584 |
-
|
1585 |
-
$image = array(
|
1586 |
-
$this->generate_url( $image_url, $exactdn_args ),
|
1587 |
-
$has_size_meta ? $width : false,
|
1588 |
-
$has_size_meta ? $height : false,
|
1589 |
-
$intermediate,
|
1590 |
-
);
|
1591 |
}
|
1592 |
-
}
|
1593 |
-
if ( ! empty( $image[0] ) && is_string( $image[0] ) ) {
|
1594 |
-
ewwwio_debug_message( $image[0] );
|
1595 |
-
}
|
1596 |
-
ewwwio_debug_message( 'end image_downsize' );
|
1597 |
-
$elapsed_time = microtime( true ) - $started;
|
1598 |
-
ewwwio_debug_message( "parsing image_downsize took $elapsed_time seconds" );
|
1599 |
-
$this->elapsed_time += microtime( true ) - $started;
|
1600 |
-
return $image;
|
1601 |
-
}
|
1602 |
-
|
1603 |
-
/**
|
1604 |
-
* Filters an array of image `srcset` values, replacing each URL with its ExactDN equivalent.
|
1605 |
-
*
|
1606 |
-
* @param array $sources An array of image urls and widths.
|
1607 |
-
* @param array $size_array Array of width and height values in pixels.
|
1608 |
-
* @param string $image_src The 'src' of the image.
|
1609 |
-
* @param array $image_meta The image metadata as returned by 'wp_get_attachment_metadata()'.
|
1610 |
-
* @param int $attachment_id Image attachment ID or 0.
|
1611 |
-
* @uses this::validate_image_url, this::generate_url, this::parse_from_filename
|
1612 |
-
* @uses this::strip_image_dimensions_maybe, this::get_content_width
|
1613 |
-
* @return array An array of ExactDN image urls and widths.
|
1614 |
-
*/
|
1615 |
-
public function filter_srcset_array( $sources = array(), $size_array = array(), $image_src = '', $image_meta = array(), $attachment_id = 0 ) {
|
1616 |
-
$started = microtime( true );
|
1617 |
-
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
1618 |
-
// Don't foul up the admin side of things, unless a plugin wants to.
|
1619 |
-
if ( is_admin() &&
|
1620 |
-
/**
|
1621 |
-
* Provide plugins a way of running ExactDN for images in the WordPress Dashboard (wp-admin).
|
1622 |
-
*
|
1623 |
-
* @param bool false Stop ExactDN from being run on the Dashboard. Default to false, use true to run in wp-admin.
|
1624 |
-
* @param array $args {
|
1625 |
-
* Array of image details.
|
1626 |
-
*
|
1627 |
-
* @type string|bool $image Image URL or false.
|
1628 |
-
* @type int $attachment_id Attachment ID of the image.
|
1629 |
-
* }
|
1630 |
-
*/
|
1631 |
-
false === apply_filters( 'exactdn_admin_allow_image_srcset', false, compact( 'image_src', 'attachment_id' ) )
|
1632 |
-
) {
|
1633 |
-
return $sources;
|
1634 |
-
}
|
1635 |
-
|
1636 |
-
if ( ! is_array( $sources ) ) {
|
1637 |
-
return $sources;
|
1638 |
-
}
|
1639 |
|
1640 |
-
|
1641 |
-
|
1642 |
-
$w_descriptor = true;
|
1643 |
-
|
1644 |
-
foreach ( $sources as $i => $source ) {
|
1645 |
-
if ( 'x' === $source['descriptor'] ) {
|
1646 |
-
$w_descriptor = false;
|
1647 |
-
}
|
1648 |
-
if ( ! $this->validate_image_url( $source['url'] ) ) {
|
1649 |
-
continue;
|
1650 |
}
|
1651 |
|
1652 |
-
|
1653 |
-
|
1654 |
-
|
1655 |
-
}
|
1656 |
|
1657 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
1658 |
|
1659 |
-
|
1660 |
-
|
1661 |
-
|
1662 |
-
|
1663 |
-
|
1664 |
-
|
1665 |
|
1666 |
-
|
1667 |
-
if (
|
1668 |
-
(
|
1669 |
-
) {
|
1670 |
-
ewwwio_debug_message( "preventing further processing for (detected) full-size $url" );
|
1671 |
$sources[ $i ]['url'] = $this->generate_url( $source['url'] );
|
1672 |
continue;
|
1673 |
}
|
1674 |
-
}
|
1675 |
|
1676 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1677 |
|
1678 |
-
|
1679 |
-
if ( ! empty( $attachment_id ) ) {
|
1680 |
-
$url = wp_get_attachment_url( $attachment_id );
|
1681 |
-
} else {
|
1682 |
-
$url = $this->strip_image_dimensions_maybe( $url );
|
1683 |
-
}
|
1684 |
-
ewwwio_debug_message( "building srcs from $url" );
|
1685 |
|
1686 |
-
|
1687 |
-
|
1688 |
-
|
1689 |
-
$args['resize'] = $width . ',' . $height;
|
1690 |
} else {
|
1691 |
-
$
|
1692 |
}
|
1693 |
-
|
1694 |
|
1695 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1696 |
|
1697 |
-
|
1698 |
-
}
|
1699 |
|
1700 |
-
|
1701 |
-
|
1702 |
-
* Now, we're going to construct additional sizes based on multiples of the content_width.
|
1703 |
-
*/
|
1704 |
|
1705 |
-
|
1706 |
-
|
1707 |
-
|
1708 |
-
|
1709 |
-
* @param array|bool $multipliers Array of multipliers to use or false to bypass.
|
1710 |
-
*/
|
1711 |
-
$multipliers = apply_filters( 'exactdn_srcset_multipliers', array( .2, .4, .6, .8, 1, 2, 3, 1920 ) );
|
1712 |
-
$url = trailingslashit( $upload_dir['baseurl'] ) . $image_meta['file'];
|
1713 |
-
if ( ! $w_descriptor ) {
|
1714 |
-
ewwwio_debug_message( 'using x descriptors instead of w' );
|
1715 |
-
$multipliers = array_filter( $multipliers, 'is_int' );
|
1716 |
-
}
|
1717 |
|
1718 |
-
|
1719 |
-
|
1720 |
-
|
1721 |
-
|
1722 |
-
|
1723 |
-
|
1724 |
-
|
1725 |
-
|
1726 |
-
|
1727 |
-
|
1728 |
-
|
1729 |
-
) {
|
1730 |
-
|
1731 |
-
$fullwidth = $image_meta['width'];
|
1732 |
-
$fullheight = $image_meta['height'];
|
1733 |
-
$reqwidth = $size_array[0];
|
1734 |
-
$reqheight = $size_array[1];
|
1735 |
-
ewwwio_debug_message( "filling additional sizes with requested w $reqwidth h $reqheight full w $fullwidth full h $fullheight" );
|
1736 |
-
|
1737 |
-
$constrained_size = wp_constrain_dimensions( $fullwidth, $fullheight, $reqwidth );
|
1738 |
-
$expected_size = array( $reqwidth, $reqheight );
|
1739 |
-
|
1740 |
-
ewwwio_debug_message( $constrained_size[0] );
|
1741 |
-
ewwwio_debug_message( $constrained_size[1] );
|
1742 |
-
if ( abs( $constrained_size[0] - $expected_size[0] ) <= 1 && abs( $constrained_size[1] - $expected_size[1] ) <= 1 ) {
|
1743 |
-
ewwwio_debug_message( 'soft cropping' );
|
1744 |
-
$crop = 'soft';
|
1745 |
-
$base = $this->get_content_width(); // Provide a default width if none set by the theme.
|
1746 |
-
} else {
|
1747 |
-
ewwwio_debug_message( 'hard cropping' );
|
1748 |
-
$crop = 'hard';
|
1749 |
-
$base = $reqwidth;
|
1750 |
}
|
1751 |
-
ewwwio_debug_message( "base width: $base" );
|
1752 |
|
1753 |
-
|
1754 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1755 |
|
1756 |
-
|
|
|
1757 |
|
1758 |
-
|
1759 |
-
|
1760 |
-
$newwidth =
|
1761 |
-
if (
|
1762 |
-
|
|
|
|
|
|
|
1763 |
}
|
1764 |
-
|
1765 |
-
|
1766 |
-
continue;
|
1767 |
-
}
|
1768 |
-
foreach ( $currentwidths as $currentwidth ) {
|
1769 |
-
// If a new width would be within 50 pixels of an existing one or larger than the full size image, skip.
|
1770 |
-
if ( abs( $currentwidth - $newwidth ) < 50 || ( $newwidth > $fullwidth ) ) {
|
1771 |
-
continue 2; // Back to the foreach ( $multipliers as $multiplier ).
|
1772 |
}
|
1773 |
-
|
1774 |
-
|
1775 |
-
|
1776 |
-
|
1777 |
-
|
1778 |
-
$
|
1779 |
-
'w' => $newwidth,
|
1780 |
-
);
|
1781 |
-
} else { // hard crop, e.g. add_image_size( 'example', 200, 200, true ).
|
1782 |
-
$args = array(
|
1783 |
-
'zoom' => $multiplier,
|
1784 |
-
'resize' => $reqwidth . ',' . $reqheight,
|
1785 |
-
);
|
1786 |
-
}
|
1787 |
-
|
1788 |
-
$args = $this->maybe_smart_crop( $args, $attachment_id, $image_meta );
|
1789 |
|
1790 |
-
|
1791 |
-
|
1792 |
-
|
1793 |
-
|
1794 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1795 |
|
1796 |
-
|
1797 |
-
} // foreach ( $multipliers as $multiplier )
|
1798 |
|
1799 |
-
|
1800 |
-
|
1801 |
-
|
1802 |
-
|
1803 |
-
|
1804 |
-
ewwwio_debug_message( "parsing srcset took $elapsed_time seconds" );
|
1805 |
-
/* ewwwio_debug_message( print_r( $sources, true ) ); */
|
1806 |
-
$this->elapsed_time += microtime( true ) - $started;
|
1807 |
-
return $sources;
|
1808 |
-
}
|
1809 |
|
1810 |
-
|
1811 |
-
|
1812 |
-
*
|
1813 |
-
* @param array $sizes An array of media query breakpoints.
|
1814 |
-
* @param array $size Width and height of the image.
|
1815 |
-
* @uses this::get_content_width
|
1816 |
-
* @return array An array of media query breakpoints.
|
1817 |
-
*/
|
1818 |
-
public function filter_sizes( $sizes, $size ) {
|
1819 |
-
$started = microtime( true );
|
1820 |
-
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
1821 |
-
if ( ! doing_filter( 'the_content' ) ) {
|
1822 |
-
return $sizes;
|
1823 |
-
}
|
1824 |
-
$content_width = $this->get_content_width();
|
1825 |
|
1826 |
-
|
1827 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1828 |
}
|
1829 |
|
1830 |
-
|
1831 |
-
|
1832 |
-
|
1833 |
-
|
1834 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1835 |
|
1836 |
-
|
1837 |
-
|
1838 |
-
|
1839 |
-
* @param string $url The url of the image.
|
1840 |
-
* @param int $width Image width to use for calculations.
|
1841 |
-
* @param bool $zoom Whether to use zoom or w param.
|
1842 |
-
* @param int $filename_width The width derived from the filename, or false.
|
1843 |
-
* @uses this::generate_url
|
1844 |
-
* @return string A srcset attribute with ExactDN image urls and widths.
|
1845 |
-
*/
|
1846 |
-
public function generate_image_srcset( $url, $width, $zoom = false, $filename_width = false ) {
|
1847 |
-
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
1848 |
-
// Don't foul up the admin side of things.
|
1849 |
-
if ( is_admin() ) {
|
1850 |
-
return '';
|
1851 |
-
}
|
1852 |
|
1853 |
-
|
1854 |
-
|
|
|
|
|
1855 |
}
|
1856 |
|
1857 |
/**
|
1858 |
-
*
|
1859 |
-
* Return false to short-circuit and bypass auto-generation.
|
1860 |
-
*
|
1861 |
-
* @param array|bool $multipliers Array of multipliers to use or false to bypass.
|
1862 |
-
*/
|
1863 |
-
$multipliers = apply_filters( 'exactdn_srcset_multipliers', array( .2, .4, .6, .8, 1, 2, 3, 1920 ) );
|
1864 |
-
/**
|
1865 |
-
* Filter the width ExactDN will use to create srcset attribute.
|
1866 |
-
* Return a falsy value to short-circuit and bypass srcset fill.
|
1867 |
*
|
1868 |
-
* @param
|
|
|
|
|
|
|
|
|
|
|
1869 |
*/
|
1870 |
-
|
1871 |
-
|
1872 |
-
|
1873 |
-
|
1874 |
-
|
1875 |
-
|
1876 |
|
1877 |
-
|
1878 |
-
|
1879 |
-
|
1880 |
-
|
1881 |
-
/**
|
1882 |
-
|
1883 |
-
|
1884 |
-
|
1885 |
-
|
1886 |
-
|
1887 |
-
|
1888 |
-
|
1889 |
-
|
1890 |
-
|
1891 |
-
|
1892 |
-
|
1893 |
-
|
1894 |
-
|
1895 |
-
|
1896 |
-
|
1897 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1898 |
}
|
1899 |
-
} // foreach ( $currentwidths as $currentwidth ){
|
1900 |
-
if ( $filename_width && $newwidth > $filename_width ) {
|
1901 |
-
continue;
|
1902 |
-
}
|
1903 |
|
1904 |
-
|
1905 |
-
|
1906 |
-
|
1907 |
-
|
1908 |
-
|
1909 |
-
|
1910 |
-
|
1911 |
-
|
1912 |
-
|
1913 |
-
|
1914 |
-
|
1915 |
|
1916 |
-
|
1917 |
-
|
1918 |
-
|
1919 |
-
|
1920 |
-
|
1921 |
|
1922 |
-
|
|
|
1923 |
}
|
1924 |
-
|
1925 |
-
|
1926 |
-
|
1927 |
-
|
1928 |
}
|
|
|
|
|
1929 |
}
|
1930 |
-
/* ewwwio_debug_message( print_r( $sources, true ) ); */
|
1931 |
-
return rtrim( $srcset, ', ' );
|
1932 |
-
}
|
1933 |
|
1934 |
-
|
1935 |
-
|
1936 |
-
|
1937 |
-
|
1938 |
-
|
1939 |
-
|
1940 |
-
|
1941 |
-
|
1942 |
-
|
1943 |
-
|
1944 |
-
|
1945 |
-
|
1946 |
-
|
1947 |
-
return $args;
|
1948 |
-
}
|
1949 |
-
// Doing something other than a hard crop, or we don't know what the ID is.
|
1950 |
-
if ( empty( $args['resize'] ) || empty( $attachment_id ) ) {
|
1951 |
-
ewwwio_debug_message( 'not resizing, so no custom crop' );
|
1952 |
-
return $args;
|
1953 |
-
}
|
1954 |
-
// TST is not active.
|
1955 |
-
if ( ! defined( 'TST_VERSION' ) ) {
|
1956 |
-
ewwwio_debug_message( 'no TST plugin' );
|
1957 |
-
return $args;
|
1958 |
-
}
|
1959 |
-
if ( ! class_exists( 'TstPostOptions' ) || ! defined( 'TstPostOptions::META_POSITION' ) ) {
|
1960 |
-
ewwwio_debug_message( 'no TstPostOptions class' );
|
1961 |
-
return $args;
|
1962 |
-
}
|
1963 |
-
if ( ! $meta || ! is_array( $meta ) || empty( $meta['sizes'] ) ) {
|
1964 |
-
// $focus_point = get_post_meta( $attachment_id, TstPostOptions::META_POSITION, true );
|
1965 |
-
$meta = wp_get_attachment_metadata( $attachment_id );
|
1966 |
-
if ( ! is_array( $meta ) || empty( $meta['width'] ) || empty( $meta['height'] ) ) {
|
1967 |
-
ewwwio_debug_message( 'unusable meta retrieved' );
|
1968 |
return $args;
|
1969 |
}
|
1970 |
-
|
1971 |
-
|
1972 |
-
|
1973 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1974 |
return $args;
|
1975 |
}
|
1976 |
-
$focus_point = TstPostOptions::get_meta( $attachment_id, $meta['width'], $meta['height'] );
|
1977 |
-
} else {
|
1978 |
-
ewwwio_debug_message( 'unusable meta' );
|
1979 |
-
return $args;
|
1980 |
-
}
|
1981 |
-
if ( empty( $focus_point ) || ! is_array( $focus_point ) ) {
|
1982 |
-
ewwwio_debug_message( 'unusable focus point' );
|
1983 |
-
return $args;
|
1984 |
-
}
|
1985 |
|
1986 |
-
|
1987 |
|
1988 |
-
|
1989 |
-
|
1990 |
-
|
1991 |
-
|
1992 |
-
|
1993 |
-
|
1994 |
-
|
1995 |
-
|
1996 |
-
|
1997 |
-
|
1998 |
-
|
1999 |
-
|
2000 |
-
|
2001 |
-
|
2002 |
-
|
2003 |
-
|
2004 |
-
|
2005 |
-
|
2006 |
-
|
2007 |
-
|
2008 |
-
|
2009 |
-
|
2010 |
-
|
2011 |
-
}
|
2012 |
-
|
2013 |
-
/**
|
2014 |
-
* Check if this is a REST API request that we should handle (or not).
|
2015 |
-
*
|
2016 |
-
* @param WP_HTTP_Response $response Result to send to the client. Usually a WP_REST_Response.
|
2017 |
-
* @param WP_REST_Server $handler ResponseHandler instance (usually WP_REST_Server).
|
2018 |
-
* @param WP_REST_Request $request Request used to generate the response.
|
2019 |
-
* @return WP_HTTP_Response The result, unaltered.
|
2020 |
-
*/
|
2021 |
-
function parse_restapi_maybe( $response, $handler, $request ) {
|
2022 |
-
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
2023 |
-
if ( ! is_a( $request, 'WP_REST_Request' ) ) {
|
2024 |
-
ewwwio_debug_message( 'oddball REST request or handler' );
|
2025 |
-
return $response; // Something isn't right, bail.
|
2026 |
-
}
|
2027 |
-
$route = $request->get_route();
|
2028 |
-
if ( is_string( $route ) ) {
|
2029 |
-
ewwwio_debug_message( "current REST route is $route" );
|
2030 |
-
}
|
2031 |
-
if ( is_string( $route ) && false !== strpos( $route, 'wp/v2/media/' ) && ! empty( $request['context'] ) && 'edit' === $request['context'] ) {
|
2032 |
-
ewwwio_debug_message( 'REST API media endpoint from post editor' );
|
2033 |
-
// We don't want ExactDN urls anywhere near the editor, so disable everything we can.
|
2034 |
-
add_filter( 'exactdn_override_image_downsize', '__return_true', PHP_INT_MAX );
|
2035 |
-
add_filter( 'exactdn_skip_image', '__return_true', PHP_INT_MAX ); // This skips existing srcset indices.
|
2036 |
-
add_filter( 'exactdn_srcset_multipliers', '__return_false', PHP_INT_MAX ); // This one skips the additional multipliers.
|
2037 |
}
|
2038 |
-
return $response;
|
2039 |
-
}
|
2040 |
|
2041 |
-
|
2042 |
-
|
2043 |
-
|
2044 |
-
|
2045 |
-
|
2046 |
-
|
2047 |
-
|
2048 |
-
|
2049 |
-
|
2050 |
-
$
|
2051 |
-
if (
|
2052 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2053 |
}
|
|
|
2054 |
}
|
2055 |
-
return false;
|
2056 |
-
}
|
2057 |
|
2058 |
-
|
2059 |
-
|
2060 |
-
|
2061 |
-
|
2062 |
-
|
2063 |
-
|
2064 |
-
|
2065 |
-
|
2066 |
-
|
2067 |
-
|
2068 |
-
|
2069 |
-
|
2070 |
-
|
2071 |
-
|
2072 |
-
}
|
2073 |
-
$parsed_url = $this->parse_url( $url );
|
2074 |
-
if ( ! $parsed_url ) {
|
2075 |
-
ewwwio_debug_message( "could not parse: $url" );
|
2076 |
return false;
|
2077 |
}
|
2078 |
|
2079 |
-
|
2080 |
-
|
2081 |
-
|
2082 |
-
|
2083 |
-
|
2084 |
-
|
2085 |
-
|
2086 |
-
|
2087 |
-
|
2088 |
-
)
|
2089 |
-
|
2090 |
-
|
2091 |
-
|
2092 |
-
|
2093 |
-
|
2094 |
-
|
2095 |
-
|
2096 |
-
|
2097 |
-
|
2098 |
-
|
2099 |
-
) {
|
2100 |
-
ewwwio_debug_message( 'rejected https via filter' );
|
2101 |
-
return false;
|
2102 |
-
}
|
2103 |
|
2104 |
-
|
2105 |
-
|
2106 |
-
|
2107 |
-
|
2108 |
-
|
|
|
|
|
|
|
|
|
|
|
2109 |
|
2110 |
-
|
2111 |
-
|
2112 |
-
|
2113 |
-
|
2114 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2115 |
|
2116 |
-
|
2117 |
-
|
2118 |
-
|
2119 |
-
|
2120 |
-
|
2121 |
|
2122 |
-
|
2123 |
-
|
2124 |
-
|
2125 |
-
|
2126 |
-
|
2127 |
|
2128 |
-
|
2129 |
-
|
2130 |
-
|
2131 |
-
|
2132 |
-
|
2133 |
|
2134 |
-
|
2135 |
-
|
2136 |
-
|
2137 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2138 |
}
|
2139 |
|
2140 |
-
// If we got this far, we should have an acceptable image URL,
|
2141 |
-
// but let folks filter to decline if they prefer.
|
2142 |
/**
|
2143 |
-
*
|
2144 |
*
|
2145 |
-
* @param
|
2146 |
-
* @
|
2147 |
-
|
2148 |
-
|
2149 |
-
|
2150 |
-
|
2151 |
-
|
2152 |
-
|
2153 |
-
|
2154 |
-
|
2155 |
-
|
2156 |
-
|
2157 |
-
|
2158 |
-
|
2159 |
-
|
2160 |
-
|
2161 |
-
|
2162 |
-
|
2163 |
-
|
2164 |
-
|
2165 |
-
$
|
2166 |
-
|
2167 |
-
// Extracts the file path to the image minus the base url.
|
2168 |
-
$file_path = substr( $stripped_src, strlen( $upload_dir['baseurl'] ) );
|
2169 |
-
|
2170 |
-
if ( is_file( $upload_dir['basedir'] . $file_path ) ) {
|
2171 |
-
$src = $stripped_src;
|
2172 |
-
}
|
2173 |
-
ewwwio_debug_message( 'stripped dims' );
|
2174 |
}
|
2175 |
-
return $src;
|
2176 |
-
}
|
2177 |
|
2178 |
-
|
2179 |
-
|
2180 |
-
|
2181 |
-
|
2182 |
-
|
2183 |
-
|
2184 |
-
|
2185 |
-
|
2186 |
-
|
2187 |
-
|
2188 |
-
|
2189 |
-
|
2190 |
-
|
2191 |
-
|
2192 |
-
|
2193 |
-
|
2194 |
-
|
2195 |
-
|
2196 |
-
|
2197 |
-
|
2198 |
-
|
2199 |
-
|
2200 |
-
|
2201 |
-
|
2202 |
-
|
2203 |
-
|
2204 |
-
|
2205 |
-
|
2206 |
-
|
2207 |
-
|
2208 |
-
|
2209 |
-
|
2210 |
-
|
2211 |
-
|
2212 |
-
|
2213 |
-
|
2214 |
|
2215 |
-
|
2216 |
-
|
2217 |
|
2218 |
-
|
2219 |
-
|
2220 |
-
|
2221 |
-
|
2222 |
-
|
|
|
2223 |
}
|
2224 |
-
}
|
2225 |
|
2226 |
-
|
2227 |
-
|
2228 |
|
2229 |
-
|
2230 |
-
|
2231 |
-
|
2232 |
-
|
2233 |
-
|
2234 |
-
|
2235 |
-
|
2236 |
-
|
2237 |
-
|
2238 |
-
|
2239 |
-
|
2240 |
-
|
2241 |
-
|
2242 |
-
|
2243 |
-
|
2244 |
-
|
2245 |
-
|
2246 |
-
|
2247 |
-
|
2248 |
-
|
2249 |
-
|
2250 |
-
|
2251 |
-
|
|
|
2252 |
}
|
2253 |
}
|
2254 |
-
|
2255 |
-
|
2256 |
-
|
2257 |
-
|
2258 |
-
|
2259 |
}
|
2260 |
}
|
2261 |
}
|
2262 |
}
|
|
|
2263 |
}
|
2264 |
-
return $images;
|
2265 |
-
}
|
2266 |
|
2267 |
-
|
2268 |
-
|
2269 |
-
|
2270 |
-
|
2271 |
-
|
2272 |
-
|
2273 |
-
|
2274 |
-
|
2275 |
-
|
2276 |
-
|
2277 |
-
|
2278 |
-
|
2279 |
-
|
2280 |
-
|
2281 |
-
|
2282 |
-
|
2283 |
-
|
2284 |
-
|
2285 |
-
|
2286 |
-
|
2287 |
-
|
2288 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
2289 |
return $image;
|
2290 |
}
|
2291 |
-
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
2292 |
-
if ( $this->validate_image_url( $image ) ) {
|
2293 |
-
return $this->generate_url( $image );
|
2294 |
-
}
|
2295 |
-
return $image;
|
2296 |
-
}
|
2297 |
|
2298 |
-
|
2299 |
-
|
2300 |
-
|
2301 |
-
|
2302 |
-
|
2303 |
-
|
2304 |
-
|
2305 |
-
|
2306 |
-
|
2307 |
-
|
|
|
2308 |
}
|
|
|
2309 |
}
|
2310 |
-
return $product_data;
|
2311 |
-
}
|
2312 |
|
2313 |
-
|
2314 |
-
|
2315 |
-
|
2316 |
-
|
2317 |
-
|
2318 |
-
|
2319 |
-
|
2320 |
-
|
2321 |
-
|
2322 |
-
|
2323 |
-
|
2324 |
-
|
2325 |
-
|
2326 |
-
|
2327 |
-
|
2328 |
-
|
2329 |
-
|
2330 |
-
|
2331 |
-
|
2332 |
-
|
2333 |
-
|
2334 |
-
|
2335 |
-
|
2336 |
-
|
2337 |
-
|
2338 |
-
|
2339 |
-
|
2340 |
-
|
2341 |
-
|
2342 |
-
|
2343 |
-
|
2344 |
-
|
2345 |
-
|
2346 |
-
|
2347 |
-
|
2348 |
-
|
|
|
2349 |
}
|
2350 |
-
return $args;
|
2351 |
-
}
|
2352 |
|
2353 |
-
|
2354 |
-
|
2355 |
-
|
2356 |
-
|
2357 |
-
|
2358 |
-
|
2359 |
-
|
2360 |
-
|
2361 |
-
|
2362 |
-
|
2363 |
-
|
2364 |
-
|
2365 |
-
|
2366 |
-
|
2367 |
-
|
|
|
2368 |
}
|
2369 |
}
|
|
|
2370 |
}
|
2371 |
-
return $skip;
|
2372 |
-
}
|
2373 |
-
|
2374 |
-
/**
|
2375 |
-
* Converts a local script/css url to use ExactDN.
|
2376 |
-
*
|
2377 |
-
* @param string $url URL to the resource being parsed.
|
2378 |
-
* @return string The ExactDN version of the resource, if it was local.
|
2379 |
-
*/
|
2380 |
-
function parse_enqueue( $url ) {
|
2381 |
-
if ( is_admin() ) {
|
2382 |
-
return $url;
|
2383 |
-
}
|
2384 |
-
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
2385 |
-
$parsed_url = $this->parse_url( $url );
|
2386 |
|
2387 |
-
if ( false !== strpos( $url, 'wp-admin/' ) ) {
|
2388 |
-
return $url;
|
2389 |
-
}
|
2390 |
-
if ( false !== strpos( $url, 'xmlrpc.php' ) ) {
|
2391 |
-
return $url;
|
2392 |
-
}
|
2393 |
-
if ( strpos( $url, 'wp-content/plugins/anti-captcha/' ) ) {
|
2394 |
-
return $url;
|
2395 |
-
}
|
2396 |
/**
|
2397 |
-
*
|
2398 |
*
|
2399 |
-
* @param
|
2400 |
-
* @
|
2401 |
-
* @param array|string $args Array of ExactDN arguments.
|
2402 |
-
* @param string|null $scheme URL scheme. Default to null.
|
2403 |
*/
|
2404 |
-
|
2405 |
-
|
2406 |
-
|
2407 |
-
|
2408 |
-
|
2409 |
-
|
2410 |
-
ewwwio_debug_message( 'src url no good' );
|
2411 |
-
return $url;
|
2412 |
-
}
|
2413 |
|
2414 |
-
|
2415 |
-
|
2416 |
-
|
2417 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2418 |
|
2419 |
-
|
2420 |
-
|
2421 |
-
|
2422 |
-
|
2423 |
-
|
2424 |
|
2425 |
-
|
2426 |
-
|
2427 |
-
|
2428 |
-
|
2429 |
-
}
|
2430 |
|
2431 |
-
|
2432 |
-
|
2433 |
-
|
2434 |
-
|
2435 |
-
|
2436 |
-
}
|
2437 |
|
2438 |
-
|
2439 |
-
|
2440 |
-
|
2441 |
-
|
2442 |
-
if ( empty( $modified ) ) {
|
2443 |
-
$modified = (int) EWWW_IMAGE_OPTIMIZER_VERSION;
|
2444 |
}
|
2445 |
-
/**
|
2446 |
-
* Allows a custom version string for resources that are missing one.
|
2447 |
-
*
|
2448 |
-
* @param string EWWW IO version.
|
2449 |
-
*/
|
2450 |
-
$parsed_url['query'] = apply_filters( 'exactdn_version_string', "m=$modified" );
|
2451 |
-
} elseif ( empty( $parsed_url['query'] ) ) {
|
2452 |
-
$parsed_url['query'] = '';
|
2453 |
-
}
|
2454 |
|
2455 |
-
|
2456 |
-
|
2457 |
-
|
2458 |
-
|
|
|
|
|
2459 |
|
2460 |
-
|
2461 |
-
|
2462 |
-
|
2463 |
-
|
2464 |
-
|
2465 |
-
|
2466 |
-
|
2467 |
-
|
2468 |
-
|
2469 |
-
|
2470 |
-
|
|
|
|
|
|
|
|
|
|
|
2471 |
|
2472 |
-
|
2473 |
-
$
|
|
|
2474 |
}
|
2475 |
|
2476 |
/**
|
2477 |
-
*
|
2478 |
*
|
2479 |
-
* @param
|
|
|
|
|
|
|
2480 |
*/
|
2481 |
-
|
2482 |
-
|
2483 |
-
|
2484 |
|
2485 |
-
|
2486 |
-
|
2487 |
-
|
2488 |
-
* @param bool false Should the URL be returned as is, without going through ExactDN. Default to false.
|
2489 |
-
* @param string $image_url Resource URL.
|
2490 |
-
* @param array|string $args Array of ExactDN arguments.
|
2491 |
-
* @param string|null $scheme URL scheme. Default to null.
|
2492 |
-
*/
|
2493 |
-
if ( true === apply_filters( 'exactdn_skip_for_url', false, $image_url, $args, $scheme ) ) {
|
2494 |
-
return $image_url;
|
2495 |
-
}
|
2496 |
|
2497 |
-
|
2498 |
-
|
2499 |
-
|
|
|
|
|
|
|
|
|
|
|
2500 |
|
2501 |
-
|
2502 |
-
|
2503 |
-
|
2504 |
-
|
2505 |
-
|
2506 |
-
|
2507 |
-
|
2508 |
-
|
2509 |
-
|
2510 |
-
|
2511 |
-
|
2512 |
-
$args = wp_parse_args( $args, $more_args );
|
2513 |
|
2514 |
-
|
2515 |
-
|
2516 |
-
|
2517 |
-
* @param string $image_url Image URL.
|
2518 |
-
* @param array|string $args Array of ExactDN arguments.
|
2519 |
-
* @param string|null $scheme Image scheme. Default to null.
|
2520 |
-
*/
|
2521 |
-
$image_url = apply_filters( 'exactdn_pre_image_url', $image_url, $args, $scheme );
|
2522 |
|
2523 |
-
|
2524 |
-
|
2525 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2526 |
|
2527 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2528 |
|
2529 |
-
|
2530 |
-
|
2531 |
-
|
2532 |
-
return $image_url;
|
2533 |
-
}
|
2534 |
|
2535 |
-
|
2536 |
-
|
2537 |
-
|
|
|
|
|
|
|
2538 |
}
|
2539 |
-
$scheme = 'https';
|
2540 |
-
}
|
2541 |
|
2542 |
-
|
2543 |
-
|
2544 |
-
|
2545 |
-
|
2546 |
-
|
2547 |
-
|
2548 |
-
*/
|
2549 |
-
$args = apply_filters( 'exactdn_pre_args', $args, $image_url, $scheme );
|
2550 |
|
2551 |
-
|
2552 |
-
|
2553 |
-
|
2554 |
-
|
2555 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2556 |
}
|
|
|
|
|
|
|
2557 |
}
|
2558 |
|
2559 |
-
|
2560 |
-
$args = rawurlencode_deep( $args );
|
2561 |
-
}
|
2562 |
|
2563 |
-
|
|
|
|
|
|
|
|
|
2564 |
|
2565 |
-
|
2566 |
-
|
2567 |
-
|
2568 |
-
|
2569 |
-
|
|
|
|
|
2570 |
|
2571 |
-
|
2572 |
-
|
2573 |
-
|
2574 |
-
|
2575 |
-
$
|
2576 |
-
|
2577 |
-
|
|
|
2578 |
|
2579 |
-
|
2580 |
-
|
2581 |
-
|
2582 |
-
|
2583 |
-
|
2584 |
-
|
2585 |
-
return $image_url;
|
2586 |
-
}
|
2587 |
|
2588 |
-
|
2589 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2590 |
}
|
2591 |
-
$domain = 'http://' . $this->exactdn_domain . '/';
|
2592 |
-
$exactdn_url = $domain . ltrim( $image_url_parts['path'], '/' );
|
2593 |
-
ewwwio_debug_message( "bare exactdn url: $exactdn_url" );
|
2594 |
|
2595 |
/**
|
2596 |
-
*
|
2597 |
-
* By default, ExactDN doesn't support query strings so we ignore them.
|
2598 |
-
* This setting is ExactDN Server dependent.
|
2599 |
*
|
2600 |
-
* @param
|
2601 |
-
* @param string $
|
|
|
2602 |
*/
|
2603 |
-
|
2604 |
-
$
|
2605 |
-
|
2606 |
-
|
2607 |
-
|
2608 |
-
|
2609 |
-
|
2610 |
-
|
2611 |
-
|
2612 |
-
|
2613 |
-
$exactdn_url = add_query_arg( $args, $exactdn_url );
|
2614 |
-
} else {
|
2615 |
-
// You can pass a query string for complicated requests, although this should have been converted to an array already.
|
2616 |
-
$exactdn_url .= '?' . $args;
|
2617 |
}
|
|
|
|
|
2618 |
}
|
2619 |
-
ewwwio_debug_message( "exactdn url with args: $exactdn_url" );
|
2620 |
-
|
2621 |
-
return $this->url_scheme( $exactdn_url, $scheme );
|
2622 |
-
}
|
2623 |
|
2624 |
-
|
2625 |
-
|
2626 |
-
|
2627 |
-
|
2628 |
-
|
2629 |
-
|
2630 |
-
|
2631 |
-
|
2632 |
-
|
2633 |
-
|
2634 |
-
|
2635 |
-
|
2636 |
-
|
2637 |
-
|
2638 |
}
|
2639 |
-
|
2640 |
-
$
|
|
|
2641 |
}
|
2642 |
-
ewwwio_debug_message( "valid $scheme - $url" );
|
2643 |
-
return preg_replace( '#^([a-z:]+)?//#i', "$scheme://", $url );
|
2644 |
-
}
|
2645 |
|
2646 |
-
|
2647 |
-
|
2648 |
-
|
2649 |
-
|
2650 |
-
|
2651 |
-
|
2652 |
-
|
2653 |
-
|
2654 |
-
|
2655 |
-
|
2656 |
-
|
2657 |
-
|
2658 |
-
|
2659 |
-
|
|
|
|
|
2660 |
}
|
2661 |
-
// Because encoded ampersands in the filename break things.
|
2662 |
-
$url = str_replace( '&', '&', $url );
|
2663 |
-
return parse_url( $url, $component );
|
2664 |
-
}
|
2665 |
|
2666 |
-
|
2667 |
-
|
2668 |
-
|
2669 |
-
|
2670 |
-
|
2671 |
-
|
2672 |
-
|
2673 |
-
|
2674 |
-
|
2675 |
-
|
2676 |
-
|
2677 |
-
|
2678 |
-
if ( $diff < 60 ) {
|
2679 |
-
return "$diff sec";
|
2680 |
}
|
2681 |
-
return human_time_diff( $from, $to );
|
2682 |
-
}
|
2683 |
|
2684 |
-
|
2685 |
-
|
2686 |
-
|
2687 |
-
|
2688 |
-
|
2689 |
-
|
2690 |
-
|
2691 |
-
|
2692 |
-
|
2693 |
-
|
|
|
|
|
|
|
2694 |
}
|
2695 |
-
return $hints;
|
2696 |
}
|
2697 |
|
2698 |
-
|
2699 |
-
|
2700 |
-
*
|
2701 |
-
* @param array $domains A list of domains considered 'local' by Autoptimize.
|
2702 |
-
* @return array The same list, with the ExactDN domain appended.
|
2703 |
-
*/
|
2704 |
-
function autoptimize_cdn_url( $domains ) {
|
2705 |
-
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
2706 |
-
if ( is_array( $domains ) && ! in_array( $this->exactdn_domain, $domains, true ) ) {
|
2707 |
-
ewwwio_debug_message( 'adding to AO list: ' . $this->exactdn_domain );
|
2708 |
-
$domains[] = $this->exactdn_domain;
|
2709 |
-
}
|
2710 |
-
return $domains;
|
2711 |
-
}
|
2712 |
}
|
2713 |
-
|
2714 |
-
global $exactdn;
|
2715 |
-
$exactdn = new ExactDN();
|
3 |
* Class and methods to implement ExactDN (based on Photon implementation).
|
4 |
*
|
5 |
* @link https://ewww.io
|
6 |
+
* @package EIO
|
7 |
*/
|
8 |
|
9 |
if ( ! defined( 'ABSPATH' ) ) {
|
10 |
exit;
|
11 |
}
|
12 |
|
13 |
+
if ( ! class_exists( 'ExactDN' ) ) {
|
|
|
|
|
|
|
|
|
14 |
/**
|
15 |
+
* Enables plugin to filter the page content and replace image urls with ExactDN urls.
|
|
|
|
|
|
|
16 |
*/
|
17 |
+
class ExactDN extends EIO_Page_Parser {
|
18 |
|
19 |
+
/**
|
20 |
+
* A list of user-defined exclusions, populated by validate_user_exclusions().
|
21 |
+
*
|
22 |
+
* @access protected
|
23 |
+
* @var array $user_exclusions
|
24 |
+
*/
|
25 |
+
protected $user_exclusions = array();
|
26 |
|
27 |
+
/**
|
28 |
+
* A list of image sizes registered for attachments.
|
29 |
+
*
|
30 |
+
* @access protected
|
31 |
+
* @var array $image_sizes
|
32 |
+
*/
|
33 |
+
protected static $image_sizes = null;
|
34 |
|
35 |
+
/**
|
36 |
+
* Indicates if we are in full-page filtering mode.
|
37 |
+
*
|
38 |
+
* @access public
|
39 |
+
* @var bool $filtering_the_page
|
40 |
+
*/
|
41 |
+
public $filtering_the_page = false;
|
42 |
|
43 |
+
/**
|
44 |
+
* Indicates if we are in content filtering mode.
|
45 |
+
*
|
46 |
+
* @access public
|
47 |
+
* @var bool $filtering_the_content
|
48 |
+
*/
|
49 |
+
public $filtering_the_content = false;
|
50 |
|
51 |
+
/**
|
52 |
+
* List of permitted domains for ExactDN rewriting.
|
53 |
+
*
|
54 |
+
* @access public
|
55 |
+
* @var array $allowed_domains
|
56 |
+
*/
|
57 |
+
public $allowed_domains = array();
|
58 |
|
59 |
+
/**
|
60 |
+
* Path portion to remove at beginning of URL, usually for path-style S3 domains.
|
61 |
+
*
|
62 |
+
* @access public
|
63 |
+
* @var string $remove_path
|
64 |
+
*/
|
65 |
+
public $remove_path = '';
|
66 |
|
67 |
+
/**
|
68 |
+
* The ExactDN domain/zone.
|
69 |
+
*
|
70 |
+
* @access private
|
71 |
+
* @var float $elapsed_time
|
72 |
+
*/
|
73 |
+
private $exactdn_domain = false;
|
74 |
|
75 |
+
/**
|
76 |
+
* The detected site scheme (http/https).
|
77 |
+
*
|
78 |
+
* @access private
|
79 |
+
* @var string $scheme
|
80 |
+
*/
|
81 |
+
private $scheme = false;
|
82 |
|
83 |
+
/**
|
84 |
+
* Allow us to track how much overhead ExactDN introduces.
|
85 |
+
*
|
86 |
+
* @access private
|
87 |
+
* @var float $elapsed_time
|
88 |
+
*/
|
89 |
+
private $elapsed_time = 0;
|
90 |
|
91 |
+
/**
|
92 |
+
* Keep track of the attribute we use for srcset, in case a lazy load plugin is active.
|
93 |
+
*
|
94 |
+
* @access private
|
95 |
+
* @var string $srcset_attr
|
96 |
+
*/
|
97 |
+
private $srcset_attr = 'srcset';
|
|
|
|
|
98 |
|
99 |
+
/**
|
100 |
+
* Register (once) actions and filters for ExactDN. If you want to use this class, use the global.
|
101 |
+
*/
|
102 |
+
function __construct() {
|
103 |
+
parent::__construct( __FILE__ );
|
104 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
105 |
+
global $exactdn;
|
106 |
+
if ( is_object( $exactdn ) ) {
|
107 |
+
return 'you are doing it wrong';
|
108 |
+
}
|
109 |
|
110 |
+
// Make sure we have an ExactDN domain to use.
|
111 |
+
if ( ! $this->setup() ) {
|
112 |
+
return;
|
|
|
|
|
113 |
}
|
|
|
|
|
114 |
|
115 |
+
if ( ! $this->scheme ) {
|
116 |
+
$site_url = get_home_url();
|
117 |
+
$scheme = 'http';
|
118 |
+
if ( strpos( $site_url, 'https://' ) !== false ) {
|
119 |
+
$scheme = 'https';
|
120 |
+
}
|
121 |
+
$this->scheme = $scheme;
|
122 |
+
}
|
123 |
|
124 |
+
// Images in post content and galleries.
|
125 |
+
add_filter( 'the_content', array( $this, 'filter_the_content' ), 999999 );
|
126 |
+
// Start an output buffer before any output starts.
|
127 |
+
add_filter( $this->prefix . 'filter_page_output', array( $this, 'filter_page_output' ), 5 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
|
129 |
+
// Core image retrieval.
|
130 |
+
if ( ! function_exists( 'aq_resize' ) ) {
|
131 |
+
add_filter( 'image_downsize', array( $this, 'filter_image_downsize' ), 10, 3 );
|
132 |
+
} else {
|
133 |
+
$this->debug_message( 'aq_resize detected, image_downsize filter disabled' );
|
134 |
+
}
|
135 |
+
// Disable image_downsize filter during themify_get_image().
|
136 |
+
add_action( 'themify_before_post_image', array( $this, 'disable_image_downsize' ) );
|
137 |
+
if ( defined( 'EXACTDN_IMAGE_DOWNSIZE_SCALE' ) && EXACTDN_IMAGE_DOWNSIZE_SCALE ) {
|
138 |
+
add_action( 'exactdn_image_downsize_array', array( $this, 'image_downsize_scale' ) );
|
139 |
+
}
|
140 |
|
141 |
+
// Check REST API requests to see if ExactDN should be running.
|
142 |
+
add_filter( 'rest_request_before_callbacks', array( $this, 'parse_restapi_maybe' ), 10, 3 );
|
|
|
|
|
|
|
|
|
|
|
143 |
|
144 |
+
// Overrides for admin-ajax images.
|
145 |
+
add_filter( 'exactdn_admin_allow_image_downsize', array( $this, 'allow_admin_image_downsize' ), 10, 2 );
|
146 |
+
// Overrides for "pass through" images.
|
147 |
+
add_filter( 'exactdn_pre_args', array( $this, 'exactdn_remove_args' ), 10, 3 );
|
148 |
+
// Overrides for user exclusions.
|
149 |
+
add_filter( 'exactdn_skip_image', array( $this, 'exactdn_skip_user_exclusions' ), 9, 2 );
|
150 |
+
add_filter( 'exactdn_skip_for_url', array( $this, 'exactdn_skip_user_exclusions' ), 9, 2 );
|
151 |
|
152 |
+
// Responsive image srcset substitution.
|
153 |
+
add_filter( 'wp_calculate_image_srcset', array( $this, 'filter_srcset_array' ), 1001, 5 );
|
154 |
+
add_filter( 'wp_calculate_image_sizes', array( $this, 'filter_sizes' ), 1, 2 ); // Early so themes can still filter.
|
155 |
|
156 |
+
// Filter for NextGEN image urls within JS.
|
157 |
+
add_filter( 'ngg_pro_lightbox_images_queue', array( $this, 'ngg_pro_lightbox_images_queue' ) );
|
158 |
+
add_filter( 'ngg_get_image_url', array( $this, 'ngg_get_image_url' ) );
|
159 |
|
160 |
+
// Filter for legacy WooCommerce API endpoints.
|
161 |
+
add_filter( 'woocommerce_api_product_response', array( $this, 'woocommerce_api_product_response' ) );
|
162 |
|
163 |
+
// DNS prefetching.
|
164 |
+
add_filter( 'wp_resource_hints', array( $this, 'dns_prefetch' ), 10, 2 );
|
|
|
|
|
|
|
165 |
|
166 |
+
// Get all the script/css urls and rewrite them (if enabled).
|
167 |
+
if ( $this->get_option( 'exactdn_all_the_things' ) ) {
|
168 |
+
add_filter( 'style_loader_src', array( $this, 'parse_enqueue' ), 20 );
|
169 |
+
add_filter( 'script_loader_src', array( $this, 'parse_enqueue' ), 20 );
|
170 |
+
}
|
171 |
|
172 |
+
// Improve the default content_width for Twenty Nineteen.
|
173 |
+
global $content_width;
|
174 |
+
if ( function_exists( 'twentynineteen_setup' ) && 640 === (int) $content_width ) {
|
175 |
+
$content_width = 932;
|
|
|
|
|
|
|
|
|
176 |
}
|
|
|
177 |
|
178 |
+
// Configure Autoptimize with our CDN domain.
|
179 |
+
add_filter( 'autoptimize_filter_cssjs_multidomain', array( $this, 'autoptimize_cdn_url' ) );
|
180 |
+
|
181 |
+
// Find the "local" domain.
|
182 |
+
$s3_active = false;
|
183 |
+
if ( class_exists( 'Amazon_S3_And_CloudFront' ) ) {
|
184 |
+
global $as3cf;
|
185 |
+
$s3_region = $as3cf->get_setting( 'region' );
|
186 |
+
$s3_bucket = $as3cf->get_setting( 'bucket' );
|
187 |
+
$s3_domain = $as3cf->get_provider()->get_url_domain( $s3_bucket, $s3_region, null, array(), true );
|
188 |
+
$this->debug_message( "found S3 domain of $s3_domain with bucket $s3_bucket and region $s3_region" );
|
189 |
+
if ( ! empty( $s3_domain ) ) {
|
190 |
+
$s3_active = true;
|
191 |
+
}
|
192 |
}
|
|
|
193 |
|
194 |
+
if ( $s3_active ) {
|
195 |
+
$upload_dir = array(
|
196 |
+
'baseurl' => 'https://' . $s3_domain,
|
197 |
+
);
|
198 |
+
} else {
|
199 |
+
$upload_dir = wp_upload_dir( null, false );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
200 |
}
|
201 |
+
$upload_url_parts = defined( 'EXACTDN_LOCAL_DOMAIN' ) && EXACTDN_LOCAL_DOMAIN ? $this->parse_url( EXACTDN_LOCAL_DOMAIN ) : $this->parse_url( $upload_dir['baseurl'] );
|
202 |
+
if ( empty( $upload_url_parts ) ) {
|
203 |
+
return;
|
204 |
+
}
|
205 |
+
$this->upload_domain = $upload_url_parts['host'];
|
206 |
+
$this->debug_message( "allowing images from here: $this->upload_domain" );
|
207 |
+
if ( strpos( $this->upload_domain, 'amazonaws.com' ) && ! empty( $upload_url_parts['path'] ) ) {
|
208 |
+
$this->remove_path = rtrim( $upload_url_parts['path'], '/' );
|
209 |
+
$this->debug_message( "removing this from urls: $this->remove_path" );
|
210 |
+
}
|
211 |
+
$this->allowed_domains[] = $this->upload_domain;
|
212 |
+
if ( ! $s3_active && strpos( $this->upload_domain, 'www' ) === false ) {
|
213 |
+
$this->allowed_domains[] = 'www.' . $this->upload_domain;
|
214 |
+
} else {
|
215 |
+
$nonwww = ltrim( 'www.', $this->upload_domain );
|
216 |
+
if ( $nonwww !== $this->upload_domain ) {
|
217 |
+
$this->allowed_domains[] = $nonwww;
|
218 |
+
}
|
219 |
+
}
|
220 |
+
$wpml_domains = apply_filters( 'wpml_setting', array(), 'language_domains' );
|
221 |
+
if ( $this->is_iterable( $wpml_domains ) ) {
|
222 |
+
$this->debug_message( 'wpml domains: ' . implode( ',', $wpml_domains ) );
|
223 |
+
$this->allowed_domains[] = $this->parse_url( get_option( 'home' ), PHP_URL_HOST );
|
224 |
+
foreach ( $wpml_domains as $wpml_domain ) {
|
225 |
+
$this->allowed_domains[] = $wpml_domain;
|
226 |
+
}
|
227 |
}
|
228 |
+
$this->allowed_domains = apply_filters( 'exactdn_allowed_domains', $this->allowed_domains );
|
229 |
+
$this->debug_message( 'allowed domains: ' . implode( ',', $this->allowed_domains ) );
|
230 |
+
$this->validate_user_exclusions();
|
231 |
}
|
|
|
|
|
|
|
|
|
232 |
|
233 |
+
/**
|
234 |
+
* If ExactDN is enabled, validates and configures the ExactDN domain name.
|
235 |
+
*/
|
236 |
+
function setup() {
|
237 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
238 |
+
// If we don't have a domain yet, go grab one.
|
239 |
+
if ( ! $this->get_exactdn_domain() ) {
|
240 |
+
$this->debug_message( 'attempting to activate exactDN' );
|
241 |
+
$exactdn_domain = $this->activate_site();
|
242 |
+
} else {
|
243 |
+
$this->debug_message( 'grabbing existing exactDN domain' );
|
244 |
+
$exactdn_domain = $this->get_exactdn_domain();
|
245 |
+
}
|
246 |
+
if ( ! $exactdn_domain ) {
|
247 |
+
delete_option( $this->prefix . 'exactdn' );
|
248 |
+
delete_site_option( $this->prefix . 'exactdn' );
|
|
|
|
|
|
|
249 |
return false;
|
250 |
}
|
251 |
+
// If we have a domain, verify it.
|
252 |
+
if ( $this->verify_domain( $exactdn_domain ) ) {
|
253 |
+
$this->debug_message( 'verified existing exactDN domain' );
|
254 |
+
$this->exactdn_domain = $exactdn_domain;
|
255 |
+
$this->debug_message( 'exactdn_domain: ' . $exactdn_domain );
|
256 |
+
return true;
|
257 |
+
}
|
258 |
+
delete_option( $this->prefix . 'exactdn_domain' );
|
259 |
+
delete_option( $this->prefix . 'exactdn_verified' );
|
260 |
+
delete_site_option( $this->prefix . 'exactdn_domain' );
|
261 |
+
delete_site_option( $this->prefix . 'exactdn_verified' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
262 |
return false;
|
263 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
264 |
|
265 |
+
/**
|
266 |
+
* Use the Site URL to get the zone domain.
|
267 |
+
*/
|
268 |
+
function activate_site() {
|
269 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
270 |
+
$s3_active = false;
|
271 |
+
if ( class_exists( 'Amazon_S3_And_CloudFront' ) ) {
|
272 |
+
global $as3cf;
|
273 |
+
$s3_scheme = $as3cf->get_url_scheme();
|
274 |
+
$s3_region = $as3cf->get_setting( 'region' );
|
275 |
+
$s3_bucket = $as3cf->get_setting( 'bucket' );
|
276 |
+
$s3_domain = $as3cf->get_provider()->get_url_domain( $s3_bucket, $s3_region, null, array(), true );
|
277 |
+
$this->debug_message( "found S3 domain of $s3_domain with bucket $s3_bucket and region $s3_region" );
|
278 |
+
if ( ! empty( $s3_domain ) ) {
|
279 |
+
$s3_active = true;
|
280 |
+
}
|
281 |
}
|
|
|
282 |
|
283 |
+
if ( $s3_active ) {
|
284 |
+
$site_url = defined( 'EXACTDN_LOCAL_DOMAIN' ) && EXACTDN_LOCAL_DOMAIN ? EXACTDN_LOCAL_DOMAIN : $s3_scheme . '://' . $s3_domain;
|
285 |
+
} else {
|
286 |
+
$site_url = defined( 'EXACTDN_LOCAL_DOMAIN' ) && EXACTDN_LOCAL_DOMAIN ? EXACTDN_LOCAL_DOMAIN : get_home_url();
|
287 |
+
}
|
288 |
+
$url = 'http://optimize.exactlywww.com/exactdn/activate.php';
|
289 |
+
$ssl = wp_http_supports( array( 'ssl' ) );
|
290 |
+
if ( $ssl ) {
|
291 |
+
$url = set_url_scheme( $url, 'https' );
|
292 |
+
}
|
293 |
+
add_filter( 'http_headers_useragent', $this->prefix . 'cloud_useragent', PHP_INT_MAX );
|
294 |
+
$result = wp_remote_post(
|
295 |
+
$url,
|
296 |
+
array(
|
297 |
+
'timeout' => 10,
|
298 |
+
'body' => array(
|
299 |
+
'site_url' => $site_url,
|
300 |
+
),
|
301 |
+
)
|
302 |
+
);
|
303 |
+
if ( is_wp_error( $result ) ) {
|
304 |
+
$error_message = $result->get_error_message();
|
305 |
+
$this->debug_message( "exactdn activation request failed: $error_message" );
|
306 |
+
global $exactdn_activate_error;
|
307 |
+
$exactdn_activate_error = $error_message;
|
308 |
+
add_action( 'admin_notices', $this->prefix . 'notice_exactdn_activation_error' );
|
309 |
+
return false;
|
310 |
+
} elseif ( ! empty( $result['body'] ) && strpos( $result['body'], 'domain' ) !== false ) {
|
311 |
+
$response = json_decode( $result['body'], true );
|
312 |
+
if ( ! empty( $response['domain'] ) ) {
|
313 |
+
if ( strpos( $site_url, 'amazonaws.com' ) || strpos( $site_url, 'digitaloceanspaces.com' ) ) {
|
314 |
+
$this->set_exactdn_option( 'verify_method', -1, false );
|
315 |
+
}
|
316 |
+
if ( get_option( 'exactdn_never_been_active' ) ) {
|
317 |
+
$this->set_option( $this->prefix . 'lazy_load', true );
|
318 |
+
delete_option( 'exactdn_never_been_active' );
|
319 |
+
}
|
320 |
+
if ( 'external' === get_option( 'elementor_css_print_method' ) ) {
|
321 |
+
update_option( 'elementor_css_print_method', 'internal' );
|
322 |
+
}
|
323 |
+
if ( function_exists( 'et_get_option' ) && function_exists( 'et_update_option' ) && 'on' === et_get_option( 'et_pb_static_css_file', 'on' ) ) {
|
324 |
+
et_update_option( 'et_pb_static_css_file', 'off' );
|
325 |
+
et_update_option( 'et_pb_css_in_footer', 'off' );
|
326 |
+
}
|
327 |
+
return $this->set_exactdn_domain( $response['domain'] );
|
328 |
}
|
329 |
+
} elseif ( ! empty( $result['body'] ) && strpos( $result['body'], 'error' ) !== false ) {
|
330 |
+
$response = json_decode( $result['body'], true );
|
331 |
+
$error_message = $response['error'];
|
332 |
+
$this->debug_message( "exactdn activation request failed: $error_message" );
|
333 |
+
global $exactdn_activate_error;
|
334 |
+
$exactdn_activate_error = $error_message;
|
335 |
+
add_action( 'admin_notices', $this->prefix . 'notice_exactdn_activation_error' );
|
336 |
+
return false;
|
337 |
}
|
|
|
|
|
|
|
|
|
338 |
return false;
|
339 |
}
|
|
|
|
|
340 |
|
341 |
+
/**
|
342 |
+
* Verify the ExactDN domain.
|
343 |
+
*
|
344 |
+
* @param string $domain The ExactDN domain to verify.
|
345 |
+
* @return bool Whether the domain is still valid.
|
346 |
+
*/
|
347 |
+
function verify_domain( $domain ) {
|
348 |
+
if ( empty( $domain ) ) {
|
349 |
+
return false;
|
350 |
+
}
|
351 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
352 |
+
// Check the time, to see how long it has been since we verified the domain.
|
353 |
+
$last_checkin = $this->get_exactdn_option( 'checkin' );
|
354 |
+
if ( $this->get_exactdn_option( 'verified' ) ) {
|
355 |
+
return true;
|
356 |
+
}
|
357 |
+
|
358 |
+
$this->check_verify_method();
|
359 |
+
|
360 |
+
// Set a default error.
|
361 |
+
global $exactdn_activate_error;
|
362 |
+
$exactdn_activate_error = 'zone not verified';
|
363 |
+
if ( ! defined( 'EXACTDN_LOCAL_DOMAIN' ) && $this->get_exactdn_option( 'verify_method' ) > 0 ) {
|
364 |
+
// Test with an image file that should be available on the ExactDN zone.
|
365 |
+
$test_url = plugins_url( '/images/test.png', constant( strtoupper( $this->prefix ) . 'PLUGIN_FILE' ) );
|
366 |
+
$local_domain = $this->parse_url( $test_url, PHP_URL_HOST );
|
367 |
+
$test_url = str_replace( $local_domain, $domain, $test_url );
|
368 |
+
$this->debug_message( "test url is $test_url" );
|
369 |
+
add_filter( 'http_headers_useragent', $this->prefix . 'cloud_useragent', PHP_INT_MAX );
|
370 |
+
$test_result = wp_remote_get( $test_url );
|
371 |
+
if ( is_wp_error( $test_result ) ) {
|
372 |
+
$error_message = $test_result->get_error_message();
|
373 |
+
$this->debug_message( "exactdn verification request failed: $error_message" );
|
374 |
+
$exactdn_activate_error = $error_message;
|
375 |
+
add_action( 'admin_notices', $this->prefix . 'notice_exactdn_activation_error' );
|
376 |
+
return false;
|
377 |
+
} elseif ( ! empty( $test_result['body'] ) && strlen( $test_result['body'] ) > 300 ) {
|
378 |
+
if ( 200 === $test_result['response']['code'] &&
|
379 |
+
( '89504e470d0a1a0a' === bin2hex( substr( $test_result['body'], 0, 8 ) ) || '52494646' === bin2hex( substr( $test_result['body'], 0, 4 ) ) ) ) {
|
380 |
+
$this->debug_message( 'exactdn (real-world) verification succeeded' );
|
381 |
+
$this->set_exactdn_option( 'verified', 1, false );
|
382 |
+
add_action( 'admin_notices', $this->prefix . 'notice_exactdn_activation_success' );
|
383 |
+
return true;
|
384 |
+
}
|
385 |
+
$this->debug_message( 'mime check failed: ' . bin2hex( substr( $test_result['body'], 0, 3 ) ) );
|
386 |
+
$exactdn_activate_error = 'zone setup pending';
|
387 |
+
}
|
388 |
+
add_action( 'admin_notices', $this->prefix . 'notice_exactdn_activation_error' );
|
389 |
return false;
|
390 |
}
|
|
|
|
|
391 |
|
392 |
+
// Secondary test against the API db.
|
393 |
+
$url = 'http://optimize.exactlywww.com/exactdn/verify.php';
|
394 |
+
$ssl = wp_http_supports( array( 'ssl' ) );
|
395 |
+
if ( $ssl ) {
|
396 |
+
$url = set_url_scheme( $url, 'https' );
|
397 |
+
}
|
398 |
+
add_filter( 'http_headers_useragent', $this->prefix . 'cloud_useragent', PHP_INT_MAX );
|
399 |
+
$result = wp_remote_post(
|
400 |
+
$url,
|
401 |
+
array(
|
402 |
+
'timeout' => 10,
|
403 |
+
'body' => array(
|
404 |
+
'alias' => $domain,
|
405 |
+
),
|
406 |
+
)
|
407 |
+
);
|
408 |
+
if ( is_wp_error( $result ) ) {
|
409 |
+
$error_message = $result->get_error_message();
|
410 |
+
$this->debug_message( "exactdn verification request failed: $error_message" );
|
411 |
+
$exactdn_activate_error = $error_message;
|
412 |
+
add_action( 'admin_notices', $this->prefix . 'notice_exactdn_activation_error' );
|
413 |
return false;
|
414 |
+
} elseif ( ! empty( $result['body'] ) && strpos( $result['body'], 'error' ) === false ) {
|
415 |
+
$response = json_decode( $result['body'], true );
|
416 |
+
if ( ! empty( $response['success'] ) ) {
|
417 |
+
$this->debug_message( 'exactdn (secondary) verification succeeded' );
|
|
|
418 |
$this->set_exactdn_option( 'verified', 1, false );
|
419 |
+
add_action( 'admin_notices', $this->prefix . 'notice_exactdn_activation_success' );
|
420 |
return true;
|
421 |
}
|
422 |
+
} elseif ( ! empty( $result['body'] ) ) {
|
423 |
+
$response = json_decode( $result['body'], true );
|
424 |
+
$error_message = $response['error'];
|
425 |
+
$this->debug_message( "exactdn verification request failed: $error_message" );
|
426 |
+
$exactdn_activate_error = $error_message;
|
427 |
+
add_action( 'admin_notices', $this->prefix . 'notice_exactdn_activation_error' );
|
428 |
+
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
429 |
}
|
430 |
+
add_action( 'admin_notices', $this->prefix . 'notice_exactdn_activation_error' );
|
|
|
|
|
|
|
|
|
431 |
return false;
|
432 |
}
|
|
|
|
|
|
|
433 |
|
434 |
+
/**
|
435 |
+
* Run a simulation to decide which verification method to use.
|
436 |
+
*/
|
437 |
+
function check_verify_method() {
|
438 |
+
if ( ! $this->get_exactdn_option( 'verify_method' ) ) {
|
439 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
440 |
+
// Prelim test with a known valid image to ensure http(s) connectivity.
|
441 |
+
$sim_url = 'https://optimize.exactdn.com/exactdn/testorig.jpg';
|
442 |
+
add_filter( 'http_headers_useragent', $this->prefix . 'cloud_useragent', PHP_INT_MAX );
|
443 |
+
$sim_result = wp_remote_get( $sim_url );
|
444 |
+
if ( is_wp_error( $sim_result ) ) {
|
445 |
+
$error_message = $sim_result->get_error_message();
|
446 |
+
$this->debug_message( "exactdn (simulated) verification request failed: $error_message" );
|
447 |
+
} elseif ( ! empty( $sim_result['body'] ) && strlen( $sim_result['body'] ) > 300 ) {
|
448 |
+
if ( 'ffd8ff' === bin2hex( substr( $sim_result['body'], 0, 3 ) ) ) {
|
449 |
+
$this->debug_message( 'exactdn (simulated) verification succeeded' );
|
450 |
+
$this->set_exactdn_option( 'verify_method', 1, false );
|
451 |
+
return;
|
452 |
+
}
|
453 |
}
|
454 |
+
$this->debug_message( 'exactdn (simulated) verification request failed, error unknown' );
|
455 |
+
$this->set_exactdn_option( 'verify_method', -1, false );
|
456 |
}
|
|
|
|
|
457 |
}
|
|
|
458 |
|
459 |
+
/**
|
460 |
+
* Validate the ExactDN domain.
|
461 |
+
*
|
462 |
+
* @param string $domain The unverified ExactDN domain.
|
463 |
+
* @return string The validated ExactDN domain.
|
464 |
+
*/
|
465 |
+
function sanitize_domain( $domain ) {
|
466 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
467 |
+
if ( ! $domain ) {
|
468 |
+
return;
|
469 |
+
}
|
470 |
+
if ( strlen( $domain ) > 80 ) {
|
471 |
+
$this->debug_message( "$domain too long" );
|
472 |
+
return false;
|
473 |
+
}
|
474 |
+
if ( ! preg_match( '#^[A-Za-z0-9\.\-]+$#', $domain ) ) {
|
475 |
+
$this->debug_message( "$domain has bad characters" );
|
476 |
+
return false;
|
477 |
+
}
|
478 |
+
return $domain;
|
479 |
}
|
|
|
|
|
480 |
|
481 |
+
/**
|
482 |
+
* Get the ExactDN domain name to use.
|
483 |
+
*
|
484 |
+
* @return string The ExactDN domain name for this site or network.
|
485 |
+
*/
|
486 |
+
function get_exactdn_domain() {
|
487 |
+
if ( defined( 'EXACTDN_DOMAIN' ) && EXACTDN_DOMAIN ) {
|
488 |
+
return $this->sanitize_domain( EXACTDN_DOMAIN );
|
489 |
+
}
|
490 |
+
if ( is_multisite() ) {
|
491 |
+
if ( ! SUBDOMAIN_INSTALL ) {
|
492 |
+
return $this->sanitize_domain( get_site_option( $this->prefix . 'exactdn_domain' ) );
|
493 |
+
}
|
494 |
}
|
495 |
+
return $this->sanitize_domain( get_option( $this->prefix . 'exactdn_domain' ) );
|
496 |
}
|
|
|
|
|
497 |
|
498 |
+
/**
|
499 |
+
* Method to override the ExactDN domain at runtime, use with caution.
|
500 |
+
*
|
501 |
+
* @param string $domain The ExactDN domain to use instead.
|
502 |
+
*/
|
503 |
+
function set_domain( $domain ) {
|
504 |
+
if ( is_string( $domain ) ) {
|
505 |
+
$this->exactdn_domain = $domain;
|
506 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
507 |
}
|
508 |
+
/**
|
509 |
+
* Get the ExactDN option.
|
510 |
+
*
|
511 |
+
* @param string $option_name The name of the ExactDN option.
|
512 |
+
* @return int The numerical value of the option.
|
513 |
+
*/
|
514 |
+
function get_exactdn_option( $option_name ) {
|
515 |
+
if ( defined( 'EXACTDN_DOMAIN' ) && EXACTDN_DOMAIN ) {
|
516 |
+
return (int) get_option( $this->prefix . 'exactdn_' . $option_name );
|
517 |
+
}
|
518 |
+
if ( is_multisite() ) {
|
519 |
+
if ( ! SUBDOMAIN_INSTALL ) {
|
520 |
+
return (int) get_site_option( $this->prefix . 'exactdn_' . $option_name );
|
521 |
+
}
|
522 |
}
|
523 |
+
return (int) get_option( $this->prefix . 'exactdn_' . $option_name );
|
524 |
}
|
|
|
|
|
525 |
|
526 |
+
/**
|
527 |
+
* Set the ExactDN domain name to use.
|
528 |
+
*
|
529 |
+
* @param string $domain The ExactDN domain name for this site or network.
|
530 |
+
*/
|
531 |
+
function set_exactdn_domain( $domain ) {
|
532 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
533 |
+
if ( defined( 'EXACTDN_DOMAIN' ) && $this->sanitize_domain( EXACTDN_DOMAIN ) ) {
|
534 |
+
return true;
|
535 |
+
}
|
536 |
+
$domain = $this->sanitize_domain( $domain );
|
537 |
+
if ( ! $domain ) {
|
538 |
+
return false;
|
539 |
+
}
|
540 |
+
if ( is_multisite() ) {
|
541 |
+
if ( ! SUBDOMAIN_INSTALL ) {
|
542 |
+
update_site_option( $this->prefix . 'exactdn_domain', $domain );
|
543 |
+
return $domain;
|
544 |
+
}
|
545 |
}
|
546 |
+
update_option( $this->prefix . 'exactdn_domain', $domain );
|
547 |
+
return $domain;
|
548 |
}
|
|
|
|
|
|
|
549 |
|
550 |
+
/**
|
551 |
+
* Set an option for ExactDN.
|
552 |
+
*
|
553 |
+
* @param string $option_name The name of the ExactDN option.
|
554 |
+
* @param int $option_value The value to set for the ExactDN option.
|
555 |
+
* @param bool $autoload Optional. Whether to load the option when WordPress starts up.
|
556 |
+
*/
|
557 |
+
function set_exactdn_option( $option_name, $option_value, $autoload = null ) {
|
558 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
559 |
+
if ( defined( 'EXACTDN_DOMAIN' ) && EXACTDN_DOMAIN ) {
|
560 |
+
return update_option( $this->prefix . 'exactdn_' . $option_name, $option_value, $autoload );
|
561 |
+
}
|
562 |
+
if ( is_multisite() ) {
|
563 |
+
if ( ! SUBDOMAIN_INSTALL ) {
|
564 |
+
return update_site_option( $this->prefix . 'exactdn_' . $option_name, $option_value );
|
565 |
+
}
|
566 |
}
|
567 |
+
return update_option( $this->prefix . 'exactdn_' . $option_name, $option_value, $autoload );
|
568 |
}
|
|
|
|
|
569 |
|
570 |
+
/**
|
571 |
+
* Validate the user-defined exclusions for "all the things" rewriting.
|
572 |
+
*/
|
573 |
+
function validate_user_exclusions() {
|
574 |
+
if ( defined( 'EXACTDN_EXCLUDE' ) && EXACTDN_EXCLUDE ) {
|
575 |
+
$user_exclusions = EXACTDN_EXCLUDE;
|
576 |
+
}
|
577 |
+
if ( ! empty( $user_exclusions ) ) {
|
578 |
+
if ( is_string( $user_exclusions ) ) {
|
579 |
+
$user_exclusions = array( $user_exclusions );
|
580 |
+
}
|
581 |
+
if ( is_array( $user_exclusions ) ) {
|
582 |
+
foreach ( $user_exclusions as $exclusion ) {
|
583 |
+
if ( false !== strpos( $exclusion, 'wp-content' ) ) {
|
584 |
+
$exclusion = preg_replace( '#([^"\'?>]+?)?wp-content/#i', '', $exclusion );
|
585 |
+
}
|
586 |
+
$this->user_exclusions[] = ltrim( $exclusion, '/' );
|
587 |
}
|
|
|
588 |
}
|
589 |
}
|
590 |
}
|
|
|
591 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
592 |
/**
|
593 |
+
* Get $content_width, with a filter.
|
594 |
*
|
595 |
+
* @return bool|string The content width, if set. Default false.
|
596 |
*/
|
597 |
+
function get_content_width() {
|
598 |
+
$content_width = isset( $GLOBALS['content_width'] ) && is_numeric( $GLOBALS['content_width'] ) && $GLOBALS['content_width'] > 100 ? $GLOBALS['content_width'] : 1920;
|
599 |
+
if ( function_exists( 'twentynineteen_setup' ) && 640 === (int) $content_width ) {
|
600 |
+
$content_width = 932;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
601 |
}
|
602 |
+
/**
|
603 |
+
* Filter the Content Width value.
|
604 |
+
*
|
605 |
+
* @param string $content_width Content Width value.
|
606 |
+
*/
|
607 |
+
return (int) apply_filters( 'exactdn_content_width', $content_width );
|
608 |
+
}
|
609 |
+
|
610 |
+
/**
|
611 |
+
* Get width within an ExactDN url.
|
612 |
+
*
|
613 |
+
* @param string $url The ExactDN url to parse.
|
614 |
+
* @return string The width, if found.
|
615 |
+
*/
|
616 |
+
public function get_exactdn_width_from_url( $url ) {
|
617 |
+
$url_args = $this->parse_url( $url, PHP_URL_QUERY );
|
618 |
+
if ( ! $url_args ) {
|
619 |
+
return '';
|
620 |
}
|
621 |
+
$args = explode( '&', $url_args );
|
622 |
+
foreach ( $args as $arg ) {
|
623 |
+
if ( preg_match( '#w=(\d+)#', $arg, $width_match ) ) {
|
624 |
+
return $width_match[1];
|
625 |
+
}
|
626 |
+
if ( preg_match( '#resize=(\d+)#', $arg, $width_match ) ) {
|
627 |
+
return $width_match[1];
|
628 |
+
}
|
629 |
+
if ( preg_match( '#fit=(\d+)#', $arg, $width_match ) ) {
|
630 |
+
return $width_match[1];
|
631 |
+
}
|
632 |
}
|
633 |
+
return '';
|
634 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
635 |
|
636 |
/**
|
637 |
+
* Identify images in page content, and if images are local (uploaded to the current site), pass through ExactDN.
|
638 |
*
|
639 |
+
* @param string $content The page/post content.
|
640 |
+
* @return string The content with ExactDN image urls.
|
641 |
*/
|
642 |
+
function filter_page_output( $content ) {
|
643 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
644 |
+
$this->filtering_the_page = true;
|
645 |
|
646 |
+
$content = $this->filter_the_content( $content );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
647 |
|
648 |
+
/**
|
649 |
+
* Allow parsing the full page content after ExactDN is finished with it.
|
650 |
+
*
|
651 |
+
* @param string $content The fully-parsed HTML code of the page.
|
652 |
+
*/
|
653 |
+
$content = apply_filters( 'exactdn_the_page', $content );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
654 |
|
655 |
+
$this->filtering_the_page = false;
|
656 |
+
$this->debug_message( "parsing page took $this->elapsed_time seconds" );
|
657 |
+
return $content;
|
658 |
+
}
|
659 |
|
660 |
+
/**
|
661 |
+
* Identify images in the content, and if images are local (uploaded to the current site), pass through ExactDN.
|
662 |
+
*
|
663 |
+
* @param string $content The page/post content.
|
664 |
+
* @return string The content with ExactDN image urls.
|
665 |
+
*/
|
666 |
+
function filter_the_content( $content ) {
|
667 |
+
$started = microtime( true );
|
668 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
669 |
+
$images = $this->get_images_from_html( $content, true );
|
670 |
+
|
671 |
+
if ( ! empty( $images ) ) {
|
672 |
+
$this->debug_message( 'we have images to parse' );
|
673 |
+
$content_width = false;
|
674 |
+
if ( ! $this->filtering_the_page ) {
|
675 |
+
$this->filtering_the_content = true;
|
676 |
+
$this->debug_message( 'filtering the content' );
|
677 |
+
$content_width = $this->get_content_width();
|
678 |
}
|
679 |
+
$resize_existing = defined( 'EXACTDN_RESIZE_EXISTING' ) && EXACTDN_RESIZE_EXISTING;
|
680 |
|
681 |
+
$image_sizes = $this->image_sizes();
|
682 |
|
683 |
+
foreach ( $images[0] as $index => $tag ) {
|
684 |
+
// Default to resize, though fit may be used in certain cases where a dimension cannot be ascertained.
|
685 |
+
$transform = 'resize';
|
|
|
686 |
|
687 |
+
// Start with a clean slate each time.
|
688 |
+
$attachment_id = false;
|
689 |
+
$exactdn_url = false;
|
690 |
+
$width = false;
|
691 |
+
$lazy = false;
|
692 |
+
$srcset_fill = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
693 |
|
694 |
+
// Flag if we need to munge a fullsize URL.
|
695 |
+
$fullsize_url = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
696 |
|
697 |
+
// Identify image source.
|
698 |
+
$src = $images['img_url'][ $index ];
|
699 |
+
$src_orig = $images['img_url'][ $index ];
|
700 |
+
$this->debug_message( $src );
|
701 |
+
|
702 |
+
/**
|
703 |
+
* Allow specific images to be skipped by ExactDN.
|
704 |
+
*
|
705 |
+
* @param bool false Should ExactDN ignore this image. Default false.
|
706 |
+
* @param string $src Image URL.
|
707 |
+
* @param string $tag Image HTML Tag.
|
708 |
+
*/
|
709 |
+
if ( apply_filters( 'exactdn_skip_image', false, $src, $tag ) ) {
|
710 |
+
continue;
|
|
|
711 |
}
|
712 |
|
713 |
+
$this->debug_message( 'made it passed the filters' );
|
|
|
|
|
714 |
|
715 |
+
// Log 0-size Pinterest schema images.
|
716 |
+
if ( strpos( $tag, 'data-pin-description=' ) && strpos( $tag, 'width="0" height="0"' ) ) {
|
717 |
+
$this->debug_message( 'data-pin/Pinterest image' );
|
|
|
|
|
|
|
|
|
|
|
718 |
}
|
719 |
|
720 |
+
// Pre-empt srcset fill if the surrounding link has a background image or if there is a data-desktop attribute indicating a potential slider.
|
721 |
+
if ( strpos( $tag, 'background-image:' ) || strpos( $tag, 'data-desktop=' ) ) {
|
722 |
+
$srcset_fill = false;
|
723 |
+
}
|
724 |
+
/**
|
725 |
+
* Documented in generate_url, in this case used to detect images that should bypass srcset fill.
|
726 |
+
*
|
727 |
+
* @param array|string $args Array of ExactDN arguments.
|
728 |
+
* @param string $image_url Image URL.
|
729 |
+
* @param string|null $scheme Image scheme. Default to null.
|
730 |
+
*/
|
731 |
+
$args = apply_filters( 'exactdn_pre_args', array( 'test' => 'lazy-test' ), $src, null );
|
732 |
+
if ( empty( $args ) ) {
|
733 |
+
$srcset_fill = false;
|
734 |
+
}
|
735 |
+
// Support Lazy Load plugins.
|
736 |
+
// Don't modify $tag yet as we need unmodified version later.
|
737 |
+
$lazy_load_src = $this->get_attribute( $images['img_tag'][ $index ], 'data-lazy-src' );
|
738 |
+
if ( $lazy_load_src ) {
|
739 |
+
$placeholder_src = $src;
|
740 |
+
$placeholder_src_orig = $src;
|
741 |
+
$src = $lazy_load_src;
|
742 |
+
$src_orig = $lazy_load_src;
|
743 |
+
$this->srcset_attr = 'data-lazy-srcset';
|
744 |
+
$lazy = true;
|
745 |
+
$srcset_fill = true;
|
746 |
}
|
747 |
+
// Must be a legacy Jetpack thing as far as I can tell, no matches found in any currently installed plugins.
|
748 |
+
$lazy_load_src = $this->get_attribute( $images['img_tag'][ $index ], 'data-lazy-original' );
|
749 |
+
if ( ! $lazy && $lazy_load_src ) {
|
750 |
+
$placeholder_src = $src;
|
751 |
+
$placeholder_src_orig = $src;
|
752 |
+
$src = $lazy_load_src;
|
753 |
+
$src_orig = $lazy_load_src;
|
754 |
+
$lazy = true;
|
755 |
}
|
756 |
+
if ( ! $lazy && strpos( $images['img_tag'][ $index ], 'a3-lazy-load/assets/images/lazy_placeholder' ) ) {
|
757 |
+
$lazy_load_src = $this->get_attribute( $images['img_tag'][ $index ], 'data-src' );
|
|
|
758 |
}
|
759 |
+
if (
|
760 |
+
! $lazy &&
|
761 |
+
strpos( $images['img_tag'][ $index ], ' data-src=' ) &&
|
762 |
+
strpos( $images['img_tag'][ $index ], 'lazyload' ) &&
|
763 |
+
(
|
764 |
+
strpos( $images['img_tag'][ $index ], 'data:image/gif' ) ||
|
765 |
+
strpos( $images['img_tag'][ $index ], 'data:image/svg' )
|
766 |
+
)
|
767 |
+
) {
|
768 |
+
$lazy_load_src = $this->get_attribute( $images['img_tag'][ $index ], 'data-src' );
|
769 |
+
$this->debug_message( "found eio ll src: $lazy_load_src" );
|
770 |
+
}
|
771 |
+
if ( ! $lazy && $lazy_load_src ) {
|
772 |
+
$placeholder_src = $src;
|
773 |
+
$placeholder_src_orig = $src;
|
774 |
+
$src = $lazy_load_src;
|
775 |
+
$src_orig = $lazy_load_src;
|
776 |
+
$this->srcset_attr = 'data-srcset';
|
777 |
+
$lazy = true;
|
778 |
+
$srcset_fill = true;
|
779 |
+
}
|
780 |
+
if ( ! $lazy && strpos( $images['img_tag'][ $index ], 'revslider/admin/assets/images/dummy' ) ) {
|
781 |
+
$lazy_load_src = $this->get_attribute( $images['img_tag'][ $index ], 'data-lazyload' );
|
782 |
+
}
|
783 |
+
if ( ! $lazy && $lazy_load_src ) {
|
784 |
+
$placeholder_src = $src;
|
785 |
+
$placeholder_src_orig = $src;
|
786 |
+
$src = $lazy_load_src;
|
787 |
+
$src_orig = $lazy_load_src;
|
788 |
+
$lazy = true;
|
789 |
+
}
|
790 |
+
|
791 |
+
// Check for relative urls that start with a slash. Unlikely that we'll attempt relative urls beyond that.
|
792 |
+
if (
|
793 |
+
'/' === substr( $src, 0, 1 ) &&
|
794 |
+
'/' !== substr( $src, 1, 1 ) &&
|
795 |
+
false === strpos( $this->upload_domain, 'amazonaws.com' ) &&
|
796 |
+
false === strpos( $this->upload_domain, 'digitaloceanspaces.com' )
|
797 |
+
) {
|
798 |
+
$src = '//' . $this->upload_domain . $src;
|
799 |
+
}
|
800 |
+
|
801 |
+
// Check if image URL should be used with ExactDN.
|
802 |
+
if ( $this->validate_image_url( $src ) ) {
|
803 |
+
$this->debug_message( 'url validated' );
|
804 |
+
|
805 |
+
// Find the width and height attributes.
|
806 |
+
$width = $this->get_img_width( $images['img_tag'][ $index ] );
|
807 |
+
$height = $this->get_attribute( $images['img_tag'][ $index ], 'height' );
|
808 |
+
// Falsify them if empty.
|
809 |
+
$width = $width ? $width : false;
|
810 |
+
$height = $height ? $height : false;
|
811 |
+
|
812 |
+
// Can't pass both a relative width and height, so unset the dimensions in favor of not breaking the horizontal layout.
|
813 |
+
if ( false !== strpos( $width, '%' ) && false !== strpos( $height, '%' ) ) {
|
814 |
+
$width = false;
|
815 |
+
$height = false;
|
816 |
+
}
|
817 |
+
|
818 |
+
// Detect WP registered image size from HTML class.
|
819 |
+
if ( preg_match( '#class=["|\']?[^"\']*size-([^"\'\s]+)[^"\']*["|\']?#i', $images['img_tag'][ $index ], $size ) ) {
|
820 |
+
$size = array_pop( $size );
|
821 |
+
|
822 |
+
$this->debug_message( "detected $size" );
|
823 |
+
if ( false === $width && false === $height && 'full' !== $size && array_key_exists( $size, $image_sizes ) ) {
|
824 |
+
$width = (int) $image_sizes[ $size ]['width'];
|
825 |
+
$height = (int) $image_sizes[ $size ]['height'];
|
826 |
+
$transform = $image_sizes[ $size ]['crop'] ? 'resize' : 'fit';
|
827 |
+
}
|
828 |
+
} else {
|
829 |
+
unset( $size );
|
830 |
+
}
|
831 |
+
|
832 |
+
list( $filename_width, $filename_height ) = $this->get_dimensions_from_filename( $src );
|
833 |
+
if ( false === $width && false === $height ) {
|
834 |
+
$width = $filename_width;
|
835 |
+
$height = $filename_height;
|
836 |
+
}
|
837 |
+
// WP Attachment ID, if uploaded to this site.
|
838 |
+
$attachment_id = $this->get_attribute( $images['img_tag'][ $index ], 'data-id' );
|
839 |
+
if ( empty( $attachment_id ) ) {
|
840 |
+
$this->debug_message( 'data-id not found, looking for wp-image-x in class' );
|
841 |
+
preg_match( '#class=["|\']?[^"\']*wp-image-([\d]+)[^"\']*["|\']?#i', $images['img_tag'][ $index ], $attachment_id );
|
842 |
}
|
843 |
+
if ( ! $this->get_option( 'exactdn_prevent_db_queries' ) && empty( $attachment_id ) ) {
|
844 |
+
$this->debug_message( 'looking for attachment id' );
|
845 |
+
$attachment_id = attachment_url_to_postid( $src );
|
846 |
+
}
|
847 |
+
if ( ! $this->get_option( 'exactdn_prevent_db_queries' ) && ! empty( $attachment_id ) ) {
|
848 |
+
if ( is_array( $attachment_id ) ) {
|
849 |
+
$attachment_id = intval( array_pop( $attachment_id ) );
|
850 |
+
}
|
851 |
+
$this->debug_message( "using attachment id ($attachment_id) to get source image" );
|
852 |
+
|
853 |
+
if ( $attachment_id ) {
|
854 |
+
$this->debug_message( "detected attachment $attachment_id" );
|
855 |
+
$attachment = get_post( $attachment_id );
|
856 |
+
|
857 |
+
// Basic check on returned post object.
|
858 |
+
if ( is_object( $attachment ) && ! is_wp_error( $attachment ) && 'attachment' === $attachment->post_type ) {
|
859 |
+
$src_per_wp = wp_get_attachment_image_src( $attachment_id, 'full' );
|
860 |
+
|
861 |
+
if ( $src_per_wp && is_array( $src_per_wp ) ) {
|
862 |
+
$this->debug_message( "src retrieved from db: {$src_per_wp[0]}, checking for match" );
|
863 |
+
$fullsize_url_path = $this->parse_url( $src_per_wp[0], PHP_URL_PATH );
|
864 |
+
if ( is_null( $fullsize_url_path ) ) {
|
865 |
+
$src_per_wp = false;
|
866 |
+
} elseif ( $fullsize_url_path ) {
|
867 |
+
$fullsize_url_basename = pathinfo( $fullsize_url_path, PATHINFO_FILENAME );
|
868 |
+
$this->debug_message( "looking for $fullsize_url_basename in $src" );
|
869 |
+
if ( strpos( wp_basename( $src ), $fullsize_url_basename ) === false ) {
|
870 |
+
$this->debug_message( 'fullsize url does not match' );
|
871 |
+
$src_per_wp = false;
|
872 |
+
}
|
873 |
+
} else {
|
874 |
$src_per_wp = false;
|
875 |
}
|
|
|
|
|
876 |
}
|
|
|
877 |
|
878 |
+
if ( $src_per_wp && $this->validate_image_url( $src_per_wp[0] ) ) {
|
879 |
+
$this->debug_message( "detected $width filenamew $filename_width" );
|
880 |
+
if ( $resize_existing || ( $width && (int) $filename_width !== (int) $width ) ) {
|
881 |
+
$this->debug_message( 'resizing existing or width does not match' );
|
882 |
+
$src = $src_per_wp[0];
|
883 |
+
}
|
884 |
+
$fullsize_url = true;
|
885 |
|
886 |
+
// Prevent image distortion if a detected dimension exceeds the image's natural dimensions.
|
887 |
+
if ( ( false !== $width && $width > $src_per_wp[1] ) || ( false !== $height && $height > $src_per_wp[2] ) ) {
|
888 |
+
$width = false === $width ? false : min( $width, $src_per_wp[1] );
|
889 |
+
$height = false === $height ? false : min( $height, $src_per_wp[2] );
|
890 |
+
$this->debug_message( "constrained to attachment dims, w=$width and h=$height" );
|
891 |
+
}
|
892 |
|
893 |
+
// If no width and height are found, max out at source image's natural dimensions.
|
894 |
+
// Otherwise, respect registered image sizes' cropping setting.
|
895 |
+
if ( false === $width && false === $height ) {
|
896 |
+
$width = $src_per_wp[1];
|
897 |
+
$height = $src_per_wp[2];
|
898 |
+
$transform = 'fit';
|
899 |
+
$this->debug_message( "no dims, using attachment dims, w=$width and h=$height" );
|
900 |
+
} elseif ( isset( $size ) && array_key_exists( $size, $image_sizes ) && isset( $image_sizes[ $size ]['crop'] ) ) {
|
901 |
+
$transform = (bool) $image_sizes[ $size ]['crop'] ? 'resize' : 'fit';
|
902 |
+
$this->debug_message( 'attachment size set to crop' );
|
903 |
+
}
|
904 |
}
|
905 |
+
} else {
|
906 |
+
unset( $attachment_id );
|
907 |
+
unset( $attachment );
|
908 |
}
|
|
|
|
|
|
|
909 |
}
|
910 |
}
|
911 |
+
$constrain_width = (int) $content_width;
|
912 |
+
if ( ! empty( $images['figure_class'][ $index ] ) && false !== strpos( $images['figure_class'][ $index ], 'alignfull' ) && current_theme_supports( 'align-wide' ) ) {
|
913 |
+
$constrain_width = (int) apply_filters( 'exactdn_full_align_image_width', max( 1920, $content_width ) );
|
914 |
+
} elseif ( ! empty( $images['figure_class'][ $index ] ) && false !== strpos( $images['figure_class'][ $index ], 'alignwide' ) && current_theme_supports( 'align-wide' ) ) {
|
915 |
+
$constrain_width = (int) apply_filters( 'exactdn_wide_align_image_width', max( 1500, $content_width ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
916 |
}
|
917 |
+
// If width is available, constrain to $content_width.
|
918 |
+
if ( false !== $width && false === strpos( $width, '%' ) && is_numeric( $constrain_width ) ) {
|
919 |
+
if ( $width > $constrain_width && false !== $height && false === strpos( $height, '%' ) ) {
|
920 |
+
$this->debug_message( 'constraining to content width' );
|
921 |
+
$height = round( ( $constrain_width * $height ) / $width );
|
922 |
+
$width = $constrain_width;
|
923 |
+
} elseif ( $width > $constrain_width ) {
|
924 |
+
$this->debug_message( 'constraining to content width' );
|
925 |
+
$width = $constrain_width;
|
926 |
+
}
|
927 |
}
|
|
|
928 |
|
929 |
+
// Set a width if none is found and $content_width is available.
|
930 |
+
// If width is set in this manner and height is available, use `fit` instead of `resize` to prevent skewing.
|
931 |
+
if ( false === $width && is_numeric( $constrain_width ) ) {
|
932 |
+
$width = (int) $constrain_width;
|
933 |
|
934 |
+
if ( false !== $height ) {
|
935 |
+
$transform = 'fit';
|
936 |
+
}
|
937 |
+
}
|
938 |
|
939 |
+
// Detect if image source is for a custom-cropped thumbnail and prevent further URL manipulation.
|
940 |
+
if ( ! $fullsize_url && preg_match_all( '#-e[a-z0-9]+(-\d+x\d+)?\.(' . implode( '|', $this->extensions ) . '){1}$#i', wp_basename( $src ), $filename ) ) {
|
941 |
+
$fullsize_url = true;
|
942 |
+
}
|
|
|
|
|
|
|
943 |
|
944 |
+
// Build array of ExactDN args and expose to filter before passing to ExactDN URL function.
|
|
|
945 |
$args = array();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
946 |
|
947 |
+
if ( false !== $width && false !== $height && false === strpos( $width, '%' ) && false === strpos( $height, '%' ) ) {
|
948 |
+
$args[ $transform ] = $width . ',' . $height;
|
949 |
+
} elseif ( false !== $width ) {
|
950 |
+
$args['w'] = $width;
|
951 |
+
} elseif ( false !== $height ) {
|
952 |
+
$args['h'] = $height;
|
953 |
+
}
|
954 |
|
955 |
+
if ( ! $resize_existing && ( ! $width || (int) $filename_width === (int) $width ) ) {
|
956 |
+
$this->debug_message( 'preventing resize' );
|
957 |
+
$args = array();
|
958 |
+
} elseif ( ! $fullsize_url ) {
|
959 |
+
// Build URL, first maybe removing WP's resized string so we pass the original image to ExactDN (for higher quality).
|
960 |
+
$src = $this->strip_image_dimensions_maybe( $src );
|
961 |
+
}
|
962 |
|
963 |
+
if ( ! $this->get_option( 'exactdn_prevent_db_queries' ) && ! empty( $attachment_id ) ) {
|
964 |
+
$this->debug_message( 'using attachment id to check smart crop' );
|
965 |
+
$args = $this->maybe_smart_crop( $args, $attachment_id );
|
966 |
}
|
967 |
|
968 |
+
/**
|
969 |
+
* Filter the array of ExactDN arguments added to an image.
|
970 |
+
* By default, only includes width and height values.
|
971 |
+
*
|
972 |
+
* @param array $args Array of ExactDN Arguments.
|
973 |
+
* @param array $args {
|
974 |
+
* Array of image details.
|
975 |
+
*
|
976 |
+
* @type $tag Image tag (Image HTML output).
|
977 |
+
* @type $src Image URL.
|
978 |
+
* @type $src_orig Original Image URL.
|
979 |
+
* @type $width Image width.
|
980 |
+
* @type $height Image height.
|
981 |
+
* }
|
982 |
+
*/
|
983 |
+
$args = apply_filters( 'exactdn_post_image_args', $args, compact( 'tag', 'src', 'src_orig', 'width', 'height' ) );
|
984 |
+
$this->debug_message( "width $width" );
|
985 |
+
$this->debug_message( "height $height" );
|
986 |
+
$this->debug_message( "transform $transform" );
|
987 |
+
|
988 |
+
$exactdn_url = $this->generate_url( $src, $args );
|
989 |
+
$this->debug_message( "new url $exactdn_url" );
|
990 |
+
|
991 |
+
// Modify image tag if ExactDN function provides a URL
|
992 |
+
// Ensure changes are only applied to the current image by copying and modifying the matched tag, then replacing the entire tag with our modified version.
|
993 |
+
if ( $src !== $exactdn_url ) {
|
994 |
+
$new_tag = $tag;
|
995 |
+
|
996 |
+
// If present, replace the link href with an ExactDN URL for the full-size image.
|
997 |
+
if ( ! empty( $images['link_url'][ $index ] ) && $this->validate_image_url( $images['link_url'][ $index ] ) ) {
|
998 |
+
$new_tag = preg_replace( '#(href=["|\'])' . $images['link_url'][ $index ] . '(["|\'])#i', '\1' . $this->generate_url( $images['link_url'][ $index ] ) . '\2', $new_tag, 1 );
|
999 |
}
|
|
|
1000 |
|
1001 |
+
// Insert new image src into the srcset as well, if we have a width.
|
1002 |
+
if ( false !== $width && false === strpos( $width, '%' ) && $width ) {
|
1003 |
+
$this->debug_message( 'checking to see if srcset width already exists' );
|
1004 |
+
$srcset_url = $exactdn_url . ' ' . (int) $width . 'w, ';
|
1005 |
+
$new_srcset_attr = $this->get_attribute( $new_tag, $this->srcset_attr );
|
1006 |
+
if ( $new_srcset_attr && false === strpos( $new_srcset_attr, ' ' . (int) $width . 'w' ) && ! preg_match( '/\s(1|2|3)x/', $new_srcset_attr ) ) {
|
1007 |
+
$this->debug_message( 'src not in srcset, adding' );
|
1008 |
+
$this->set_attribute( $new_tag, $this->srcset_attr, $srcset_url . $new_srcset_attr, true );
|
1009 |
+
}
|
1010 |
}
|
|
|
1011 |
|
1012 |
+
// Check if content width pushed the respimg sizes attribute too far down.
|
1013 |
+
if ( ! empty( $constrain_width ) && (int) $constrain_width !== (int) $content_width ) {
|
1014 |
+
$sizes_attr = $this->get_attribute( $new_tag, 'sizes' );
|
1015 |
+
$new_sizes_attr = str_replace( ' ' . $content_width . 'px', ' ' . $constrain_width . 'px', $sizes_attr );
|
1016 |
+
if ( $sizes_attr !== $new_sizes_attr ) {
|
1017 |
+
$new_tag = str_replace( $sizes_attr, $new_sizes_attr, $new_tag );
|
1018 |
+
}
|
1019 |
+
}
|
1020 |
|
1021 |
+
// Cleanup ExactDN URL.
|
1022 |
+
$exactdn_url = str_replace( '&', '&', esc_url( $exactdn_url ) );
|
1023 |
+
// Supplant the original source value with our ExactDN URL.
|
1024 |
+
$this->debug_message( "replacing $src_orig with $exactdn_url" );
|
1025 |
+
$new_tag = str_replace( $src_orig, $exactdn_url, $new_tag );
|
1026 |
|
1027 |
+
// If Lazy Load is in use, pass placeholder image through ExactDN.
|
1028 |
+
if ( isset( $placeholder_src ) && $this->validate_image_url( $placeholder_src ) ) {
|
1029 |
+
$placeholder_src = $this->generate_url( $placeholder_src );
|
1030 |
|
1031 |
+
if ( $placeholder_src !== $placeholder_src_orig ) {
|
1032 |
+
$new_tag = str_replace( $placeholder_src_orig, str_replace( '&', '&', esc_url( $placeholder_src ) ), $new_tag );
|
1033 |
+
}
|
1034 |
|
1035 |
+
unset( $placeholder_src );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1036 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1037 |
|
1038 |
+
// Replace original tag with modified version.
|
1039 |
+
$content = str_replace( $tag, $new_tag, $content );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1040 |
}
|
1041 |
+
} elseif ( ! $lazy && $this->validate_image_url( $src, true ) ) {
|
1042 |
+
$this->debug_message( "found a potential exactdn src url to insert into srcset: $src" );
|
1043 |
+
// Find the width attribute.
|
1044 |
+
$width = $this->get_img_width( $images['img_tag'][ $index ] );
|
1045 |
+
if ( $width ) {
|
1046 |
+
$this->debug_message( 'found the width' );
|
1047 |
+
// Insert new image src into the srcset as well, if we have a width.
|
1048 |
+
if (
|
1049 |
+
false !== $width &&
|
1050 |
+
false === strpos( $width, '%' ) &&
|
1051 |
+
false !== strpos( $src, $width ) &&
|
1052 |
+
false !== strpos( $src, $this->exactdn_domain )
|
1053 |
+
) {
|
1054 |
+
$new_tag = $tag;
|
1055 |
+
$exactdn_url = $src;
|
1056 |
+
$this->debug_message( 'checking to see if srcset width already exists' );
|
1057 |
+
$srcset_url = $exactdn_url . ' ' . (int) $width . 'w, ';
|
1058 |
+
$new_srcset_attr = $this->get_attribute( $new_tag, $this->srcset_attr );
|
1059 |
+
if ( $new_srcset_attr && false === strpos( $new_srcset_attr, ' ' . (int) $width . 'w' ) && ! preg_match( '/\s(1|2|3)x/', $new_srcset_attr ) ) {
|
1060 |
+
$this->debug_message( 'src not in srcset, adding' );
|
1061 |
+
$this->set_attribute( $new_tag, $this->srcset_attr, $srcset_url . $new_srcset_attr, true );
|
1062 |
+
// Replace original tag with modified version.
|
1063 |
+
$content = str_replace( $tag, $new_tag, $content );
|
1064 |
+
}
|
1065 |
+
}
|
1066 |
}
|
1067 |
+
} elseif ( $lazy && ! empty( $placeholder_src ) && $this->validate_image_url( $placeholder_src ) ) {
|
1068 |
+
$new_tag = $tag;
|
1069 |
+
// If Lazy Load is in use, pass placeholder image through ExactDN.
|
1070 |
+
$placeholder_src = $this->generate_url( $placeholder_src );
|
1071 |
+
if ( $placeholder_src !== $placeholder_src_orig ) {
|
1072 |
+
$new_tag = str_replace( $placeholder_src_orig, str_replace( '&', '&', esc_url( $placeholder_src ) ), $new_tag );
|
1073 |
+
// Replace original tag with modified version.
|
1074 |
+
$content = str_replace( $tag, $new_tag, $content );
|
1075 |
}
|
1076 |
+
unset( $placeholder_src );
|
1077 |
+
} // End if().
|
1078 |
+
|
1079 |
+
// At this point, we discard the original src in favor of the ExactDN url.
|
1080 |
+
if ( ! empty( $exactdn_url ) ) {
|
1081 |
+
$src = $exactdn_url;
|
1082 |
+
}
|
1083 |
+
if ( $srcset_fill && ( ! defined( 'EXACTDN_PREVENT_SRCSET_FILL' ) || ! EXACTDN_PREVENT_SRCSET_FILL ) && false !== strpos( $src, $this->exactdn_domain ) ) {
|
1084 |
+
if ( ! $this->get_attribute( $images['img_tag'][ $index ], $this->srcset_attr ) && ! $this->get_attribute( $images['img_tag'][ $index ], 'sizes' ) ) {
|
1085 |
+
$this->debug_message( "srcset filling with $src" );
|
1086 |
+
$zoom = false;
|
1087 |
+
// If $width is empty, we'll search the url for a width param, then we try searching the img element, with fall back to the filename.
|
1088 |
+
if ( empty( $width ) || ! is_numeric( $width ) ) {
|
1089 |
+
// This only searches for w, resize, or fit flags, others are ignored.
|
1090 |
+
$width = $this->get_exactdn_width_from_url( $src );
|
1091 |
+
if ( $width ) {
|
1092 |
+
$zoom = true;
|
1093 |
+
}
|
1094 |
+
}
|
1095 |
+
if ( empty( $width ) || ! is_numeric( $width ) ) {
|
1096 |
+
$width = $this->get_img_width( $images['img_tag'][ $index ] );
|
1097 |
+
}
|
1098 |
+
list( $filename_width, $discard_height ) = $this->get_dimensions_from_filename( $src );
|
1099 |
+
if ( empty( $width ) || ! is_numeric( $width ) ) {
|
1100 |
+
$width = $filename_width;
|
1101 |
+
}
|
1102 |
+
if ( empty( $width ) || ! is_numeric( $width ) ) {
|
1103 |
+
$width = $this->get_attribute( $images['img_tag'][ $index ], 'data-actual-width' );
|
1104 |
+
}
|
1105 |
+
if ( false !== strpos( $src, 'crop=' ) || false !== strpos( $src, '&h=' ) || false !== strpos( $src, '?h=' ) ) {
|
1106 |
+
$width = false;
|
1107 |
+
}
|
1108 |
+
// Then add a srcset and sizes.
|
1109 |
+
if ( $width ) {
|
1110 |
+
$srcset = $this->generate_image_srcset( $src, $width, $zoom, $filename_width );
|
1111 |
+
if ( $srcset ) {
|
1112 |
+
$new_tag = $images['img_tag'][ $index ];
|
1113 |
+
$this->set_attribute( $new_tag, $this->srcset_attr, $srcset );
|
1114 |
+
$this->set_attribute( $new_tag, 'sizes', sprintf( '(max-width: %1$dpx) 100vw, %1$dpx', $width ) );
|
1115 |
+
// Replace original tag with modified version.
|
1116 |
+
$content = str_replace( $images['img_tag'][ $index ], $new_tag, $content );
|
1117 |
+
}
|
1118 |
}
|
1119 |
}
|
1120 |
}
|
1121 |
+
} // End foreach().
|
1122 |
+
} // End if();
|
1123 |
+
$content = $this->filter_bg_images( $content, 'div' );
|
1124 |
+
$content = $this->filter_bg_images( $content, 'li' );
|
1125 |
+
$content = $this->filter_bg_images( $content, 'span' );
|
1126 |
+
$content = $this->filter_bg_images( $content, 'section' );
|
1127 |
+
if ( $this->filtering_the_page ) {
|
1128 |
+
$content = $this->filter_prz_thumb( $content );
|
1129 |
+
}
|
1130 |
+
if ( $this->filtering_the_page && $this->get_option( 'exactdn_all_the_things' ) ) {
|
1131 |
+
$this->debug_message( 'rewriting all other wp_content urls' );
|
1132 |
+
if ( $this->exactdn_domain && $this->upload_domain ) {
|
1133 |
+
$escaped_upload_domain = str_replace( '.', '\.', ltrim( $this->upload_domain, 'w.' ) );
|
1134 |
+
$this->debug_message( $escaped_upload_domain );
|
1135 |
+
if ( ! empty( $this->user_exclusions ) ) {
|
1136 |
+
$content = preg_replace( '#(https?:)?//(?:www\.)?' . $escaped_upload_domain . '([^"\'?>]+?)?/wp-content/([^"\'?>]+?)?(' . implode( '|', $this->user_exclusions ) . ')#i', '$1//' . $this->upload_domain . '$2/?wpcontent-bypass?/$3$4', $content );
|
1137 |
+
}
|
1138 |
+
if ( strpos( $content, '<use ' ) ) {
|
1139 |
+
// Pre-empt rewriting of files within <use> tags, particularly to prevent security errors for SVGs.
|
1140 |
+
$content = preg_replace( '#(<use.+?href=["\'])(https?:)?//(?:www\.)?' . $escaped_upload_domain . '([^"\'?>]+?)/wp-content/#is', '$1$2//' . $this->upload_domain . '$3/?wpcontent-bypass?/', $content );
|
1141 |
+
}
|
1142 |
+
// Pre-empt rewriting of wp-includes and wp-content if the extension is not allowed by using a temporary placeholder.
|
1143 |
+
$content = preg_replace( '#(https?:)?//(?:www\.)?' . $escaped_upload_domain . '([^"\'?>]+?)?/wp-content/([^"\'?>]+?)\.(htm|html|php|ashx|m4v|mov|wvm|qt|webm|ogv|mp4|m4p|mpg|mpeg|mpv)#i', '$1//' . $this->upload_domain . '$2/?wpcontent-bypass?/$3.$4', $content );
|
1144 |
+
$content = str_replace( 'wp-content/themes/jupiter"', '?wpcontent-bypass?/themes/jupiter"', $content );
|
1145 |
+
$content = str_replace( 'wp-content/plugins/anti-captcha/', '?wpcontent-bypass?/plugins/anti-captcha', $content );
|
1146 |
+
if ( strpos( $this->upload_domain, 'amazonaws.com' ) || strpos( $this->upload_domain, 'digitaloceanspaces.com' ) ) {
|
1147 |
+
$content = preg_replace( '#(https?:)?//(?:www\.)?' . $escaped_upload_domain . $this->remove_path . '/#i', '$1//' . $this->exactdn_domain . '/', $content );
|
1148 |
+
} else {
|
1149 |
+
$content = preg_replace( '#(https?:)?//(?:www\.)?' . $escaped_upload_domain . '/([^"\'?>]+?)?(nextgen-image|wp-includes|wp-content)/#i', '$1//' . $this->exactdn_domain . '/$2$3/', $content );
|
1150 |
+
}
|
1151 |
+
$content = str_replace( '?wpcontent-bypass?', 'wp-content', $content );
|
1152 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1153 |
}
|
1154 |
+
$this->debug_message( 'done parsing page' );
|
1155 |
+
$this->filtering_the_content = false;
|
1156 |
+
|
1157 |
+
$elapsed_time = microtime( true ) - $started;
|
1158 |
+
$this->debug_message( "parsing the_content took $elapsed_time seconds" );
|
1159 |
+
$this->elapsed_time += microtime( true ) - $started;
|
1160 |
+
$this->debug_message( "parsing the page took $this->elapsed_time seconds so far" );
|
1161 |
+
if ( ! $this->get_option( 'exactdn_prevent_db_queries' ) && $this->elapsed_time > .5 ) {
|
1162 |
+
$this->set_option( 'exactdn_prevent_db_queries', true );
|
1163 |
+
}
|
1164 |
+
return $content;
|
1165 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1166 |
|
1167 |
+
/**
|
1168 |
+
* Parse page content looking for elements with CSS background-image properties.
|
1169 |
+
*
|
1170 |
+
* @param string $content The HTML content to parse.
|
1171 |
+
* @param string $tag_type The type of HTML tag to look for.
|
1172 |
+
* @return string The filtered HTML content.
|
1173 |
+
*/
|
1174 |
+
function filter_bg_images( $content, $tag_type ) {
|
1175 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
1176 |
+
$content_width = false;
|
1177 |
+
if ( ! $this->filtering_the_page ) {
|
1178 |
+
$content_width = $this->get_content_width();
|
1179 |
+
}
|
1180 |
+
$this->debug_message( "content width is $content_width" );
|
1181 |
+
// Process background images on elements.
|
1182 |
+
$elements = $this->get_elements_from_html( $content, $tag_type );
|
1183 |
+
if ( $this->is_iterable( $elements ) ) {
|
1184 |
+
foreach ( $elements as $index => $element ) {
|
1185 |
+
$this->debug_message( "parsing a $tag_type" );
|
1186 |
+
if ( false === strpos( $element, 'background:' ) && false === strpos( $element, 'background-image:' ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1187 |
continue;
|
1188 |
}
|
1189 |
+
$style = $this->get_attribute( $element, 'style' );
|
1190 |
+
if ( empty( $style ) ) {
|
1191 |
+
continue;
|
|
|
|
|
|
|
|
|
|
|
1192 |
}
|
1193 |
+
$this->debug_message( "checking style attr for background-image: $style" );
|
1194 |
+
$bg_image_url = $this->get_background_image_url( $style );
|
1195 |
+
if ( $this->validate_image_url( $bg_image_url ) ) {
|
1196 |
+
/** This filter is already documented in class-exactdn.php */
|
1197 |
+
if ( apply_filters( 'exactdn_skip_image', false, $bg_image_url, $element ) ) {
|
1198 |
+
continue;
|
1199 |
+
}
|
1200 |
+
$args = array();
|
1201 |
+
$element_class = $this->get_attribute( $element, 'class' );
|
1202 |
+
if ( false !== strpos( $element_class, 'alignfull' ) && current_theme_supports( 'align-wide' ) ) {
|
1203 |
+
$args['w'] = apply_filters( 'exactdn_full_align_bgimage_width', 1920, $bg_image_url );
|
1204 |
+
} elseif ( false !== strpos( $element_class, 'alignwide' ) && current_theme_supports( 'align-wide' ) ) {
|
1205 |
+
$args['w'] = apply_filters( 'exactdn_wide_align_bgimage_width', 1500, $bg_image_url );
|
1206 |
+
} elseif ( 'div' === $tag_type && $content_width ) {
|
1207 |
+
$args['w'] = apply_filters( 'exactdn_content_bgimage_width', $content_width, $bg_image_url );
|
1208 |
+
}
|
1209 |
+
if ( isset( $args['w'] ) && empty( $args['w'] ) ) {
|
1210 |
+
unset( $args['w'] );
|
1211 |
+
}
|
1212 |
+
$exactdn_bg_image_url = $this->generate_url( $bg_image_url, $args );
|
1213 |
+
if ( $bg_image_url !== $exactdn_bg_image_url ) {
|
1214 |
+
$new_style = str_replace( $bg_image_url, $exactdn_bg_image_url, $style );
|
1215 |
+
$element = str_replace( $style, $new_style, $element );
|
1216 |
+
}
|
1217 |
}
|
1218 |
+
if ( $element !== $elements[ $index ] ) {
|
1219 |
+
$content = str_replace( $elements[ $index ], $element, $content );
|
|
|
|
|
1220 |
}
|
1221 |
}
|
|
|
|
|
|
|
1222 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1223 |
return $content;
|
1224 |
}
|
1225 |
+
|
1226 |
+
/**
|
1227 |
+
* Parse page content looking for thumburl from personalization.com.
|
1228 |
+
*
|
1229 |
+
* @param string $content The HTML content to parse.
|
1230 |
+
* @return string The filtered HTML content.
|
1231 |
+
*/
|
1232 |
+
function filter_prz_thumb( $content ) {
|
1233 |
+
if ( ! class_exists( 'WooCommerce' ) || false === strpos( $content, 'productDetailsForPrz' ) ) {
|
1234 |
+
return $content;
|
1235 |
+
}
|
1236 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
1237 |
+
$prz_match = preg_match( '#productDetailsForPrz=[^<]+?thumbnailUrl:\'([^\']+?)\'[^<]+?</script>#', $content, $prz_detail_matches );
|
1238 |
+
if ( $prz_match && ! empty( $prz_detail_matches[1] ) && $this->validate_image_url( $prz_detail_matches[1] ) ) {
|
1239 |
+
$prz_thumb = $this->generate_url( $prz_detail_matches[1], apply_filters( 'exactdn_personalizationdotcom_thumb_args', '', $prz_detail_matches[1] ) );
|
1240 |
+
if ( $prz_thumb !== $prz_detail_matches ) {
|
1241 |
+
$content = str_replace( "thumbnailUrl:'{$prz_detail_matches[1]}'", "thumbnailUrl:'$prz_thumb'", $content );
|
1242 |
+
}
|
1243 |
}
|
1244 |
+
return $content;
|
1245 |
}
|
|
|
|
|
1246 |
|
1247 |
+
/**
|
1248 |
+
* Allow resizing of images for some admin-ajax requests.
|
1249 |
+
*
|
1250 |
+
* @param bool $allow Will normally be false, unless already modified by another function.
|
1251 |
+
* @param array $image Bunch of information about the image, but we don't care about that here.
|
1252 |
+
* @return bool True if it's an allowable admin-ajax request, false for all other admin requests.
|
1253 |
+
*/
|
1254 |
+
function allow_admin_image_downsize( $allow, $image ) {
|
1255 |
+
if ( ! wp_doing_ajax() ) {
|
1256 |
+
return $allow;
|
1257 |
+
}
|
1258 |
+
if ( ! empty( $_POST['action'] ) && 'eddvbugm_viewport_downloads' === $_POST['action'] ) {
|
1259 |
+
return true;
|
1260 |
+
}
|
1261 |
+
if ( ! empty( $_POST['action'] ) && 'vc_get_vc_grid_data' === $_POST['action'] ) {
|
1262 |
+
return true;
|
1263 |
+
}
|
1264 |
+
if ( ! empty( $_POST['action'] ) && 'Essential_Grid_Front_request_ajax' === $_POST['action'] ) {
|
1265 |
+
return true;
|
1266 |
+
}
|
1267 |
+
if ( ! empty( $_POST['action'] ) && 'mabel-rpn-getnew-purchased-products' === $_POST['action'] ) {
|
1268 |
+
return true;
|
1269 |
+
}
|
1270 |
return $allow;
|
1271 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1272 |
|
1273 |
+
/**
|
1274 |
+
* Disable resizing of images during image_downsize().
|
1275 |
+
*
|
1276 |
+
* @param mixed $param Could be anything (or nothing), we just pass it along untouched.
|
1277 |
+
* @return mixed Just the same value, going back out the door.
|
1278 |
+
*/
|
1279 |
+
function disable_image_downsize( $param = false ) {
|
1280 |
+
remove_filter( 'image_downsize', array( $this, 'filter_image_downsize' ) );
|
1281 |
+
add_action( 'themify_after_post_image', array( $this, 'enable_image_downsize' ) );
|
1282 |
+
return $param;
|
1283 |
+
}
|
1284 |
|
1285 |
+
/**
|
1286 |
+
* Re-enable resizing of images during image_downsize().
|
1287 |
+
*/
|
1288 |
+
function enable_image_downsize() {
|
1289 |
+
add_filter( 'image_downsize', array( $this, 'filter_image_downsize' ), 10, 3 );
|
1290 |
+
}
|
1291 |
|
1292 |
+
/**
|
1293 |
+
* Change the default for processing an array of dimensions to scaling instead of cropping.
|
1294 |
+
*
|
1295 |
+
* @param array $exactdn_args The ExactDN args generated by filter_image_downsize() when $size is an array.
|
1296 |
+
* @return array $exactdn_args The ExactDN args, with resize (crop) changed to fit (scale).
|
1297 |
+
*/
|
1298 |
+
function image_downsize_scale( $exactdn_args ) {
|
1299 |
+
if ( ! is_array( $exactdn_args ) ) {
|
1300 |
+
return $exactdn_args;
|
1301 |
+
}
|
1302 |
+
if ( ! empty( $exactdn_args['resize'] ) ) {
|
1303 |
+
$exactdn_args['fit'] = $exactdn_args['resize'];
|
1304 |
+
unset( $exactdn_args['resize'] );
|
1305 |
+
}
|
1306 |
return $exactdn_args;
|
1307 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1308 |
|
1309 |
+
/**
|
1310 |
+
* Filter post thumbnail image retrieval, passing images through ExactDN.
|
1311 |
+
*
|
1312 |
+
* @param array|bool $image Defaults to false, but may be a url if another plugin/theme has already filtered the value.
|
1313 |
+
* @param int $attachment_id The ID number for the image attachment.
|
1314 |
+
* @param string|array $size The name of the image size or an array of width and height. Default 'medium'.
|
1315 |
+
* @uses is_admin, apply_filters, wp_get_attachment_url, this::validate_image_url, this::image_sizes, this::generate_url
|
1316 |
+
* @filter image_downsize
|
1317 |
+
* @return string|bool
|
1318 |
+
*/
|
1319 |
+
function filter_image_downsize( $image, $attachment_id, $size ) {
|
1320 |
+
$started = microtime( true );
|
1321 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
1322 |
+
|
1323 |
+
// Don't foul up the admin side of things, unless a plugin wants to.
|
1324 |
+
if ( is_admin() &&
|
1325 |
+
/**
|
1326 |
+
* Provide plugins a way of running ExactDN for images in the WordPress Dashboard (wp-admin).
|
1327 |
+
*
|
1328 |
+
* Note: enabling this will result in ExactDN URLs added to your post content, which could make migrations across domains (and off ExactDN) a bit more challenging.
|
1329 |
+
*
|
1330 |
+
* @param bool false Allow ExactDN to run on the Dashboard. Default to false.
|
1331 |
+
* @param array $args {
|
1332 |
+
* Array of image details.
|
1333 |
+
*
|
1334 |
+
* @type array|bool $image Image URL or false.
|
1335 |
+
* @type int $attachment_id Attachment ID of the image.
|
1336 |
+
* @type array|string $size Image size. Can be a string (name of the image size, e.g. full) or an array of height and width.
|
1337 |
+
* }
|
1338 |
+
*/
|
1339 |
+
false === apply_filters( 'exactdn_admin_allow_image_downsize', false, compact( 'image', 'attachment_id', 'size' ) )
|
1340 |
+
) {
|
1341 |
+
return $image;
|
1342 |
+
}
|
1343 |
|
|
|
|
|
1344 |
/**
|
1345 |
+
* Provide plugins a way of preventing ExactDN from being applied to images retrieved from WordPress Core.
|
|
|
|
|
1346 |
*
|
1347 |
+
* @param bool false Stop ExactDN from being applied to the image. Default to false.
|
1348 |
* @param array $args {
|
1349 |
* Array of image details.
|
1350 |
*
|
1351 |
+
* @type string|bool $image Image URL or false.
|
1352 |
* @type int $attachment_id Attachment ID of the image.
|
1353 |
* @type array|string $size Image size. Can be a string (name of the image size, e.g. full) or an array of height and width.
|
1354 |
* }
|
1355 |
*/
|
1356 |
+
if ( apply_filters( 'exactdn_override_image_downsize', false, compact( 'image', 'attachment_id', 'size' ) ) ) {
|
1357 |
+
return $image;
|
1358 |
+
}
|
|
|
1359 |
|
1360 |
+
if ( function_exists( 'aq_resize' ) ) {
|
1361 |
+
$this->debug_message( 'aq_resize detected, image_downsize filter disabled' );
|
1362 |
+
return $image;
|
1363 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1364 |
|
1365 |
+
if ( $this->filtering_the_content || $this->filtering_the_page ) {
|
1366 |
+
$this->debug_message( 'end image_downsize early' );
|
1367 |
+
return $image;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1368 |
}
|
|
|
|
|
|
|
1369 |
|
1370 |
+
// Get the image URL and proceed with ExactDN replacement if successful.
|
1371 |
+
$image_url = wp_get_attachment_url( $attachment_id );
|
1372 |
+
/** This filter is already documented in class-exactdn.php */
|
1373 |
+
if ( apply_filters( 'exactdn_skip_image', false, $image_url, null ) ) {
|
1374 |
return $image;
|
1375 |
}
|
1376 |
+
$this->debug_message( $image_url );
|
1377 |
+
$this->debug_message( $attachment_id );
|
1378 |
+
if ( is_string( $size ) || is_int( $size ) ) {
|
1379 |
+
$this->debug_message( $size );
|
1380 |
+
} elseif ( is_array( $size ) ) {
|
1381 |
+
foreach ( $size as $dimension ) {
|
1382 |
+
$this->debug_message( 'dimension: ' . $dimension );
|
1383 |
+
}
|
1384 |
+
}
|
1385 |
+
// Set this to true later when we know we have size meta.
|
1386 |
+
$has_size_meta = false;
|
1387 |
|
1388 |
+
if ( $image_url ) {
|
1389 |
+
// Check if image URL should be used with ExactDN.
|
1390 |
+
if ( ! $this->validate_image_url( $image_url ) ) {
|
1391 |
+
return $image;
|
1392 |
+
}
|
1393 |
|
1394 |
+
$intermediate = true; // For the fourth array item returned by the image_downsize filter.
|
1395 |
+
$resize_existing = defined( 'EXACTDN_RESIZE_EXISTING' ) && EXACTDN_RESIZE_EXISTING;
|
|
|
|
|
|
|
1396 |
|
1397 |
+
// If an image is requested with a size known to WordPress, use that size's settings with ExactDN.
|
1398 |
+
if ( is_string( $size ) && array_key_exists( $size, $this->image_sizes() ) ) {
|
1399 |
+
$image_args = $this->image_sizes();
|
1400 |
+
$image_args = $image_args[ $size ];
|
1401 |
+
$this->debug_message( "image args for $size: " . $this->implode( ',', $image_args ) );
|
1402 |
|
1403 |
+
$exactdn_args = array();
|
1404 |
|
1405 |
+
$image_meta = image_get_intermediate_size( $attachment_id, $size );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1406 |
|
1407 |
+
// 'full' is a special case: We need consistent data regardless of the requested size.
|
1408 |
+
if ( 'full' === $size ) {
|
1409 |
+
$image_meta = wp_get_attachment_metadata( $attachment_id );
|
1410 |
+
$intermediate = false;
|
1411 |
+
} elseif ( ! $image_meta ) {
|
1412 |
+
$this->debug_message( 'still do not have meta, getting it now' );
|
1413 |
+
// If we still don't have any image meta at this point, it's probably from a custom thumbnail size
|
1414 |
+
// for an image that was uploaded before the custom image was added to the theme. Try to determine the size manually.
|
1415 |
+
$image_meta = wp_get_attachment_metadata( $attachment_id );
|
1416 |
+
|
1417 |
+
if ( isset( $image_meta['width'], $image_meta['height'] ) ) {
|
1418 |
+
$image_resized = image_resize_dimensions( $image_meta['width'], $image_meta['height'], $image_args['width'], $image_args['height'], $image_args['crop'] );
|
1419 |
+
if ( $image_resized ) { // This could be false when the requested image size is larger than the full-size image.
|
1420 |
+
$image_meta['width'] = $image_resized[6];
|
1421 |
+
$image_meta['height'] = $image_resized[7];
|
1422 |
+
}
|
1423 |
}
|
1424 |
}
|
1425 |
+
if ( isset( $image_meta['width'], $image_meta['height'] ) ) {
|
1426 |
+
$image_args['width'] = $image_meta['width'];
|
1427 |
+
$image_args['height'] = $image_meta['height'];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1428 |
|
1429 |
+
// NOTE: it will constrain an image to $content_width which is expected behavior in core, so far as I can see.
|
1430 |
+
list( $image_args['width'], $image_args['height'] ) = image_constrain_size_for_editor( $image_args['width'], $image_args['height'], $size, 'display' );
|
1431 |
|
1432 |
+
$has_size_meta = true;
|
1433 |
+
$this->debug_message( 'image args constrained: ' . $this->implode( ',', $image_args ) );
|
|
|
|
|
|
|
|
|
1434 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1435 |
|
1436 |
+
$transform = $image_args['crop'] ? 'resize' : 'fit';
|
1437 |
+
|
1438 |
+
// Check specified image dimensions and account for possible zero values; ExactDN fails to resize if a dimension is zero.
|
1439 |
+
if ( ! $image_args['width'] || ! $image_args['height'] ) {
|
1440 |
+
if ( ! $image_args['width'] && 0 < $image_args['height'] ) {
|
1441 |
+
$exactdn_args['h'] = $image_args['height'];
|
1442 |
+
} elseif ( ! $image_args['height'] && 0 < $image_args['width'] ) {
|
1443 |
+
$exactdn_args['w'] = $image_args['width'];
|
1444 |
+
}
|
1445 |
} else {
|
1446 |
+
if ( ! isset( $image_meta['sizes'] ) ) {
|
1447 |
+
$size_meta = $image_meta;
|
1448 |
+
// Because we don't have the "real" meta, just the height/width for the specific size.
|
1449 |
+
$this->debug_message( 'getting attachment meta now' );
|
1450 |
+
$image_meta = wp_get_attachment_metadata( $attachment_id );
|
1451 |
+
}
|
1452 |
+
if ( 'resize' === $transform && $image_meta && isset( $image_meta['width'], $image_meta['height'] ) ) {
|
1453 |
+
// Lets make sure that we don't upscale images since wp never upscales them as well.
|
1454 |
+
$smaller_width = ( ( $image_meta['width'] < $image_args['width'] ) ? $image_meta['width'] : $image_args['width'] );
|
1455 |
+
$smaller_height = ( ( $image_meta['height'] < $image_args['height'] ) ? $image_meta['height'] : $image_args['height'] );
|
1456 |
+
|
1457 |
+
$exactdn_args[ $transform ] = $smaller_width . ',' . $smaller_height;
|
1458 |
+
} else {
|
1459 |
+
$exactdn_args[ $transform ] = $image_args['width'] . ',' . $image_args['height'];
|
1460 |
+
}
|
1461 |
}
|
|
|
1462 |
|
1463 |
+
if (
|
1464 |
+
! empty( $image_meta['sizes'] ) && ! empty( $image_meta['width'] ) && ! empty( $image_meta['height'] ) &&
|
1465 |
+
(int) $image_args['width'] === (int) $image_meta['width'] &&
|
1466 |
+
(int) $image_args['height'] === (int) $image_meta['height']
|
1467 |
+
) {
|
1468 |
+
$this->debug_message( 'image args match size of original, just use that' );
|
1469 |
+
$size = 'full';
|
1470 |
+
}
|
1471 |
+
if ( empty( $image_meta['sizes'] ) && ! empty( $size_meta ) ) {
|
1472 |
+
$image_meta['sizes'][ $size ] = $size_meta;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1473 |
}
|
1474 |
+
if ( ! empty( $image_meta['sizes'] ) && 'full' !== $size && ! empty( $image_meta['sizes'][ $size ]['file'] ) ) {
|
1475 |
+
$image_url_basename = wp_basename( $image_url );
|
1476 |
+
$intermediate_url = str_replace( $image_url_basename, $image_meta['sizes'][ $size ]['file'], $image_url );
|
1477 |
+
|
1478 |
+
if ( empty( $image_meta['width'] ) || empty( $image_meta['height'] ) ) {
|
1479 |
+
list( $filename_width, $filename_height ) = $this->get_dimensions_from_filename( $intermediate_url );
|
1480 |
+
}
|
1481 |
+
$filename_width = $image_meta['width'] ? $image_meta['width'] : $filename_width;
|
1482 |
+
$filename_height = $image_meta['height'] ? $image_meta['height'] : $filename_height;
|
1483 |
+
if ( $filename_width && $filename_height && $image_args['width'] === $filename_width && $image_args['height'] === $filename_height ) {
|
1484 |
+
$image_url = $intermediate_url;
|
1485 |
+
} else {
|
1486 |
+
$resize_existing = true;
|
1487 |
+
}
|
1488 |
} else {
|
1489 |
$resize_existing = true;
|
1490 |
}
|
|
|
|
|
|
|
|
|
|
|
1491 |
|
1492 |
+
$exactdn_args = $resize_existing && 'full' !== $size ? $this->maybe_smart_crop( $exactdn_args, $attachment_id, $image_meta ) : array();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1493 |
|
1494 |
+
/**
|
1495 |
+
* Filter the ExactDN arguments added to an image, when that image size is a string.
|
1496 |
+
* Image size will be a string (e.g. "full", "medium") when it is known to WordPress.
|
1497 |
+
*
|
1498 |
+
* @param array $exactdn_args ExactDN arguments.
|
1499 |
+
* @param array $args {
|
1500 |
+
* Array of image details.
|
1501 |
+
*
|
1502 |
+
* @type array $image_args Image arguments (width, height, crop).
|
1503 |
+
* @type string $image_url Image URL.
|
1504 |
+
* @type int $attachment_id Attachment ID of the image.
|
1505 |
+
* @type string $size Image size name.
|
1506 |
+
* @type string $transform Value can be resize or fit.
|
1507 |
+
* }
|
1508 |
+
*/
|
1509 |
+
$exactdn_args = apply_filters( 'exactdn_image_downsize_string', $exactdn_args, compact( 'image_args', 'image_url', 'attachment_id', 'size', 'transform' ) );
|
1510 |
+
|
1511 |
+
// Generate ExactDN URL.
|
1512 |
+
$image = array(
|
1513 |
+
$this->generate_url( $image_url, $exactdn_args ),
|
1514 |
+
$has_size_meta ? $image_args['width'] : false,
|
1515 |
+
$has_size_meta ? $image_args['height'] : false,
|
1516 |
+
$intermediate,
|
1517 |
+
);
|
1518 |
+
} elseif ( is_array( $size ) ) {
|
1519 |
+
// Pull width and height values from the provided array, if possible.
|
1520 |
+
$width = isset( $size[0] ) ? (int) $size[0] : false;
|
1521 |
+
$height = isset( $size[1] ) ? (int) $size[1] : false;
|
1522 |
+
|
1523 |
+
// Don't bother if necessary parameters aren't passed.
|
1524 |
+
if ( ! $width || ! $height ) {
|
1525 |
+
return $image;
|
1526 |
+
}
|
1527 |
+
$this->debug_message( "requested w$width by h$height" );
|
1528 |
|
1529 |
+
$image_meta = wp_get_attachment_metadata( $attachment_id );
|
1530 |
+
if ( isset( $image_meta['width'], $image_meta['height'] ) ) {
|
1531 |
+
$image_resized = image_resize_dimensions( $image_meta['width'], $image_meta['height'], $width, $height, true );
|
1532 |
|
1533 |
+
if ( $image_resized ) { // This could be false when the requested image size is larger than the full-size image.
|
1534 |
+
$width = $image_resized[6];
|
1535 |
+
$height = $image_resized[7];
|
1536 |
+
$this->debug_message( "using resize dims w$width by h$height" );
|
1537 |
+
} else {
|
1538 |
+
$width = $image_meta['width'];
|
1539 |
+
$height = $image_meta['height'];
|
1540 |
+
$this->debug_message( "using meta dims w$width by h$height" );
|
1541 |
+
}
|
1542 |
+
$has_size_meta = true;
|
1543 |
}
|
|
|
|
|
1544 |
|
1545 |
+
list( $width, $height ) = image_constrain_size_for_editor( $width, $height, $size );
|
1546 |
+
$this->debug_message( "constrained to w$width by h$height" );
|
1547 |
|
1548 |
+
// Expose arguments to a filter before passing to ExactDN.
|
1549 |
+
$exactdn_args = array(
|
1550 |
+
'resize' => $width . ',' . $height,
|
1551 |
+
);
|
1552 |
|
1553 |
+
$exactdn_args = $this->maybe_smart_crop( $exactdn_args, $attachment_id, $image_meta );
|
1554 |
+
|
1555 |
+
/**
|
1556 |
+
* Filter the ExactDN arguments added to an image, when the image size is an array of height and width values.
|
1557 |
+
*
|
1558 |
+
* @param array $exactdn_args ExactDN arguments/parameters.
|
1559 |
+
* @param array $args {
|
1560 |
+
* Array of image details.
|
1561 |
+
*
|
1562 |
+
* @type int $width Image width.
|
1563 |
+
* @type int $height Image height.
|
1564 |
+
* @type string $image_url Image URL.
|
1565 |
+
* @type int $attachment_id Attachment ID of the image.
|
1566 |
+
* }
|
1567 |
+
*/
|
1568 |
+
$exactdn_args = apply_filters( 'exactdn_image_downsize_array', $exactdn_args, compact( 'width', 'height', 'image_url', 'attachment_id' ) );
|
1569 |
+
|
1570 |
+
// Generate ExactDN URL.
|
1571 |
+
$image = array(
|
1572 |
+
$this->generate_url( $image_url, $exactdn_args ),
|
1573 |
+
$has_size_meta ? $width : false,
|
1574 |
+
$has_size_meta ? $height : false,
|
1575 |
+
$intermediate,
|
1576 |
+
);
|
1577 |
+
}
|
1578 |
+
}
|
1579 |
+
if ( ! empty( $image[0] ) && is_string( $image[0] ) ) {
|
1580 |
+
$this->debug_message( $image[0] );
|
1581 |
+
}
|
1582 |
+
$this->debug_message( 'end image_downsize' );
|
1583 |
+
$elapsed_time = microtime( true ) - $started;
|
1584 |
+
$this->debug_message( "parsing image_downsize took $elapsed_time seconds" );
|
1585 |
+
$this->elapsed_time += microtime( true ) - $started;
|
1586 |
+
return $image;
|
1587 |
+
}
|
1588 |
|
1589 |
+
/**
|
1590 |
+
* Filters an array of image `srcset` values, replacing each URL with its ExactDN equivalent.
|
1591 |
+
*
|
1592 |
+
* @param array $sources An array of image urls and widths.
|
1593 |
+
* @param array $size_array Array of width and height values in pixels.
|
1594 |
+
* @param string $image_src The 'src' of the image.
|
1595 |
+
* @param array $image_meta The image metadata as returned by 'wp_get_attachment_metadata()'.
|
1596 |
+
* @param int $attachment_id Image attachment ID or 0.
|
1597 |
+
* @uses this::validate_image_url, this::generate_url, this::parse_from_filename
|
1598 |
+
* @uses this::strip_image_dimensions_maybe, this::get_content_width
|
1599 |
+
* @return array An array of ExactDN image urls and widths.
|
1600 |
+
*/
|
1601 |
+
public function filter_srcset_array( $sources = array(), $size_array = array(), $image_src = '', $image_meta = array(), $attachment_id = 0 ) {
|
1602 |
+
$started = microtime( true );
|
1603 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
1604 |
+
// Don't foul up the admin side of things, unless a plugin wants to.
|
1605 |
+
if ( is_admin() &&
|
1606 |
/**
|
1607 |
+
* Provide plugins a way of running ExactDN for images in the WordPress Dashboard (wp-admin).
|
1608 |
*
|
1609 |
+
* @param bool false Stop ExactDN from being run on the Dashboard. Default to false, use true to run in wp-admin.
|
1610 |
* @param array $args {
|
1611 |
* Array of image details.
|
1612 |
*
|
1613 |
+
* @type string|bool $image Image URL or false.
|
1614 |
+
* @type int $attachment_id Attachment ID of the image.
|
|
|
|
|
1615 |
* }
|
1616 |
*/
|
1617 |
+
false === apply_filters( 'exactdn_admin_allow_image_srcset', false, compact( 'image_src', 'attachment_id' ) )
|
1618 |
+
) {
|
1619 |
+
return $sources;
|
|
|
|
|
|
|
|
|
|
|
|
|
1620 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1621 |
|
1622 |
+
if ( ! is_array( $sources ) ) {
|
1623 |
+
return $sources;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1624 |
}
|
1625 |
|
1626 |
+
$upload_dir = wp_get_upload_dir();
|
1627 |
+
$resize_existing = defined( 'EXACTDN_RESIZE_EXISTING' ) && EXACTDN_RESIZE_EXISTING;
|
1628 |
+
$w_descriptor = true;
|
|
|
1629 |
|
1630 |
+
foreach ( $sources as $i => $source ) {
|
1631 |
+
if ( 'x' === $source['descriptor'] ) {
|
1632 |
+
$w_descriptor = false;
|
1633 |
+
}
|
1634 |
+
if ( ! $this->validate_image_url( $source['url'] ) ) {
|
1635 |
+
continue;
|
1636 |
+
}
|
1637 |
|
1638 |
+
/** This filter is already documented in class-exactdn.php */
|
1639 |
+
if ( apply_filters( 'exactdn_skip_image', false, $source['url'], $source ) ) {
|
1640 |
+
continue;
|
1641 |
+
}
|
1642 |
+
|
1643 |
+
$url = $source['url'];
|
1644 |
|
1645 |
+
list( $width, $height ) = $this->get_dimensions_from_filename( $url );
|
1646 |
+
if ( ! $resize_existing && 'w' === $source['descriptor'] && (int) $source['value'] === (int) $width ) {
|
1647 |
+
$this->debug_message( "preventing further processing for $url" );
|
|
|
|
|
1648 |
$sources[ $i ]['url'] = $this->generate_url( $source['url'] );
|
1649 |
continue;
|
1650 |
}
|
|
|
1651 |
|
1652 |
+
if ( $image_meta && ! empty( $image_meta['width'] ) ) {
|
1653 |
+
if ( ( $height && (int) $image_meta['height'] === (int) $height && $width && (int) $image_meta['width'] === (int) $width ) ||
|
1654 |
+
( ! $height && ! $width && (int) $image_meta['width'] === (int) $source['value'] )
|
1655 |
+
) {
|
1656 |
+
$this->debug_message( "preventing further processing for (detected) full-size $url" );
|
1657 |
+
$sources[ $i ]['url'] = $this->generate_url( $source['url'] );
|
1658 |
+
continue;
|
1659 |
+
}
|
1660 |
+
}
|
1661 |
|
1662 |
+
$this->debug_message( 'continuing: ' . $width . ' vs. ' . $source['value'] );
|
|
|
|
|
|
|
|
|
|
|
|
|
1663 |
|
1664 |
+
// It's quicker to get the full size with the data we have already, if available.
|
1665 |
+
if ( ! empty( $attachment_id ) ) {
|
1666 |
+
$url = wp_get_attachment_url( $attachment_id );
|
|
|
1667 |
} else {
|
1668 |
+
$url = $this->strip_image_dimensions_maybe( $url );
|
1669 |
}
|
1670 |
+
$this->debug_message( "building srcs from $url" );
|
1671 |
|
1672 |
+
$args = array();
|
1673 |
+
if ( 'w' === $source['descriptor'] ) {
|
1674 |
+
if ( $height && ( (int) $source['value'] === (int) $width ) ) {
|
1675 |
+
$args['resize'] = $width . ',' . $height;
|
1676 |
+
} else {
|
1677 |
+
$args['w'] = $source['value'];
|
1678 |
+
}
|
1679 |
+
}
|
1680 |
|
1681 |
+
$args = $this->maybe_smart_crop( $args, $attachment_id, $image_meta );
|
|
|
1682 |
|
1683 |
+
$sources[ $i ]['url'] = $this->generate_url( $url, $args );
|
1684 |
+
}
|
|
|
|
|
1685 |
|
1686 |
+
/**
|
1687 |
+
* At this point, $sources is the original srcset with ExactDN URLs.
|
1688 |
+
* Now, we're going to construct additional sizes based on multiples of the content_width.
|
1689 |
+
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1690 |
|
1691 |
+
/**
|
1692 |
+
* Filter the multiplier ExactDN uses to create new srcset items.
|
1693 |
+
* Return false to short-circuit and bypass auto-generation.
|
1694 |
+
*
|
1695 |
+
* @param array|bool $multipliers Array of multipliers to use or false to bypass.
|
1696 |
+
*/
|
1697 |
+
$multipliers = apply_filters( 'exactdn_srcset_multipliers', array( .2, .4, .6, .8, 1, 2, 3, 1920 ) );
|
1698 |
+
$url = trailingslashit( $upload_dir['baseurl'] ) . $image_meta['file'];
|
1699 |
+
if ( ! $w_descriptor ) {
|
1700 |
+
$this->debug_message( 'using x descriptors instead of w' );
|
1701 |
+
$multipliers = array_filter( $multipliers, 'is_int' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1702 |
}
|
|
|
1703 |
|
1704 |
+
if (
|
1705 |
+
/** Short-circuit via exactdn_srcset_multipliers filter. */
|
1706 |
+
is_array( $multipliers )
|
1707 |
+
/** This filter is already documented in class-exactdn.php */
|
1708 |
+
&& ! apply_filters( 'exactdn_skip_image', false, $url, null )
|
1709 |
+
/** The original url is valid/allowed. */
|
1710 |
+
&& $this->validate_image_url( $url )
|
1711 |
+
/** Verify basic meta is intact. */
|
1712 |
+
&& isset( $image_meta['width'] ) && isset( $image_meta['height'] ) && isset( $image_meta['file'] )
|
1713 |
+
/** Verify we have the requested width/height. */
|
1714 |
+
&& isset( $size_array[0] ) && isset( $size_array[1] )
|
1715 |
+
) {
|
1716 |
+
|
1717 |
+
$fullwidth = $image_meta['width'];
|
1718 |
+
$fullheight = $image_meta['height'];
|
1719 |
+
$reqwidth = $size_array[0];
|
1720 |
+
$reqheight = $size_array[1];
|
1721 |
+
$this->debug_message( "filling additional sizes with requested w $reqwidth h $reqheight full w $fullwidth full h $fullheight" );
|
1722 |
+
|
1723 |
+
$constrained_size = wp_constrain_dimensions( $fullwidth, $fullheight, $reqwidth );
|
1724 |
+
$expected_size = array( $reqwidth, $reqheight );
|
1725 |
+
|
1726 |
+
$this->debug_message( $constrained_size[0] );
|
1727 |
+
$this->debug_message( $constrained_size[1] );
|
1728 |
+
if ( abs( $constrained_size[0] - $expected_size[0] ) <= 1 && abs( $constrained_size[1] - $expected_size[1] ) <= 1 ) {
|
1729 |
+
$this->debug_message( 'soft cropping' );
|
1730 |
+
$crop = 'soft';
|
1731 |
+
$base = $this->get_content_width(); // Provide a default width if none set by the theme.
|
1732 |
+
} else {
|
1733 |
+
$this->debug_message( 'hard cropping' );
|
1734 |
+
$crop = 'hard';
|
1735 |
+
$base = $reqwidth;
|
1736 |
+
}
|
1737 |
+
$this->debug_message( "base width: $base" );
|
1738 |
|
1739 |
+
$currentwidths = array_keys( $sources );
|
1740 |
+
$newsources = null;
|
1741 |
|
1742 |
+
foreach ( $multipliers as $multiplier ) {
|
1743 |
+
|
1744 |
+
$newwidth = intval( $base * $multiplier );
|
1745 |
+
if ( 1920 === (int) $multiplier ) {
|
1746 |
+
$newwidth = 1920;
|
1747 |
+
if ( ! $w_descriptor ) {
|
1748 |
+
continue;
|
1749 |
+
}
|
1750 |
}
|
1751 |
+
if ( $newwidth < 50 ) {
|
1752 |
+
continue;
|
|
|
|
|
|
|
|
|
|
|
|
|
1753 |
}
|
1754 |
+
foreach ( $currentwidths as $currentwidth ) {
|
1755 |
+
// If a new width would be within 50 pixels of an existing one or larger than the full size image, skip.
|
1756 |
+
if ( abs( $currentwidth - $newwidth ) < 50 || ( $newwidth > $fullwidth ) ) {
|
1757 |
+
continue 2; // Back to the foreach ( $multipliers as $multiplier ).
|
1758 |
+
}
|
1759 |
+
} // foreach ( $currentwidths as $currentwidth ){
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1760 |
|
1761 |
+
if ( 1 === $multiplier && abs( $newwidth - $fullwidth ) < 5 ) {
|
1762 |
+
$args = array();
|
1763 |
+
} elseif ( 'soft' === $crop ) {
|
1764 |
+
$args = array(
|
1765 |
+
'w' => $newwidth,
|
1766 |
+
);
|
1767 |
+
} else { // hard crop, e.g. add_image_size( 'example', 200, 200, true ).
|
1768 |
+
$args = array(
|
1769 |
+
'zoom' => $multiplier,
|
1770 |
+
'resize' => $reqwidth . ',' . $reqheight,
|
1771 |
+
);
|
1772 |
+
}
|
1773 |
|
1774 |
+
$args = $this->maybe_smart_crop( $args, $attachment_id, $image_meta );
|
|
|
1775 |
|
1776 |
+
$newsources[ $newwidth ] = array(
|
1777 |
+
'url' => $this->generate_url( $url, $args ),
|
1778 |
+
'descriptor' => ( $w_descriptor ? 'w' : 'x' ),
|
1779 |
+
'value' => ( $w_descriptor ? $newwidth : $multiplier ),
|
1780 |
+
);
|
|
|
|
|
|
|
|
|
|
|
1781 |
|
1782 |
+
$currentwidths[] = $newwidth;
|
1783 |
+
} // foreach ( $multipliers as $multiplier )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1784 |
|
1785 |
+
if ( is_array( $newsources ) ) {
|
1786 |
+
$sources = array_replace( $sources, $newsources );
|
1787 |
+
}
|
1788 |
+
} // if ( isset( $image_meta['width'] ) && isset( $image_meta['file'] ) )
|
1789 |
+
$elapsed_time = microtime( true ) - $started;
|
1790 |
+
$this->debug_message( "parsing srcset took $elapsed_time seconds" );
|
1791 |
+
/* $this->debug_message( print_r( $sources, true ) ); */
|
1792 |
+
$this->elapsed_time += microtime( true ) - $started;
|
1793 |
+
return $sources;
|
1794 |
}
|
1795 |
|
1796 |
+
/**
|
1797 |
+
* Filters an array of image `sizes` values, using $content_width instead of image's full size.
|
1798 |
+
*
|
1799 |
+
* @param array $sizes An array of media query breakpoints.
|
1800 |
+
* @param array $size Width and height of the image.
|
1801 |
+
* @uses this::get_content_width
|
1802 |
+
* @return array An array of media query breakpoints.
|
1803 |
+
*/
|
1804 |
+
public function filter_sizes( $sizes, $size ) {
|
1805 |
+
$started = microtime( true );
|
1806 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
1807 |
+
if ( ! doing_filter( 'the_content' ) ) {
|
1808 |
+
return $sizes;
|
1809 |
+
}
|
1810 |
+
$content_width = $this->get_content_width();
|
1811 |
|
1812 |
+
if ( ( is_array( $size ) && $size[0] < $content_width ) ) {
|
1813 |
+
return $sizes;
|
1814 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1815 |
|
1816 |
+
$elapsed_time = microtime( true ) - $started;
|
1817 |
+
$this->debug_message( "parsing sizes took $elapsed_time seconds" );
|
1818 |
+
$this->elapsed_time += microtime( true ) - $started;
|
1819 |
+
return sprintf( '(max-width: %1$dpx) 100vw, %1$dpx', $content_width );
|
1820 |
}
|
1821 |
|
1822 |
/**
|
1823 |
+
* Creates an image `srcset` attribute based on the detected width.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1824 |
*
|
1825 |
+
* @param string $url The url of the image.
|
1826 |
+
* @param int $width Image width to use for calculations.
|
1827 |
+
* @param bool $zoom Whether to use zoom or w param.
|
1828 |
+
* @param int $filename_width The width derived from the filename, or false.
|
1829 |
+
* @uses this::generate_url
|
1830 |
+
* @return string A srcset attribute with ExactDN image urls and widths.
|
1831 |
*/
|
1832 |
+
public function generate_image_srcset( $url, $width, $zoom = false, $filename_width = false ) {
|
1833 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
1834 |
+
// Don't foul up the admin side of things.
|
1835 |
+
if ( is_admin() ) {
|
1836 |
+
return '';
|
1837 |
+
}
|
1838 |
|
1839 |
+
if ( ! is_numeric( $width ) ) {
|
1840 |
+
return '';
|
1841 |
+
}
|
1842 |
+
|
1843 |
+
/**
|
1844 |
+
* Filter the multiplier ExactDN uses to create new srcset items.
|
1845 |
+
* Return false to short-circuit and bypass auto-generation.
|
1846 |
+
*
|
1847 |
+
* @param array|bool $multipliers Array of multipliers to use or false to bypass.
|
1848 |
+
*/
|
1849 |
+
$multipliers = apply_filters( 'exactdn_srcset_multipliers', array( .2, .4, .6, .8, 1, 2, 3, 1920 ) );
|
1850 |
+
/**
|
1851 |
+
* Filter the width ExactDN will use to create srcset attribute.
|
1852 |
+
* Return a falsy value to short-circuit and bypass srcset fill.
|
1853 |
+
*
|
1854 |
+
* @param int|bool $width The max width for this $url, or false to bypass.
|
1855 |
+
*/
|
1856 |
+
$width = (int) apply_filters( 'exactdn_srcset_fill_width', $width, $url );
|
1857 |
+
if ( ! $width ) {
|
1858 |
+
return '';
|
1859 |
+
}
|
1860 |
+
$srcset = '';
|
1861 |
+
$currentwidths = array();
|
1862 |
+
|
1863 |
+
if (
|
1864 |
+
/** Short-circuit via exactdn_srcset_multipliers filter. */
|
1865 |
+
is_array( $multipliers )
|
1866 |
+
&& $width
|
1867 |
+
/** This filter is already documented in class-exactdn.php */
|
1868 |
+
&& ! apply_filters( 'exactdn_skip_image', false, $url, null )
|
1869 |
+
) {
|
1870 |
+
$sources = null;
|
1871 |
+
|
1872 |
+
foreach ( $multipliers as $multiplier ) {
|
1873 |
+
$newwidth = intval( $width * $multiplier );
|
1874 |
+
if ( 1920 === (int) $multiplier ) {
|
1875 |
+
$newwidth = 1920;
|
1876 |
+
}
|
1877 |
+
if ( $newwidth < 50 ) {
|
1878 |
+
continue;
|
1879 |
+
}
|
1880 |
+
foreach ( $currentwidths as $currentwidth ) {
|
1881 |
+
// If a new width would be within 50 pixels of an existing one or larger than the full size image, skip.
|
1882 |
+
if ( 1 !== $multiplier && abs( $currentwidth - $newwidth ) < 50 ) {
|
1883 |
+
continue 2; // Back to the foreach ( $multipliers as $multiplier ).
|
1884 |
+
}
|
1885 |
+
} // foreach ( $currentwidths as $currentwidth ){
|
1886 |
+
if ( $filename_width && $newwidth > $filename_width ) {
|
1887 |
+
continue;
|
1888 |
}
|
|
|
|
|
|
|
|
|
1889 |
|
1890 |
+
if ( 1 === $multiplier ) {
|
1891 |
+
$args = array();
|
1892 |
+
} elseif ( $zoom ) {
|
1893 |
+
$args = array(
|
1894 |
+
'zoom' => $multiplier,
|
1895 |
+
);
|
1896 |
+
} else {
|
1897 |
+
$args = array(
|
1898 |
+
'w' => $newwidth,
|
1899 |
+
);
|
1900 |
+
}
|
1901 |
|
1902 |
+
$sources[ $newwidth ] = array(
|
1903 |
+
'url' => $this->generate_url( $url, $args ),
|
1904 |
+
'descriptor' => 'w',
|
1905 |
+
'value' => $newwidth,
|
1906 |
+
);
|
1907 |
|
1908 |
+
$currentwidths[] = $newwidth;
|
1909 |
+
}
|
1910 |
}
|
1911 |
+
if ( ! empty( $sources ) ) {
|
1912 |
+
foreach ( $sources as $source ) {
|
1913 |
+
$srcset .= str_replace( ' ', '%20', $source['url'] ) . ' ' . $source['value'] . $source['descriptor'] . ', ';
|
1914 |
+
}
|
1915 |
}
|
1916 |
+
/* $this->debug_message( print_r( $sources, true ) ); */
|
1917 |
+
return rtrim( $srcset, ', ' );
|
1918 |
}
|
|
|
|
|
|
|
1919 |
|
1920 |
+
/**
|
1921 |
+
* Check for smart-cropping plugin to adjust cropping parameters.
|
1922 |
+
* Currently supports Theia Smart Thumbnails using the theiaSmartThumbnails_position meta.
|
1923 |
+
*
|
1924 |
+
* @param array $args The arguments that have been generated so far.
|
1925 |
+
* @param int $attachment_id The ID number for the current image.
|
1926 |
+
* @param array $meta Optional. The attachment (image) metadata. Default false.
|
1927 |
+
* @return array The arguments, possibly altered for smart cropping.
|
1928 |
+
*/
|
1929 |
+
function maybe_smart_crop( $args, $attachment_id, $meta = false ) {
|
1930 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
1931 |
+
if ( ! empty( $args['crop'] ) ) {
|
1932 |
+
$this->debug_message( 'already cropped' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1933 |
return $args;
|
1934 |
}
|
1935 |
+
// Doing something other than a hard crop, or we don't know what the ID is.
|
1936 |
+
if ( empty( $args['resize'] ) || empty( $attachment_id ) ) {
|
1937 |
+
$this->debug_message( 'not resizing, so no custom crop' );
|
1938 |
+
return $args;
|
1939 |
+
}
|
1940 |
+
// TST is not active.
|
1941 |
+
if ( ! defined( 'TST_VERSION' ) ) {
|
1942 |
+
$this->debug_message( 'no TST plugin' );
|
1943 |
+
return $args;
|
1944 |
+
}
|
1945 |
+
if ( ! class_exists( 'TstPostOptions' ) || ! defined( 'TstPostOptions::META_POSITION' ) ) {
|
1946 |
+
$this->debug_message( 'no TstPostOptions class' );
|
1947 |
+
return $args;
|
1948 |
+
}
|
1949 |
+
if ( ! $meta || ! is_array( $meta ) || empty( $meta['sizes'] ) ) {
|
1950 |
+
// $focus_point = get_post_meta( $attachment_id, TstPostOptions::META_POSITION, true );
|
1951 |
+
$meta = wp_get_attachment_metadata( $attachment_id );
|
1952 |
+
if ( ! is_array( $meta ) || empty( $meta['width'] ) || empty( $meta['height'] ) ) {
|
1953 |
+
$this->debug_message( 'unusable meta retrieved' );
|
1954 |
+
return $args;
|
1955 |
+
}
|
1956 |
+
$focus_point = TstPostOptions::get_meta( $attachment_id, $meta['width'], $meta['height'] );
|
1957 |
+
} elseif ( ! empty( $meta['tst_thumbnail_version'] ) ) {
|
1958 |
+
if ( empty( $meta['width'] ) || empty( $meta['height'] ) ) {
|
1959 |
+
$this->debug_message( 'unusable meta passed' );
|
1960 |
+
return $args;
|
1961 |
+
}
|
1962 |
+
$focus_point = TstPostOptions::get_meta( $attachment_id, $meta['width'], $meta['height'] );
|
1963 |
+
} else {
|
1964 |
+
$this->debug_message( 'unusable meta' );
|
1965 |
+
return $args;
|
1966 |
+
}
|
1967 |
+
if ( empty( $focus_point ) || ! is_array( $focus_point ) ) {
|
1968 |
+
$this->debug_message( 'unusable focus point' );
|
1969 |
return $args;
|
1970 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1971 |
|
1972 |
+
$dimensions = explode( ',', $args['resize'] );
|
1973 |
|
1974 |
+
$new_w = $dimensions[0];
|
1975 |
+
$new_h = $dimensions[1];
|
1976 |
+
$this->debug_message( "full size dims: w{$meta['width']} h{$meta['height']}" );
|
1977 |
+
$this->debug_message( "smart crop dims: w$new_w h$new_h" );
|
1978 |
+
if ( ! empty( $args['zoom'] ) ) {
|
1979 |
+
$new_w = round( $args['zoom'] * $new_w );
|
1980 |
+
$new_h = round( $args['zoom'] * $new_h );
|
1981 |
+
$this->debug_message( "zooming: {$args['zoom']} w$new_w h$new_h" );
|
1982 |
+
}
|
1983 |
+
if ( ! $new_w || ! $new_h ) {
|
1984 |
+
$this->debug_message( 'empty dimension, not cropping' );
|
1985 |
+
return $args;
|
1986 |
+
}
|
1987 |
+
$size_ratio = max( $new_w / $meta['width'], $new_h / $meta['height'] );
|
1988 |
+
$crop_w = round( $new_w / $size_ratio );
|
1989 |
+
$crop_h = round( $new_h / $size_ratio );
|
1990 |
+
$s_x = floor( ( $meta['width'] - $crop_w ) * $focus_point[0] );
|
1991 |
+
$s_y = floor( ( $meta['height'] - $crop_h ) * $focus_point[1] );
|
1992 |
+
$this->debug_message( "doing the math with size_ratio of $size_ratio" );
|
1993 |
+
|
1994 |
+
$args['crop'] = $s_x . ',' . $s_y . ',' . $crop_w . ',' . $crop_h;
|
1995 |
+
$this->debug_message( $args['crop'] );
|
1996 |
+
return $args;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1997 |
}
|
|
|
|
|
1998 |
|
1999 |
+
/**
|
2000 |
+
* Check if this is a REST API request that we should handle (or not).
|
2001 |
+
*
|
2002 |
+
* @param WP_HTTP_Response $response Result to send to the client. Usually a WP_REST_Response.
|
2003 |
+
* @param WP_REST_Server $handler ResponseHandler instance (usually WP_REST_Server).
|
2004 |
+
* @param WP_REST_Request $request Request used to generate the response.
|
2005 |
+
* @return WP_HTTP_Response The result, unaltered.
|
2006 |
+
*/
|
2007 |
+
function parse_restapi_maybe( $response, $handler, $request ) {
|
2008 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
2009 |
+
if ( ! is_a( $request, 'WP_REST_Request' ) ) {
|
2010 |
+
$this->debug_message( 'oddball REST request or handler' );
|
2011 |
+
return $response; // Something isn't right, bail.
|
2012 |
+
}
|
2013 |
+
$route = $request->get_route();
|
2014 |
+
if ( is_string( $route ) ) {
|
2015 |
+
$this->debug_message( "current REST route is $route" );
|
2016 |
+
}
|
2017 |
+
if ( is_string( $route ) && false !== strpos( $route, 'wp/v2/media/' ) && ! empty( $request['context'] ) && 'edit' === $request['context'] ) {
|
2018 |
+
$this->debug_message( 'REST API media endpoint from post editor' );
|
2019 |
+
// We don't want ExactDN urls anywhere near the editor, so disable everything we can.
|
2020 |
+
add_filter( 'exactdn_override_image_downsize', '__return_true', PHP_INT_MAX );
|
2021 |
+
add_filter( 'exactdn_skip_image', '__return_true', PHP_INT_MAX ); // This skips existing srcset indices.
|
2022 |
+
add_filter( 'exactdn_srcset_multipliers', '__return_false', PHP_INT_MAX ); // This one skips the additional multipliers.
|
2023 |
}
|
2024 |
+
return $response;
|
2025 |
}
|
|
|
|
|
2026 |
|
2027 |
+
/**
|
2028 |
+
* Make sure the image domain is on the list of approved domains.
|
2029 |
+
*
|
2030 |
+
* @param string $domain The hostname to validate.
|
2031 |
+
* @return bool True if the hostname is allowed, false otherwise.
|
2032 |
+
*/
|
2033 |
+
public function allow_image_domain( $domain ) {
|
2034 |
+
$domain = trim( $domain );
|
2035 |
+
foreach ( $this->allowed_domains as $allowed ) {
|
2036 |
+
$allowed = trim( $allowed );
|
2037 |
+
if ( $domain === $allowed ) {
|
2038 |
+
return true;
|
2039 |
+
}
|
2040 |
+
}
|
|
|
|
|
|
|
|
|
2041 |
return false;
|
2042 |
}
|
2043 |
|
2044 |
+
/**
|
2045 |
+
* Ensure image URL is valid for ExactDN.
|
2046 |
+
* Though ExactDN functions address some of the URL issues, we should avoid unnecessary processing if we know early on that the image isn't supported.
|
2047 |
+
*
|
2048 |
+
* @param string $url The image url to be validated.
|
2049 |
+
* @param bool $exactdn_is_valid Optional. Whether an ExactDN URL should be considered valid. Default false.
|
2050 |
+
* @uses wp_parse_args
|
2051 |
+
* @return bool True if the url is considerd valid, false otherwise.
|
2052 |
+
*/
|
2053 |
+
protected function validate_image_url( $url, $exactdn_is_valid = false ) {
|
2054 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
2055 |
+
if ( false !== strpos( $url, 'data:image/' ) ) {
|
2056 |
+
$this->debug_message( "could not parse data uri: $url" );
|
2057 |
+
return false;
|
2058 |
+
}
|
2059 |
+
$parsed_url = $this->parse_url( $url );
|
2060 |
+
if ( ! $parsed_url ) {
|
2061 |
+
$this->debug_message( "could not parse: $url" );
|
2062 |
+
return false;
|
2063 |
+
}
|
|
|
|
|
|
|
|
|
2064 |
|
2065 |
+
// Parse URL and ensure needed keys exist, since the array returned by `parse_url` only includes the URL components it finds.
|
2066 |
+
$url_info = wp_parse_args(
|
2067 |
+
$parsed_url,
|
2068 |
+
array(
|
2069 |
+
'scheme' => null,
|
2070 |
+
'host' => null,
|
2071 |
+
'port' => null,
|
2072 |
+
'path' => null,
|
2073 |
+
)
|
2074 |
+
);
|
2075 |
|
2076 |
+
// Bail if scheme isn't http or port is set that isn't port 80.
|
2077 |
+
if (
|
2078 |
+
( 'http' !== $url_info['scheme'] || ( 80 !== (int) $url_info['port'] && ! is_null( $url_info['port'] ) ) ) &&
|
2079 |
+
/**
|
2080 |
+
* Tells ExactDN to ignore images that are served via HTTPS.
|
2081 |
+
*
|
2082 |
+
* @param bool $reject_https Should ExactDN ignore images using the HTTPS scheme. Default to false.
|
2083 |
+
*/
|
2084 |
+
apply_filters( 'exactdn_reject_https', false )
|
2085 |
+
) {
|
2086 |
+
$this->debug_message( 'rejected https via filter' );
|
2087 |
+
return false;
|
2088 |
+
}
|
2089 |
|
2090 |
+
// Bail if no host is found.
|
2091 |
+
if ( is_null( $url_info['host'] ) ) {
|
2092 |
+
$this->debug_message( 'null host' );
|
2093 |
+
return false;
|
2094 |
+
}
|
2095 |
|
2096 |
+
// Bail if the image already went through ExactDN.
|
2097 |
+
if ( ! $exactdn_is_valid && $this->exactdn_domain === $url_info['host'] ) {
|
2098 |
+
$this->debug_message( 'exactdn image' );
|
2099 |
+
return false;
|
2100 |
+
}
|
2101 |
|
2102 |
+
// Bail if the image already went through Photon to avoid conflicts.
|
2103 |
+
if ( preg_match( '#^i[\d]{1}.wp.com$#i', $url_info['host'] ) ) {
|
2104 |
+
$this->debug_message( 'photon/wp.com image' );
|
2105 |
+
return false;
|
2106 |
+
}
|
2107 |
|
2108 |
+
// Bail if no path is found.
|
2109 |
+
if ( is_null( $url_info['path'] ) ) {
|
2110 |
+
$this->debug_message( 'null path' );
|
2111 |
+
return false;
|
2112 |
+
}
|
2113 |
+
|
2114 |
+
// Ensure image extension is acceptable, unless it's a dynamic NextGEN image.
|
2115 |
+
if ( ! in_array( strtolower( pathinfo( $url_info['path'], PATHINFO_EXTENSION ) ), $this->extensions, true ) && false === strpos( $url_info['path'], 'nextgen-image/' ) ) {
|
2116 |
+
$this->debug_message( 'invalid extension' );
|
2117 |
+
return false;
|
2118 |
+
}
|
2119 |
+
|
2120 |
+
// Make sure this is an allowed image domain/hostname for ExactDN on this site.
|
2121 |
+
if ( ! $this->allow_image_domain( $url_info['host'] ) ) {
|
2122 |
+
$this->debug_message( 'invalid host for ExactDN' );
|
2123 |
+
return false;
|
2124 |
+
}
|
2125 |
+
|
2126 |
+
// If we got this far, we should have an acceptable image URL,
|
2127 |
+
// but let folks filter to decline if they prefer.
|
2128 |
+
/**
|
2129 |
+
* Overwrite the results of the previous validation steps an image goes through to be considered valid for ExactDN.
|
2130 |
+
*
|
2131 |
+
* @param bool true Is the image URL valid and can it be used by ExactDN. Default to true.
|
2132 |
+
* @param string $url Image URL.
|
2133 |
+
* @param array $parsed_url Array of information about the image url.
|
2134 |
+
*/
|
2135 |
+
return apply_filters( 'exactdn_validate_image_url', true, $url, $parsed_url );
|
2136 |
}
|
2137 |
|
|
|
|
|
2138 |
/**
|
2139 |
+
* Checks if the file exists before it passes the file to ExactDN.
|
2140 |
*
|
2141 |
+
* @param string $src The image URL.
|
2142 |
+
* @return string The possibly altered URL without dimensions.
|
2143 |
+
**/
|
2144 |
+
protected function strip_image_dimensions_maybe( $src ) {
|
2145 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
2146 |
+
$stripped_src = $src;
|
2147 |
+
|
2148 |
+
// Build URL, first removing WP's resized string so we pass the original image to ExactDN.
|
2149 |
+
if ( preg_match( '#(-\d+x\d+)\.(' . implode( '|', $this->extensions ) . '){1}(?:\?.+)?$#i', $src, $src_parts ) ) {
|
2150 |
+
$stripped_src = str_replace( $src_parts[1], '', $src );
|
2151 |
+
$upload_dir = wp_get_upload_dir();
|
2152 |
+
|
2153 |
+
// Extracts the file path to the image minus the base url.
|
2154 |
+
$file_path = substr( $stripped_src, strlen( $upload_dir['baseurl'] ) );
|
2155 |
+
|
2156 |
+
if ( is_file( $upload_dir['basedir'] . $file_path ) ) {
|
2157 |
+
$src = $stripped_src;
|
2158 |
+
}
|
2159 |
+
$this->debug_message( 'stripped dims' );
|
2160 |
+
}
|
2161 |
+
return $src;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2162 |
}
|
|
|
|
|
2163 |
|
2164 |
+
/**
|
2165 |
+
* Provide an array of available image sizes and corresponding dimensions.
|
2166 |
+
* Similar to get_intermediate_image_sizes() except that it includes image sizes' dimensions, not just their names.
|
2167 |
+
*
|
2168 |
+
* @global $wp_additional_image_sizes
|
2169 |
+
* @uses get_option
|
2170 |
+
* @return array
|
2171 |
+
*/
|
2172 |
+
protected function image_sizes() {
|
2173 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
2174 |
+
if ( is_null( self::$image_sizes ) ) {
|
2175 |
+
global $_wp_additional_image_sizes;
|
2176 |
+
|
2177 |
+
// Populate an array matching the data structure of $_wp_additional_image_sizes so we have a consistent structure for image sizes.
|
2178 |
+
$images = array(
|
2179 |
+
'thumb' => array(
|
2180 |
+
'width' => intval( get_option( 'thumbnail_size_w' ) ),
|
2181 |
+
'height' => intval( get_option( 'thumbnail_size_h' ) ),
|
2182 |
+
'crop' => (bool) get_option( 'thumbnail_crop' ),
|
2183 |
+
),
|
2184 |
+
'medium' => array(
|
2185 |
+
'width' => intval( get_option( 'medium_size_w' ) ),
|
2186 |
+
'height' => intval( get_option( 'medium_size_h' ) ),
|
2187 |
+
'crop' => false,
|
2188 |
+
),
|
2189 |
+
'large' => array(
|
2190 |
+
'width' => intval( get_option( 'large_size_w' ) ),
|
2191 |
+
'height' => intval( get_option( 'large_size_h' ) ),
|
2192 |
+
'crop' => false,
|
2193 |
+
),
|
2194 |
+
'full' => array(
|
2195 |
+
'width' => null,
|
2196 |
+
'height' => null,
|
2197 |
+
'crop' => false,
|
2198 |
+
),
|
2199 |
+
);
|
2200 |
|
2201 |
+
// Compatibility mapping as found in wp-includes/media.php.
|
2202 |
+
$images['thumbnail'] = $images['thumb'];
|
2203 |
|
2204 |
+
// Update class variable, merging in $_wp_additional_image_sizes if any are set.
|
2205 |
+
if ( is_array( $_wp_additional_image_sizes ) && ! empty( $_wp_additional_image_sizes ) ) {
|
2206 |
+
self::$image_sizes = array_merge( $images, $_wp_additional_image_sizes );
|
2207 |
+
} else {
|
2208 |
+
self::$image_sizes = $images;
|
2209 |
+
}
|
2210 |
}
|
|
|
2211 |
|
2212 |
+
return is_array( self::$image_sizes ) ? self::$image_sizes : array();
|
2213 |
+
}
|
2214 |
|
2215 |
+
/**
|
2216 |
+
* Handle image urls within the NextGEN pro lightbox displays.
|
2217 |
+
*
|
2218 |
+
* @param array $images An array of NextGEN images and associate attributes.
|
2219 |
+
* @return array The ExactDNified array of images.
|
2220 |
+
*/
|
2221 |
+
function ngg_pro_lightbox_images_queue( $images ) {
|
2222 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
2223 |
+
if ( $this->is_iterable( $images ) ) {
|
2224 |
+
foreach ( $images as $index => $image ) {
|
2225 |
+
if ( ! empty( $image['image'] ) && $this->validate_image_url( $image['image'] ) ) {
|
2226 |
+
$images[ $index ]['image'] = $this->generate_url( $image['image'] );
|
2227 |
+
}
|
2228 |
+
if ( ! empty( $image['thumb'] ) && $this->validate_image_url( $image['thumb'] ) ) {
|
2229 |
+
$images[ $index ]['thumb'] = $this->generate_url( $image['thumb'] );
|
2230 |
+
}
|
2231 |
+
if ( ! empty( $image['full_image'] ) && $this->validate_image_url( $image['full_image'] ) ) {
|
2232 |
+
$images[ $index ]['full_image'] = $this->generate_url( $image['full_image'] );
|
2233 |
+
}
|
2234 |
+
if ( $this->is_iterable( $image['srcsets'] ) ) {
|
2235 |
+
foreach ( $image['srcsets'] as $size => $srcset ) {
|
2236 |
+
if ( $this->validate_image_url( $srcset ) ) {
|
2237 |
+
$images[ $index ]['srcsets'][ $size ] = $this->generate_url( $srcset );
|
2238 |
+
}
|
2239 |
}
|
2240 |
}
|
2241 |
+
if ( $this->is_iterable( $image['full_srcsets'] ) ) {
|
2242 |
+
foreach ( $image['full_srcsets'] as $size => $srcset ) {
|
2243 |
+
if ( $this->validate_image_url( $srcset ) ) {
|
2244 |
+
$images[ $index ]['full_srcsets'][ $size ] = $this->generate_url( $srcset );
|
2245 |
+
}
|
2246 |
}
|
2247 |
}
|
2248 |
}
|
2249 |
}
|
2250 |
+
return $images;
|
2251 |
}
|
|
|
|
|
2252 |
|
2253 |
+
/**
|
2254 |
+
* Handle image urls within NextGEN.
|
2255 |
+
*
|
2256 |
+
* @param string $image A url for a NextGEN image.
|
2257 |
+
* @return string The ExactDNified image url.
|
2258 |
+
*/
|
2259 |
+
function ngg_get_image_url( $image ) {
|
2260 |
+
// Don't foul up the admin side of things, unless a plugin wants to.
|
2261 |
+
if ( is_admin() &&
|
2262 |
+
/**
|
2263 |
+
* Provide plugins a way of running ExactDN for images in the WordPress Dashboard (wp-admin).
|
2264 |
+
*
|
2265 |
+
* @param bool false Stop ExactDN from being run on the Dashboard. Default to false, use true to run in wp-admin.
|
2266 |
+
* @param array $args {
|
2267 |
+
* Array of image details.
|
2268 |
+
*
|
2269 |
+
* @type string|bool $image Image URL or false.
|
2270 |
+
* @type int $attachment_id Attachment ID of the image.
|
2271 |
+
* }
|
2272 |
+
*/
|
2273 |
+
false === apply_filters( 'exactdn_admin_allow_ngg_url', false, $image )
|
2274 |
+
) {
|
2275 |
+
return $image;
|
2276 |
+
}
|
2277 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
2278 |
+
if ( $this->validate_image_url( $image ) ) {
|
2279 |
+
return $this->generate_url( $image );
|
2280 |
+
}
|
2281 |
return $image;
|
2282 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2283 |
|
2284 |
+
/**
|
2285 |
+
* Handle images in legacy WooCommerce API endpoints.
|
2286 |
+
*
|
2287 |
+
* @param array $product_data The product information that will be returned via the API.
|
2288 |
+
* @return array The product information with ExactDNified image urls.
|
2289 |
+
*/
|
2290 |
+
function woocommerce_api_product_response( $product_data ) {
|
2291 |
+
if ( is_array( $product_data ) && ! empty( $product_data['featured_src'] ) ) {
|
2292 |
+
if ( $this->validate_image_url( $product_data['featured_src'] ) ) {
|
2293 |
+
$product_data['featured_src'] = $this->generate_url( $product_data['featured_src'] );
|
2294 |
+
}
|
2295 |
}
|
2296 |
+
return $product_data;
|
2297 |
}
|
|
|
|
|
2298 |
|
2299 |
+
/**
|
2300 |
+
* Suppress query args for certain files, typically for placholder images.
|
2301 |
+
*
|
2302 |
+
* @param array|string $args Array of ExactDN arguments.
|
2303 |
+
* @param string $image_url Image URL.
|
2304 |
+
* @param string|null $scheme Image scheme. Default to null.
|
2305 |
+
* @return array Empty if it matches our search, otherwise just $args untouched.
|
2306 |
+
*/
|
2307 |
+
function exactdn_remove_args( $args, $image_url, $scheme ) {
|
2308 |
+
if ( strpos( $image_url, 'ewww/lazy/placeholder' ) ) {
|
2309 |
+
return array();
|
2310 |
+
}
|
2311 |
+
if ( strpos( $image_url, 'easyio/lazy/placeholder' ) ) {
|
2312 |
+
return array();
|
2313 |
+
}
|
2314 |
+
if ( strpos( $image_url, 'revslider/admin/assets/images/dummy.png' ) ) {
|
2315 |
+
return array();
|
2316 |
+
}
|
2317 |
+
if ( strpos( $image_url, '/lazy.png' ) ) {
|
2318 |
+
return array();
|
2319 |
+
}
|
2320 |
+
if ( strpos( $image_url, 'lazy_placeholder.gif' ) ) {
|
2321 |
+
return array();
|
2322 |
+
}
|
2323 |
+
if ( strpos( $image_url, '/assets/images/' ) ) {
|
2324 |
+
return array();
|
2325 |
+
}
|
2326 |
+
if ( strpos( $image_url, 'LayerSlider/static/img' ) ) {
|
2327 |
+
return array();
|
2328 |
+
}
|
2329 |
+
if ( strpos( $image_url, 'lazy-load/images/' ) ) {
|
2330 |
+
return array();
|
2331 |
+
}
|
2332 |
+
if ( strpos( $image_url, 'public/images/spacer.' ) ) {
|
2333 |
+
return array();
|
2334 |
+
}
|
2335 |
+
return $args;
|
2336 |
}
|
|
|
|
|
2337 |
|
2338 |
+
/**
|
2339 |
+
* Exclude images and other resources from being processed based on user specified list.
|
2340 |
+
*
|
2341 |
+
* @since 4.6.0
|
2342 |
+
*
|
2343 |
+
* @param boolean $skip Whether ExactDN should skip processing.
|
2344 |
+
* @param string $url Resource URL.
|
2345 |
+
* @return boolean True to skip the resource, unchanged otherwise.
|
2346 |
+
*/
|
2347 |
+
function exactdn_skip_user_exclusions( $skip, $url ) {
|
2348 |
+
if ( $this->user_exclusions ) {
|
2349 |
+
foreach ( $this->user_exclusions as $exclusion ) {
|
2350 |
+
if ( false !== strpos( $url, $exclusion ) ) {
|
2351 |
+
$this->debug_message( "user excluded $url via $exclusion" );
|
2352 |
+
return true;
|
2353 |
+
}
|
2354 |
}
|
2355 |
}
|
2356 |
+
return $skip;
|
2357 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2358 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2359 |
/**
|
2360 |
+
* Converts a local script/css url to use ExactDN.
|
2361 |
*
|
2362 |
+
* @param string $url URL to the resource being parsed.
|
2363 |
+
* @return string The ExactDN version of the resource, if it was local.
|
|
|
|
|
2364 |
*/
|
2365 |
+
function parse_enqueue( $url ) {
|
2366 |
+
if ( is_admin() ) {
|
2367 |
+
return $url;
|
2368 |
+
}
|
2369 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
2370 |
+
$parsed_url = $this->parse_url( $url );
|
|
|
|
|
|
|
2371 |
|
2372 |
+
if ( false !== strpos( $url, 'wp-admin/' ) ) {
|
2373 |
+
return $url;
|
2374 |
+
}
|
2375 |
+
if ( false !== strpos( $url, 'xmlrpc.php' ) ) {
|
2376 |
+
return $url;
|
2377 |
+
}
|
2378 |
+
if ( strpos( $url, 'wp-content/plugins/anti-captcha/' ) ) {
|
2379 |
+
return $url;
|
2380 |
+
}
|
2381 |
+
/**
|
2382 |
+
* Allow specific URLs to avoid going through ExactDN.
|
2383 |
+
*
|
2384 |
+
* @param bool false Should the URL be returned as is, without going through ExactDN. Default to false.
|
2385 |
+
* @param string $url Resource URL.
|
2386 |
+
* @param array|string $args Array of ExactDN arguments.
|
2387 |
+
* @param string|null $scheme URL scheme. Default to null.
|
2388 |
+
*/
|
2389 |
+
if ( true === apply_filters( 'exactdn_skip_for_url', false, $url, array(), null ) ) {
|
2390 |
+
return $url;
|
2391 |
+
}
|
2392 |
|
2393 |
+
// Unable to parse.
|
2394 |
+
if ( ! $parsed_url || ! is_array( $parsed_url ) || empty( $parsed_url['host'] ) || empty( $parsed_url['path'] ) ) {
|
2395 |
+
$this->debug_message( 'src url no good' );
|
2396 |
+
return $url;
|
2397 |
+
}
|
2398 |
|
2399 |
+
// No PHP files shall pass.
|
2400 |
+
if ( preg_match( '/\.php$/', $parsed_url['path'] ) ) {
|
2401 |
+
return $url;
|
2402 |
+
}
|
|
|
2403 |
|
2404 |
+
// Make sure this is an allowed image domain/hostname for ExactDN on this site.
|
2405 |
+
if ( ! $this->allow_image_domain( $parsed_url['host'] ) ) {
|
2406 |
+
$this->debug_message( "invalid host for ExactDN: {$parsed_url['host']}" );
|
2407 |
+
return $url;
|
2408 |
+
}
|
|
|
2409 |
|
2410 |
+
// Figure out which CDN (sub)domain to use.
|
2411 |
+
if ( empty( $this->exactdn_domain ) ) {
|
2412 |
+
$this->debug_message( 'no exactdn domain configured' );
|
2413 |
+
return $url;
|
|
|
|
|
2414 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2415 |
|
2416 |
+
// You can't run an ExactDN URL through again because query strings are stripped.
|
2417 |
+
// So if the image is already an ExactDN URL, append the new arguments to the existing URL.
|
2418 |
+
if ( $this->exactdn_domain === $parsed_url['host'] ) {
|
2419 |
+
$this->debug_message( 'url already has exactdn domain' );
|
2420 |
+
return $url;
|
2421 |
+
}
|
2422 |
|
2423 |
+
global $wp_version;
|
2424 |
+
// If a resource doesn't have a version string, we add one to help with cache-busting.
|
2425 |
+
if ( ( empty( $parsed_url['query'] ) || 'ver=' . $wp_version === $parsed_url['query'] ) && false !== strpos( $url, 'wp-content/' ) ) {
|
2426 |
+
$modified = $this->function_exists( 'filemtime' ) ? filemtime( get_template_directory() ) : '';
|
2427 |
+
if ( empty( $modified ) ) {
|
2428 |
+
$modified = $this->version;
|
2429 |
+
}
|
2430 |
+
/**
|
2431 |
+
* Allows a custom version string for resources that are missing one.
|
2432 |
+
*
|
2433 |
+
* @param string Defaults to the modified time of the theme folder, and falls back to the plugin version.
|
2434 |
+
*/
|
2435 |
+
$parsed_url['query'] = apply_filters( 'exactdn_version_string', "m=$modified" );
|
2436 |
+
} elseif ( empty( $parsed_url['query'] ) ) {
|
2437 |
+
$parsed_url['query'] = '';
|
2438 |
+
}
|
2439 |
|
2440 |
+
$exactdn_url = '//' . $this->exactdn_domain . '/' . ltrim( $parsed_url['path'], '/' ) . '?' . $parsed_url['query'];
|
2441 |
+
$this->debug_message( "exactdn css/script url: $exactdn_url" );
|
2442 |
+
return $exactdn_url;
|
2443 |
}
|
2444 |
|
2445 |
/**
|
2446 |
+
* Generates an ExactDN URL.
|
2447 |
*
|
2448 |
+
* @param string $image_url URL to the publicly accessible image you want to manipulate.
|
2449 |
+
* @param array|string $args An array of arguments, i.e. array( 'w' => '300', 'resize' => '123,456' ), or in string form (w=123&h=456).
|
2450 |
+
* @param string $scheme Indicates http or https, other schemes are invalid.
|
2451 |
+
* @return string The raw final URL. You should run this through esc_url() before displaying it.
|
2452 |
*/
|
2453 |
+
function generate_url( $image_url, $args = array(), $scheme = null ) {
|
2454 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
2455 |
+
$image_url = trim( $image_url );
|
2456 |
|
2457 |
+
if ( is_null( $scheme ) ) {
|
2458 |
+
$scheme = $this->scheme;
|
2459 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2460 |
|
2461 |
+
/**
|
2462 |
+
* Disables ExactDN URL processing for local development.
|
2463 |
+
*
|
2464 |
+
* @param bool false default
|
2465 |
+
*/
|
2466 |
+
if ( true === apply_filters( 'exactdn_development_mode', false ) ) {
|
2467 |
+
return $image_url;
|
2468 |
+
}
|
2469 |
|
2470 |
+
/**
|
2471 |
+
* Allow specific URLs to avoid going through ExactDN.
|
2472 |
+
*
|
2473 |
+
* @param bool false Should the URL be returned as is, without going through ExactDN. Default to false.
|
2474 |
+
* @param string $image_url Resource URL.
|
2475 |
+
* @param array|string $args Array of ExactDN arguments.
|
2476 |
+
* @param string|null $scheme URL scheme. Default to null.
|
2477 |
+
*/
|
2478 |
+
if ( true === apply_filters( 'exactdn_skip_for_url', false, $image_url, $args, $scheme ) ) {
|
2479 |
+
return $image_url;
|
2480 |
+
}
|
|
|
2481 |
|
2482 |
+
// TODO: Not differentiated yet, but it will be, so stay tuned!
|
2483 |
+
$jpg_quality = apply_filters( 'jpeg_quality', null, 'image_resize' );
|
2484 |
+
$webp_quality = apply_filters( 'jpeg_quality', $jpg_quality, 'image/webp' );
|
|
|
|
|
|
|
|
|
|
|
2485 |
|
2486 |
+
$more_args = array();
|
2487 |
+
if ( false === strpos( $image_url, 'strip=all' ) && $this->get_option( $this->prefix . 'metadata_remove' ) ) {
|
2488 |
+
$more_args['strip'] = 'all';
|
2489 |
+
}
|
2490 |
+
if ( false === strpos( $image_url, 'lossy=' ) && $this->get_option( 'exactdn_lossy' ) ) {
|
2491 |
+
$more_args['lossy'] = is_numeric( $this->get_option( 'exactdn_lossy' ) ) ? (int) $this->get_option( 'exactdn_lossy' ) : 80;
|
2492 |
+
}
|
2493 |
+
if ( false === strpos( $image_url, 'quality=' ) && ! is_null( $jpg_quality ) && 82 !== (int) $jpg_quality ) {
|
2494 |
+
$more_args['quality'] = $jpg_quality;
|
2495 |
+
}
|
2496 |
+
// Merge given args with the automatic (option-based) args, and also makes sure args is an array if it was previously a string.
|
2497 |
+
$args = wp_parse_args( $args, $more_args );
|
2498 |
|
2499 |
+
/**
|
2500 |
+
* Filter the original image URL before it goes through ExactDN.
|
2501 |
+
*
|
2502 |
+
* @param string $image_url Image URL.
|
2503 |
+
* @param array|string $args Array of ExactDN arguments.
|
2504 |
+
* @param string|null $scheme Image scheme. Default to null.
|
2505 |
+
*/
|
2506 |
+
$image_url = apply_filters( 'exactdn_pre_image_url', $image_url, $args, $scheme );
|
2507 |
|
2508 |
+
if ( empty( $image_url ) ) {
|
2509 |
+
return $image_url;
|
2510 |
+
}
|
|
|
|
|
2511 |
|
2512 |
+
$image_url_parts = $this->parse_url( $image_url );
|
2513 |
+
|
2514 |
+
// Unable to parse.
|
2515 |
+
if ( ! is_array( $image_url_parts ) || empty( $image_url_parts['host'] ) || empty( $image_url_parts['path'] ) ) {
|
2516 |
+
$this->debug_message( 'src url no good' );
|
2517 |
+
return $image_url;
|
2518 |
}
|
|
|
|
|
2519 |
|
2520 |
+
if ( isset( $image_url_parts['scheme'] ) && 'https' === $image_url_parts['scheme'] ) {
|
2521 |
+
if ( is_array( $args ) ) {
|
2522 |
+
$args['ssl'] = 1;
|
2523 |
+
}
|
2524 |
+
$scheme = 'https';
|
2525 |
+
}
|
|
|
|
|
2526 |
|
2527 |
+
/**
|
2528 |
+
* Filter the ExactDN image parameters before they are applied to an image.
|
2529 |
+
*
|
2530 |
+
* @param array|string $args Array of ExactDN arguments.
|
2531 |
+
* @param string $image_url Image URL.
|
2532 |
+
* @param string|null $scheme Image scheme. Default to null.
|
2533 |
+
*/
|
2534 |
+
$args = apply_filters( 'exactdn_pre_args', $args, $image_url, $scheme );
|
2535 |
+
|
2536 |
+
if ( is_array( $args ) ) {
|
2537 |
+
// Convert values that are arrays into strings.
|
2538 |
+
foreach ( $args as $arg => $value ) {
|
2539 |
+
if ( is_array( $value ) ) {
|
2540 |
+
$args[ $arg ] = implode( ',', $value );
|
2541 |
+
}
|
2542 |
}
|
2543 |
+
|
2544 |
+
// Encode argument values.
|
2545 |
+
$args = rawurlencode_deep( $args );
|
2546 |
}
|
2547 |
|
2548 |
+
$this->debug_message( $image_url_parts['host'] );
|
|
|
|
|
2549 |
|
2550 |
+
// Figure out which CDN (sub)domain to use.
|
2551 |
+
if ( empty( $this->exactdn_domain ) ) {
|
2552 |
+
$this->debug_message( 'no exactdn domain configured' );
|
2553 |
+
return $image_url;
|
2554 |
+
}
|
2555 |
|
2556 |
+
// You can't run an ExactDN URL through again because query strings are stripped.
|
2557 |
+
// So if the image is already an ExactDN URL, append the new arguments to the existing URL.
|
2558 |
+
if ( $this->exactdn_domain === $image_url_parts['host'] ) {
|
2559 |
+
$this->debug_message( 'url already has exactdn domain' );
|
2560 |
+
$exactdn_url = add_query_arg( $args, $image_url );
|
2561 |
+
return $this->url_scheme( $exactdn_url, $scheme );
|
2562 |
+
}
|
2563 |
|
2564 |
+
// ExactDN doesn't support query strings so we ignore them and look only at the path.
|
2565 |
+
// However some source images are served via PHP so check the no-query-string extension.
|
2566 |
+
// For future proofing, this is a blacklist of common issues rather than a whitelist.
|
2567 |
+
$extension = pathinfo( $image_url_parts['path'], PATHINFO_EXTENSION );
|
2568 |
+
if ( ( empty( $extension ) && false === strpos( $image_url_parts['path'], 'nextgen-image/' ) ) || in_array( $extension, array( 'php', 'ashx' ), true ) ) {
|
2569 |
+
$this->debug_message( 'bad extension' );
|
2570 |
+
return $image_url;
|
2571 |
+
}
|
2572 |
|
2573 |
+
if ( $this->remove_path && 0 === strpos( $image_url_parts['path'], $this->remove_path ) ) {
|
2574 |
+
$image_url_parts['path'] = substr( $image_url_parts['path'], strlen( $this->remove_path ) );
|
2575 |
+
}
|
2576 |
+
$domain = 'http://' . $this->exactdn_domain . '/';
|
2577 |
+
$exactdn_url = $domain . ltrim( $image_url_parts['path'], '/' );
|
2578 |
+
$this->debug_message( "bare exactdn url: $exactdn_url" );
|
|
|
|
|
2579 |
|
2580 |
+
/**
|
2581 |
+
* Add query strings to ExactDN URL.
|
2582 |
+
* By default, ExactDN doesn't support query strings so we ignore them.
|
2583 |
+
* This setting is ExactDN Server dependent.
|
2584 |
+
*
|
2585 |
+
* @param bool false Should query strings be added to the image URL. Default is false.
|
2586 |
+
* @param string $image_url_parts['host'] Image URL's host.
|
2587 |
+
*/
|
2588 |
+
if ( isset( $image_url_parts['query'] ) && apply_filters( 'exactdn_add_query_string_to_domain', false, $image_url_parts['host'] ) ) {
|
2589 |
+
$exactdn_url .= '?q=' . rawurlencode( $image_url_parts['query'] );
|
2590 |
+
}
|
2591 |
+
// This is disabled, as I don't think we really need it.
|
2592 |
+
if ( false && ! empty( $image_url_parts['query'] ) && false !== strpos( $image_url_parts['query'], 'theia_smart' ) ) {
|
2593 |
+
$args = wp_parse_args( $image_url_parts['query'], $args );
|
2594 |
+
}
|
2595 |
+
|
2596 |
+
if ( $args ) {
|
2597 |
+
if ( is_array( $args ) ) {
|
2598 |
+
$exactdn_url = add_query_arg( $args, $exactdn_url );
|
2599 |
+
} else {
|
2600 |
+
// You can pass a query string for complicated requests, although this should have been converted to an array already.
|
2601 |
+
$exactdn_url .= '?' . $args;
|
2602 |
+
}
|
2603 |
+
}
|
2604 |
+
$this->debug_message( "exactdn url with args: $exactdn_url" );
|
2605 |
+
|
2606 |
+
return $this->url_scheme( $exactdn_url, $scheme );
|
2607 |
}
|
|
|
|
|
|
|
2608 |
|
2609 |
/**
|
2610 |
+
* Prepends schemeless urls or replaces non-http scheme with a valid scheme, defaults to 'http'.
|
|
|
|
|
2611 |
*
|
2612 |
+
* @param string $url The URL to parse.
|
2613 |
+
* @param string|null $scheme Retrieve specific URL component.
|
2614 |
+
* @return string Result of parse_url.
|
2615 |
*/
|
2616 |
+
function url_scheme( $url, $scheme ) {
|
2617 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
2618 |
+
if ( ! in_array( $scheme, array( 'http', 'https' ), true ) ) {
|
2619 |
+
$this->debug_message( 'not a valid scheme' );
|
2620 |
+
if ( preg_match( '#^(https?:)?//#', $url ) ) {
|
2621 |
+
$this->debug_message( 'url has a valid scheme already' );
|
2622 |
+
return $url;
|
2623 |
+
}
|
2624 |
+
$this->debug_message( 'invalid scheme provided, and url sucks, defaulting to http' );
|
2625 |
+
$scheme = 'http';
|
|
|
|
|
|
|
|
|
2626 |
}
|
2627 |
+
$this->debug_message( "valid $scheme - $url" );
|
2628 |
+
return preg_replace( '#^([a-z:]+)?//#i', "$scheme://", $url );
|
2629 |
}
|
|
|
|
|
|
|
|
|
2630 |
|
2631 |
+
/**
|
2632 |
+
* A wrapper for PHP's parse_url, prepending assumed scheme for network path
|
2633 |
+
* URLs. PHP versions 5.4.6 and earlier do not correctly parse without scheme.
|
2634 |
+
*
|
2635 |
+
* @param string $url The URL to parse.
|
2636 |
+
* @param integer $component Retrieve specific URL component.
|
2637 |
+
* @return mixed Result of parse_url.
|
2638 |
+
*/
|
2639 |
+
function parse_url( $url, $component = -1 ) {
|
2640 |
+
if ( 0 === strpos( $url, '//' ) ) {
|
2641 |
+
$url = ( is_ssl() ? 'https:' : 'http:' ) . $url;
|
2642 |
+
}
|
2643 |
+
if ( false === strpos( $url, 'http' ) && '/' !== substr( $url, 0, 1 ) ) {
|
2644 |
+
$url = ( is_ssl() ? 'https://' : 'http://' ) . $url;
|
2645 |
}
|
2646 |
+
// Because encoded ampersands in the filename break things.
|
2647 |
+
$url = str_replace( '&', '&', $url );
|
2648 |
+
return parse_url( $url, $component );
|
2649 |
}
|
|
|
|
|
|
|
2650 |
|
2651 |
+
/**
|
2652 |
+
* A wrapper for human_time_diff() that gives sub-minute times in seconds.
|
2653 |
+
*
|
2654 |
+
* @param int $from Unix timestamp from which the difference begins.
|
2655 |
+
* @param int $to Optional. Unix timestamp to end the time difference. Default is time().
|
2656 |
+
* @return string Human readable time difference.
|
2657 |
+
*/
|
2658 |
+
function human_time_diff( $from, $to = '' ) {
|
2659 |
+
if ( empty( $to ) ) {
|
2660 |
+
$to = time();
|
2661 |
+
}
|
2662 |
+
$diff = (int) abs( $to - $from );
|
2663 |
+
if ( $diff < 60 ) {
|
2664 |
+
return "$diff sec";
|
2665 |
+
}
|
2666 |
+
return human_time_diff( $from, $to );
|
2667 |
}
|
|
|
|
|
|
|
|
|
2668 |
|
2669 |
+
/**
|
2670 |
+
* Adds link to header which enables DNS prefetching for faster speed.
|
2671 |
+
*
|
2672 |
+
* @param array $hints A list of hints for a particular relationship type.
|
2673 |
+
* @param string $relationship_type The type of hint being filtered: dns-prefetch, preconnect, etc.
|
2674 |
+
* @return array The list of hints, potentially with the ExactDN domain added in.
|
2675 |
+
*/
|
2676 |
+
function dns_prefetch( $hints, $relationship_type ) {
|
2677 |
+
if ( 'dns-prefetch' === $relationship_type && $this->exactdn_domain ) {
|
2678 |
+
$hints[] = '//' . $this->exactdn_domain;
|
2679 |
+
}
|
2680 |
+
return $hints;
|
|
|
|
|
2681 |
}
|
|
|
|
|
2682 |
|
2683 |
+
/**
|
2684 |
+
* Adds the ExactDN domain to the list of 'local' domains for Autoptimize.
|
2685 |
+
*
|
2686 |
+
* @param array $domains A list of domains considered 'local' by Autoptimize.
|
2687 |
+
* @return array The same list, with the ExactDN domain appended.
|
2688 |
+
*/
|
2689 |
+
function autoptimize_cdn_url( $domains ) {
|
2690 |
+
$this->debug_message( '<b>' . __METHOD__ . '()</b>' );
|
2691 |
+
if ( is_array( $domains ) && ! in_array( $this->exactdn_domain, $domains, true ) ) {
|
2692 |
+
$this->debug_message( 'adding to AO list: ' . $this->exactdn_domain );
|
2693 |
+
$domains[] = $this->exactdn_domain;
|
2694 |
+
}
|
2695 |
+
return $domains;
|
2696 |
}
|
|
|
2697 |
}
|
2698 |
|
2699 |
+
global $exactdn;
|
2700 |
+
$exactdn = new ExactDN();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2701 |
}
|
|
|
|
|
|
common.php
CHANGED
@@ -17,15 +17,15 @@
|
|
17 |
// TODO: check this patch, to see if the use of 'full' causes any issues: https://core.trac.wordpress.org/ticket/37840 .
|
18 |
// TODO: use this: https://codex.wordpress.org/AJAX_in_Plugins#The_post-load_JavaScript_Event .
|
19 |
// TODO: can some of the bulk "fallbacks" be implemented for async processing?
|
20 |
-
// TODO: check to see if we can use PHP and WP core
|
21 |
if ( ! defined( 'ABSPATH' ) ) {
|
22 |
exit;
|
23 |
}
|
24 |
|
25 |
-
define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '
|
26 |
|
27 |
// Initialize a couple globals.
|
28 |
-
$
|
29 |
$ewww_defer = true;
|
30 |
|
31 |
if ( WP_DEBUG && function_exists( 'memory_get_usage' ) ) {
|
@@ -122,10 +122,10 @@ add_filter( 'as3cf_attachment_file_paths', 'ewww_image_optimizer_as3cf_attachmen
|
|
122 |
add_filter( 'as3cf_object_meta', 'ewww_image_optimizer_as3cf_object_meta' );
|
123 |
// Loads the plugin translations.
|
124 |
add_action( 'plugins_loaded', 'ewww_image_optimizer_preinit' );
|
|
|
|
|
125 |
// Load our front-end parsers for ExactDN and/or Alt WebP.
|
126 |
add_action( 'init', 'ewww_image_optimizer_parser_init', 99 );
|
127 |
-
// Checks for nextgen/nextcellent/flagallery existence, and loads the appropriate classes.
|
128 |
-
add_action( 'init', 'ewww_image_optimizer_gallery_support' );
|
129 |
// Initializes the plugin for admin interactions, like saving network settings and scheduling cron jobs.
|
130 |
add_action( 'admin_init', 'ewww_image_optimizer_admin_init' );
|
131 |
// Check the current screen ID to see if temp debugging should still be enabled.
|
@@ -176,8 +176,12 @@ add_action( 'wp_ajax_ewww_manual_cloud_restore', 'ewww_image_optimizer_manual' )
|
|
176 |
add_action( 'wp_ajax_ewww_manual_cloud_restore_single', 'ewww_image_optimizer_cloud_restore_single_image_handler' );
|
177 |
// AJAX action hook to dismiss the WooCommerce regen notice.
|
178 |
add_action( 'wp_ajax_ewww_dismiss_wc_regen', 'ewww_image_optimizer_dismiss_wc_regen' );
|
|
|
|
|
179 |
// AJAX action hook to disable the media library notice.
|
180 |
add_action( 'wp_ajax_ewww_dismiss_media_notice', 'ewww_image_optimizer_dismiss_media_notice' );
|
|
|
|
|
181 |
// Adds script to highlight mis-sized images on the front-end (for logged in admins only).
|
182 |
add_action( 'wp_head', 'ewww_image_optimizer_resize_detection_script' );
|
183 |
// Adds a button on the admin bar to allow highlighting mis-sized images on-demand.
|
@@ -220,7 +224,7 @@ function ewww_image_optimizer_parser_init() {
|
|
220 |
/**
|
221 |
* Page Parsing class for working with HTML content.
|
222 |
*/
|
223 |
-
require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-
|
224 |
/**
|
225 |
* ExactDN class for parsing image urls and rewriting them.
|
226 |
*/
|
@@ -237,11 +241,11 @@ function ewww_image_optimizer_parser_init() {
|
|
237 |
/**
|
238 |
* Page Parsing class for working with HTML content.
|
239 |
*/
|
240 |
-
require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-
|
241 |
/**
|
242 |
-
*
|
243 |
*/
|
244 |
-
require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-
|
245 |
}
|
246 |
// If Alt WebP Rewriting is enabled.
|
247 |
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
|
@@ -249,11 +253,11 @@ function ewww_image_optimizer_parser_init() {
|
|
249 |
/**
|
250 |
* Page Parsing class for working with HTML content.
|
251 |
*/
|
252 |
-
require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-
|
253 |
/**
|
254 |
* Alt WebP class for parsing image urls and rewriting them for WebP support.
|
255 |
*/
|
256 |
-
require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-
|
257 |
}
|
258 |
if ( $buffer_start ) {
|
259 |
// Start an output buffer before any output starts.
|
@@ -486,16 +490,14 @@ function ewww_image_optimizer_preinit() {
|
|
486 |
}
|
487 |
|
488 |
/**
|
489 |
-
*
|
490 |
-
*
|
491 |
-
* If a supported gallery is found, loads the class(es) to support integration with that gallery.
|
492 |
*/
|
493 |
-
function
|
494 |
ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
|
495 |
|
496 |
// Check to see if this is the settings page and enable debugging temporarily if it is.
|
497 |
global $ewwwio_temp_debug;
|
498 |
-
$ewwwio_temp_debug = false;
|
499 |
if ( is_admin() && ! wp_doing_ajax() ) {
|
500 |
if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
|
501 |
$ewwwio_temp_debug = true;
|
@@ -536,6 +538,13 @@ function ewww_image_optimizer_gallery_support() {
|
|
536 |
}
|
537 |
}
|
538 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
539 |
}
|
540 |
|
541 |
/**
|
@@ -591,6 +600,24 @@ function ewww_image_optimizer_upgrade() {
|
|
591 |
update_option( 'ewww_image_optimizer_aux_resume', '' );
|
592 |
ewww_image_optimizer_delete_pending();
|
593 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
594 |
ewww_image_optimizer_remove_obsolete_settings();
|
595 |
update_option( 'ewww_image_optimizer_version', EWWW_IMAGE_OPTIMIZER_VERSION );
|
596 |
ewww_image_optimizer_debug_log();
|
@@ -836,6 +863,15 @@ function ewww_image_optimizer_admin_init() {
|
|
836 |
add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_reoptimization' );
|
837 |
add_action( 'admin_notices', 'ewww_image_optimizer_notice_reoptimization' );
|
838 |
add_action( 'admin_notices', 'ewww_image_optimizer_notice_media_listmode' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
839 |
if ( ! empty( $_GET['page'] ) ) {
|
840 |
if ( 'regenerate-thumbnails' === $_GET['page']
|
841 |
|| 'force-regenerate-thumbnails' === $_GET['page']
|
@@ -846,10 +882,6 @@ function ewww_image_optimizer_admin_init() {
|
|
846 |
add_action( 'admin_notices', 'ewww_image_optimizer_thumbnail_regen_notice' );
|
847 |
}
|
848 |
}
|
849 |
-
if ( class_exists( 'WooCommerce' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_wc_regen' ) ) {
|
850 |
-
add_action( 'admin_notices', 'ewww_image_optimizer_notice_wc_regen' );
|
851 |
-
add_action( 'admin_footer', 'ewww_image_optimizer_wc_regen_script' );
|
852 |
-
}
|
853 |
if ( ! empty( $_GET['ewww_pngout'] ) ) {
|
854 |
add_action( 'admin_notices', 'ewww_image_optimizer_pngout_installed' );
|
855 |
add_action( 'network_admin_notices', 'ewww_image_optimizer_pngout_installed' );
|
@@ -858,6 +890,14 @@ function ewww_image_optimizer_admin_init() {
|
|
858 |
ewww_image_optimizer_privacy_policy_content();
|
859 |
ewww_image_optimizer_ajax_compat_check();
|
860 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
861 |
// Increase the version when the next bump is coming.
|
862 |
if ( defined( 'PHP_VERSION_ID' ) && PHP_VERSION_ID < 50600 ) {
|
863 |
add_action( 'network_admin_notices', 'ewww_image_optimizer_php55_warning' );
|
@@ -989,10 +1029,10 @@ function ewww_image_optimizer_privacy_policy_content() {
|
|
989 |
*/
|
990 |
function ewww_image_optimizer_current_screen( $screen ) {
|
991 |
global $ewwwio_temp_debug;
|
992 |
-
global $
|
993 |
-
if ( false === strpos( $screen->id, 'settings_page_ewww-image-optimizer' ) ) {
|
994 |
$ewwwio_temp_debug = false;
|
995 |
-
$
|
996 |
}
|
997 |
}
|
998 |
|
@@ -1169,6 +1209,7 @@ function ewww_image_optimizer_save_admin_colors() {
|
|
1169 |
$ewwwio_admin_color = '#0073aa';
|
1170 |
}
|
1171 |
}
|
|
|
1172 |
/**
|
1173 |
* Determines the background color to use based on the selected admin theme.
|
1174 |
*/
|
@@ -1452,6 +1493,9 @@ function ewww_image_optimizer_remove_obsolete_settings() {
|
|
1452 |
delete_option( 'ewww_image_optimizer_bulk_image_count' );
|
1453 |
delete_option( 'ewww_image_optimizer_maxwidth' );
|
1454 |
delete_option( 'ewww_image_optimizer_maxheight' );
|
|
|
|
|
|
|
1455 |
}
|
1456 |
|
1457 |
/**
|
@@ -1475,6 +1519,29 @@ function ewww_image_optimizer_pngout_installed() {
|
|
1475 |
}
|
1476 |
}
|
1477 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1478 |
/**
|
1479 |
* Display a notice that PHP version 5.5 support is going away.
|
1480 |
*/
|
@@ -1530,6 +1597,32 @@ function ewww_image_optimizer_wc_regen_script() {
|
|
1530 |
"</script>\n";
|
1531 |
}
|
1532 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1533 |
/**
|
1534 |
* Let the user know they can view more options and stats in the Media Library's list mode.
|
1535 |
*/
|
@@ -1540,6 +1633,49 @@ function ewww_image_optimizer_notice_media_listmode() {
|
|
1540 |
}
|
1541 |
}
|
1542 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1543 |
/**
|
1544 |
* Alert the user when 5 images have been re-optimized more than 10 times.
|
1545 |
*
|
@@ -1870,6 +2006,10 @@ function ewww_image_optimizer_handle_upload( $params ) {
|
|
1870 |
} else {
|
1871 |
$file_path = $params['file'];
|
1872 |
}
|
|
|
|
|
|
|
|
|
1873 |
ewww_image_optimizer_autorotate( $file_path );
|
1874 |
$new_image = ewww_image_optimizer_autoconvert( $file_path );
|
1875 |
if ( $new_image ) {
|
@@ -1888,7 +2028,6 @@ function ewww_image_optimizer_handle_upload( $params ) {
|
|
1888 |
}
|
1889 |
$file_path = $new_image;
|
1890 |
}
|
1891 |
-
// NOTE: if you use the ewww_image_optimizer_defer_resizing filter to defer the resize operation, only the "other" dimensions will apply
|
1892 |
// Resize here unless the user chose to defer resizing or imsanity is enabled with a max size.
|
1893 |
if ( ! apply_filters( 'ewww_image_optimizer_defer_resizing', false ) && ! function_exists( 'imsanity_get_max_width_height' ) ) {
|
1894 |
if ( empty( $params['type'] ) ) {
|
@@ -1900,6 +2039,7 @@ function ewww_image_optimizer_handle_upload( $params ) {
|
|
1900 |
ewww_image_optimizer_resize_upload( $file_path );
|
1901 |
}
|
1902 |
}
|
|
|
1903 |
return $params;
|
1904 |
}
|
1905 |
|
@@ -2692,7 +2832,7 @@ function ewww_image_optimizer_filesize( $file ) {
|
|
2692 |
* @return bool True if the variable is iterable.
|
2693 |
*/
|
2694 |
function ewww_image_optimizer_iterable( $var ) {
|
2695 |
-
return ! empty( $var ) && ( is_array( $var ) ||
|
2696 |
}
|
2697 |
|
2698 |
/**
|
@@ -4299,7 +4439,7 @@ function ewww_image_optimizer_size_format( $size, $precision = 1 ) {
|
|
4299 |
* @global object $wpdb
|
4300 |
* @global object $ewwwdb A clone of $wpdb unless it is lacking utf8 connectivity.
|
4301 |
* @global bool $ewww_defer Set to false to avoid deferring image optimization.
|
4302 |
-
* @global string $
|
4303 |
* @global object $ewww_image Contains more information about the image currently being processed.
|
4304 |
*
|
4305 |
* @param array $attachment {
|
@@ -4404,8 +4544,8 @@ function ewww_image_optimizer_aux_images_loop( $attachment = null, $auto = false
|
|
4404 |
number_format_i18n( $elapsed )
|
4405 |
);
|
4406 |
if ( get_site_option( 'ewww_image_optimizer_debug' ) ) {
|
4407 |
-
global $
|
4408 |
-
$output['results'] .= '<div style="background-color:#f1f1f1;">' . $
|
4409 |
}
|
4410 |
$next_file = ewww_image_optimizer_absolutize_path( $wpdb->get_var( "SELECT path FROM $wpdb->ewwwio_images WHERE pending=1 LIMIT 1" ) );
|
4411 |
if ( ! empty( $next_file ) ) {
|
@@ -6085,6 +6225,56 @@ function ewww_image_optimizer_resize_from_meta_data( $meta, $id = null, $log = t
|
|
6085 |
return $meta;
|
6086 |
}
|
6087 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6088 |
/**
|
6089 |
* Check to see if Shield's location lock option is enabled.
|
6090 |
*
|
@@ -7293,6 +7483,20 @@ function ewww_image_optimizer_dismiss_wc_regen() {
|
|
7293 |
wp_die();
|
7294 |
}
|
7295 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7296 |
/**
|
7297 |
* Disables the Media Library notice about List Mode.
|
7298 |
*/
|
@@ -7308,6 +7512,21 @@ function ewww_image_optimizer_dismiss_media_notice() {
|
|
7308 |
wp_die();
|
7309 |
}
|
7310 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7311 |
/**
|
7312 |
* Load JS in media library footer for bulk actions.
|
7313 |
*/
|
@@ -7746,9 +7965,6 @@ function ewww_image_optimizer_get_image_sizes() {
|
|
7746 |
if ( is_array( $image_sizes ) ) {
|
7747 |
ewwwio_debug_message( 'sizes: ' . implode( '<br>', $image_sizes ) );
|
7748 |
}
|
7749 |
-
if ( false ) { // set to true to enable more debugging.
|
7750 |
-
ewwwio_debug_message( print_r( $_wp_additional_image_sizes, true ) );
|
7751 |
-
}
|
7752 |
if ( ewww_image_optimizer_iterable( $image_sizes ) ) {
|
7753 |
foreach ( $image_sizes as $_size ) {
|
7754 |
if ( in_array( $_size, array( 'thumbnail', 'medium', 'medium_large', 'large' ), true ) ) {
|
@@ -7781,8 +7997,6 @@ function ewww_image_optimizer_get_image_sizes() {
|
|
7781 |
|
7782 |
/**
|
7783 |
* Wrapper that displays the EWWW IO options in the multisite network admin.
|
7784 |
-
*
|
7785 |
-
* @global string $ewww_debug In memory debug log.
|
7786 |
*/
|
7787 |
function ewww_image_optimizer_network_options() {
|
7788 |
ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
|
@@ -7795,8 +8009,6 @@ function ewww_image_optimizer_network_options() {
|
|
7795 |
*
|
7796 |
* By default, the only options displayed are the per-site resizes list, but a network admin can
|
7797 |
* permit site admins to configure their own blog settings.
|
7798 |
-
*
|
7799 |
-
* @global string $ewww_debug In memory debug log.
|
7800 |
*/
|
7801 |
function ewww_image_optimizer_network_singlesite_options() {
|
7802 |
ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
|
@@ -7807,7 +8019,7 @@ function ewww_image_optimizer_network_singlesite_options() {
|
|
7807 |
/**
|
7808 |
* Displays the EWWW IO options along with status information, and debugging information.
|
7809 |
*
|
7810 |
-
* @global string $
|
7811 |
*
|
7812 |
* @param string $network Indicates which options should be shown in multisite installations.
|
7813 |
*/
|
@@ -7842,8 +8054,8 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
|
|
7842 |
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
7843 |
}
|
7844 |
if ( 'debug-silent' !== $network ) {
|
7845 |
-
global $
|
7846 |
-
$
|
7847 |
}
|
7848 |
if ( is_multisite() && is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) && ! get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) ) {
|
7849 |
$network_class = 'network-multisite';
|
@@ -7930,6 +8142,13 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
|
|
7930 |
}
|
7931 |
if ( class_exists( 'Jetpack_Photon' ) && Jetpack::is_module_active( 'photon' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
|
7932 |
$status_notices .= '<p><b>ExactDN:</b> <span style="color: red">' . esc_html__( 'Inactive, please disable the Image Performance option on the Jetpack Dashboard.', 'ewww-image-optimizer' ) . '</span></p>';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7933 |
} elseif ( class_exists( 'ExactDN' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
|
7934 |
$status_notices .= '<p><b>ExactDN:</b> ';
|
7935 |
global $exactdn;
|
@@ -8198,12 +8417,11 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
|
|
8198 |
! ( 'network-singlesite' === $network && ! get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) ) ) { // Also make sure that this isn't single site without override mode.
|
8199 |
$output[] = "<ul class='ewww-tab-nav'>\n" .
|
8200 |
"<li class='ewww-tab ewww-general-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Basic', 'ewww-image-optimizer' ) . "</span></li>\n" .
|
8201 |
-
"<li class='ewww-tab ewww-exactdn-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'ExactDN', 'ewww-image-optimizer' ) . "</span></li>\n" .
|
8202 |
"<li class='ewww-tab ewww-optimization-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Advanced', 'ewww-image-optimizer' ) . "</span></li>\n" .
|
8203 |
"<li class='ewww-tab ewww-resize-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Resize', 'ewww-image-optimizer' ) . "</span></li>\n" .
|
8204 |
"<li class='ewww-tab ewww-conversion-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Convert', 'ewww-image-optimizer' ) . "</span></li>\n" .
|
8205 |
"<li class='ewww-tab ewww-webp-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'WebP', 'ewww-image-optimizer' ) . "</span></li>\n" .
|
8206 |
-
// "<li class='ewww-tab ewww-tools-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Tools', 'ewww-image-optimizer' ) . "</span></li>\n" .
|
8207 |
"<li class='ewww-tab ewww-overrides-nav'><span class='ewww-tab-hidden'><a href='https://docs.ewww.io/article/40-override-options' target='_blank'><span class='ewww-tab-hidden'>" . esc_html__( 'Overrides', 'ewww-image-optimizer' ) . "</a></span></li>\n" .
|
8208 |
"<li class='ewww-tab ewww-support-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Support', 'ewww-image-optimizer' ) . "</span></li>\n" .
|
8209 |
"<li class='ewww-tab ewww-contribute-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Contribute', 'ewww-image-optimizer' ) . "</span></li>\n" .
|
@@ -8578,7 +8796,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
|
|
8578 |
$output[] = "<div id='ewww-webp-settings'>\n";
|
8579 |
$output[] = '<noscript><h2>' . esc_html__( 'WebP', 'ewww-image-optimizer' ) . '</h2></noscript>';
|
8580 |
$output[] = "<table class='form-table'>\n";
|
8581 |
-
if ( !
|
8582 |
$output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_webp'>" . esc_html__( 'JPG/PNG to WebP', 'ewww-image-optimizer' ) . '</label>' .
|
8583 |
ewwwio_help_link( 'https://docs.ewww.io/article/16-ewww-io-and-webp-images', '5854745ac697912ffd6c1c89' ) .
|
8584 |
"</th><td><span><input type='checkbox' id='ewww_image_optimizer_webp' name='ewww_image_optimizer_webp' value='true' " .
|
@@ -8594,7 +8812,7 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
|
|
8594 |
esc_html__( 'WebP images will be generated and saved for all JPG/PNG images regardless of their size. The JS WebP Rewriting will not check if a file exists, only that the domain matches the home url.', 'ewww-image-optimizer' ) . "</span></td></tr>\n";
|
8595 |
ewwwio_debug_message( 'forced webp: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ? 'on' : 'off' ) );
|
8596 |
}
|
8597 |
-
if ( ! ewww_image_optimizer_ce_webp_enabled() && !
|
8598 |
$webp_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' ) ? esc_html( implode( "\n", ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' ) ) ) : '';
|
8599 |
$output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_webp_paths'>" . esc_html__( 'WebP URLs', 'ewww-image-optimizer' ) . '</label>' .
|
8600 |
ewwwio_help_link( 'https://docs.ewww.io/article/16-ewww-io-and-webp-images', '5854745ac697912ffd6c1c89' ) . '</th><td>' .
|
@@ -8612,6 +8830,8 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
|
|
8612 |
ewwwio_debug_message( 'alt webp rewriting: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) ? 'on' : 'off' ) );
|
8613 |
} elseif ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
|
8614 |
$output[] = "<tr class='$network_class'><th> </th><td><p class='description'>" . esc_html__( 'WebP images are served automatically by ExactDN.', 'ewww-image-optimizer' ) . '</p></td></tr>';
|
|
|
|
|
8615 |
}
|
8616 |
$output[] = "</table>\n</div>\n";
|
8617 |
|
@@ -8659,10 +8879,10 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
|
|
8659 |
$output[] = "<p class='submit'><input type='submit' class='button-primary' value='" . esc_attr__( 'Save Changes', 'ewww-image-optimizer' ) . "' /></p>\n";
|
8660 |
$output[] = "</form>\n";
|
8661 |
// Make sure .htaccess rules are terminated when ExactDN is enabled.
|
8662 |
-
if (
|
8663 |
ewww_image_optimizer_webp_rewrite_verify();
|
8664 |
}
|
8665 |
-
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) && ! ewww_image_optimizer_ce_webp_enabled() && !
|
8666 |
if ( ! apache_mod_loaded( 'mod_rewrite' ) ) {
|
8667 |
ewwwio_debug_message( 'webp missing mod_rewrite' );
|
8668 |
/* translators: %s: mod_rewrite or mod_headers */
|
@@ -8725,22 +8945,22 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
|
|
8725 |
return;
|
8726 |
}
|
8727 |
$output = apply_filters( 'ewww_image_optimizer_settings', $output );
|
8728 |
-
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) && ! ewww_image_optimizer_ce_webp_enabled() && !
|
8729 |
-
global $
|
8730 |
-
$
|
8731 |
}
|
8732 |
|
8733 |
$help_instructions = esc_html__( 'Enable the Debugging option and refresh this page to include debugging information with your question.', 'ewww-image-optimizer' ) . ' ' .
|
8734 |
esc_html__( 'This will allow us to assist you more quickly.', 'ewww-image-optimizer' );
|
8735 |
|
8736 |
-
global $
|
8737 |
-
if ( ! empty( $
|
8738 |
$debug_output = '<p style="clear:both"><b>' . esc_html__( 'Debugging Information', 'ewww-image-optimizer' ) . ':</b> <button id="ewww-copy-debug" class="button button-secondary" type="button">' . esc_html__( 'Copy', 'ewww-image-optimizer' ) . '</button>';
|
8739 |
if ( is_file( WP_CONTENT_DIR . '/ewww/debug.log' ) ) {
|
8740 |
$debug_output .= " <a href='admin.php?action=ewww_image_optimizer_view_debug_log'>" . esc_html( 'View Debug Log', 'ewww-image-optimizer' ) . "</a> - <a href='admin.php?action=ewww_image_optimizer_delete_debug_log'>" . esc_html( 'Remove Debug Log', 'ewww-image-optimizer' ) . '</a>';
|
8741 |
}
|
8742 |
$debug_output .= '</p>';
|
8743 |
-
$debug_output .= '<div id="ewww-debug-info" style="border:1px solid #e5e5e5;background:#fff;overflow:auto;height:300px;width:800px;" contenteditable="true">' . $
|
8744 |
|
8745 |
$help_instructions = esc_html__( 'Debugging information will be included with your message automatically.', 'ewww-image-optimizer' ) . ' ' .
|
8746 |
esc_html__( 'This will allow us to assist you more quickly.', 'ewww-image-optimizer' );
|
@@ -8767,12 +8987,12 @@ function ewww_image_optimizer_options( $network = 'singlesite' ) {
|
|
8767 |
$hs_identify = array(
|
8768 |
'email' => utf8_encode( $help_email ),
|
8769 |
);
|
8770 |
-
if ( ! empty( $
|
8771 |
-
$
|
8772 |
-
$
|
8773 |
-
foreach ( $
|
8774 |
-
$hs_identify[ 'debug_info_' . $
|
8775 |
-
$
|
8776 |
}
|
8777 |
}
|
8778 |
?>
|
@@ -8871,6 +9091,16 @@ function ewwwio_help_link( $link, $hsid = '' ) {
|
|
8871 |
return "<a class='$link_class' href='$link' target='_blank' style='margin: 3px'$beacon_attr><img title='" . esc_attr__( 'Help', 'ewww-image-optimizer' ) . "' src='$help_icon'></a>";
|
8872 |
}
|
8873 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8874 |
/**
|
8875 |
* Removes the API key currently installed.
|
8876 |
*
|
@@ -8990,7 +9220,7 @@ function ewww_image_optimizer_admin_bar_menu() {
|
|
8990 |
/**
|
8991 |
* Adds information to the in-memory debug log.
|
8992 |
*
|
8993 |
-
* @global string $
|
8994 |
*
|
8995 |
* @param string $message Debug information to add to the log.
|
8996 |
*/
|
@@ -9003,14 +9233,14 @@ function ewwwio_debug_message( $message ) {
|
|
9003 |
if ( $ewwwio_temp_debug || ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
|
9004 |
$memory_limit = ewwwio_memory_limit();
|
9005 |
if ( strlen( $message ) + 4000000 + memory_get_usage( true ) <= $memory_limit ) {
|
9006 |
-
global $
|
9007 |
-
$message
|
9008 |
-
$message
|
9009 |
-
$message
|
9010 |
-
$
|
9011 |
} else {
|
9012 |
-
global $
|
9013 |
-
$
|
9014 |
}
|
9015 |
}
|
9016 |
}
|
@@ -9018,13 +9248,13 @@ function ewwwio_debug_message( $message ) {
|
|
9018 |
/**
|
9019 |
* Saves the in-memory debug log to a logfile in the plugin folder.
|
9020 |
*
|
9021 |
-
* @global string $
|
9022 |
*/
|
9023 |
function ewww_image_optimizer_debug_log() {
|
9024 |
-
global $
|
9025 |
global $ewwwio_temp_debug;
|
9026 |
$debug_log = WP_CONTENT_DIR . '/ewww/debug.log';
|
9027 |
-
if ( ! empty( $
|
9028 |
$memory_limit = ewwwio_memory_limit();
|
9029 |
clearstatcache();
|
9030 |
$timestamp = date( 'Y-m-d H:i:s' ) . "\n";
|
@@ -9036,12 +9266,12 @@ function ewww_image_optimizer_debug_log() {
|
|
9036 |
touch( $debug_log );
|
9037 |
}
|
9038 |
}
|
9039 |
-
if ( filesize( $debug_log ) + strlen( $
|
9040 |
-
$
|
9041 |
-
file_put_contents( $debug_log, $timestamp . $
|
9042 |
}
|
9043 |
}
|
9044 |
-
$
|
9045 |
ewwwio_memory( __FUNCTION__ );
|
9046 |
}
|
9047 |
|
@@ -9081,35 +9311,35 @@ function ewww_image_optimizer_delete_debug_log() {
|
|
9081 |
/**
|
9082 |
* Adds version information to the in-memory debug log.
|
9083 |
*
|
9084 |
-
* @global string $
|
9085 |
* @global int $wp_version
|
9086 |
*/
|
9087 |
function ewwwio_debug_version_info() {
|
9088 |
-
global $
|
9089 |
if ( ! extension_loaded( 'suhosin' ) && function_exists( 'get_current_user' ) ) {
|
9090 |
-
$
|
9091 |
}
|
9092 |
|
9093 |
-
$
|
9094 |
|
9095 |
// Check the WP version.
|
9096 |
global $wp_version;
|
9097 |
-
$my_version
|
9098 |
-
$
|
9099 |
|
9100 |
if ( defined( 'PHP_VERSION_ID' ) ) {
|
9101 |
-
$
|
9102 |
}
|
9103 |
if ( defined( 'LIBXML_VERSION' ) ) {
|
9104 |
-
$
|
9105 |
}
|
9106 |
if ( ! empty( $_ENV['PANTHEON_ENVIRONMENT'] ) && in_array( $_ENV['PANTHEON_ENVIRONMENT'], array( 'test', 'live', 'dev' ), true ) ) {
|
9107 |
-
$
|
9108 |
}
|
9109 |
if ( defined( 'EWWW_IO_CLOUD_PLUGIN' ) && EWWW_IO_CLOUD_PLUGIN ) {
|
9110 |
-
$
|
9111 |
} else {
|
9112 |
-
$
|
9113 |
}
|
9114 |
}
|
9115 |
|
@@ -9274,9 +9504,9 @@ function ewww_image_optimizer_image_queue_debug() {
|
|
9274 |
*/
|
9275 |
function ewww_image_optimizer_temp_debug_clear() {
|
9276 |
global $ewwwio_temp_debug;
|
9277 |
-
global $
|
9278 |
if ( $ewwwio_temp_debug ) {
|
9279 |
-
$
|
9280 |
}
|
9281 |
$ewwwio_temp_debug = false;
|
9282 |
}
|
17 |
// TODO: check this patch, to see if the use of 'full' causes any issues: https://core.trac.wordpress.org/ticket/37840 .
|
18 |
// TODO: use this: https://codex.wordpress.org/AJAX_in_Plugins#The_post-load_JavaScript_Event .
|
19 |
// TODO: can some of the bulk "fallbacks" be implemented for async processing?
|
20 |
+
// TODO: check to see if we can use PHP and WP core is_countable functions.
|
21 |
if ( ! defined( 'ABSPATH' ) ) {
|
22 |
exit;
|
23 |
}
|
24 |
|
25 |
+
define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '493.0' );
|
26 |
|
27 |
// Initialize a couple globals.
|
28 |
+
$eio_debug = '';
|
29 |
$ewww_defer = true;
|
30 |
|
31 |
if ( WP_DEBUG && function_exists( 'memory_get_usage' ) ) {
|
122 |
add_filter( 'as3cf_object_meta', 'ewww_image_optimizer_as3cf_object_meta' );
|
123 |
// Loads the plugin translations.
|
124 |
add_action( 'plugins_loaded', 'ewww_image_optimizer_preinit' );
|
125 |
+
// Runs any checks that need to run everywhere and early.
|
126 |
+
add_action( 'init', 'ewww_image_optimizer_init', 9 );
|
127 |
// Load our front-end parsers for ExactDN and/or Alt WebP.
|
128 |
add_action( 'init', 'ewww_image_optimizer_parser_init', 99 );
|
|
|
|
|
129 |
// Initializes the plugin for admin interactions, like saving network settings and scheduling cron jobs.
|
130 |
add_action( 'admin_init', 'ewww_image_optimizer_admin_init' );
|
131 |
// Check the current screen ID to see if temp debugging should still be enabled.
|
176 |
add_action( 'wp_ajax_ewww_manual_cloud_restore_single', 'ewww_image_optimizer_cloud_restore_single_image_handler' );
|
177 |
// AJAX action hook to dismiss the WooCommerce regen notice.
|
178 |
add_action( 'wp_ajax_ewww_dismiss_wc_regen', 'ewww_image_optimizer_dismiss_wc_regen' );
|
179 |
+
// AJAX action hook to dismiss the WP/LR Sync regen notice.
|
180 |
+
add_action( 'wp_ajax_ewww_dismiss_lr_sync', 'ewww_image_optimizer_dismiss_lr_sync' );
|
181 |
// AJAX action hook to disable the media library notice.
|
182 |
add_action( 'wp_ajax_ewww_dismiss_media_notice', 'ewww_image_optimizer_dismiss_media_notice' );
|
183 |
+
// AJAX action hook to disable the 'review request' notice.
|
184 |
+
add_action( 'wp_ajax_ewww_dismiss_review_notice', 'ewww_image_optimizer_dismiss_review_notice' );
|
185 |
// Adds script to highlight mis-sized images on the front-end (for logged in admins only).
|
186 |
add_action( 'wp_head', 'ewww_image_optimizer_resize_detection_script' );
|
187 |
// Adds a button on the admin bar to allow highlighting mis-sized images on-demand.
|
224 |
/**
|
225 |
* Page Parsing class for working with HTML content.
|
226 |
*/
|
227 |
+
require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-eio-page-parser.php' );
|
228 |
/**
|
229 |
* ExactDN class for parsing image urls and rewriting them.
|
230 |
*/
|
241 |
/**
|
242 |
* Page Parsing class for working with HTML content.
|
243 |
*/
|
244 |
+
require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-eio-page-parser.php' );
|
245 |
/**
|
246 |
+
* Lazy Load class for parsing image urls and rewriting them to defer off-screen images.
|
247 |
*/
|
248 |
+
require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-eio-lazy-load.php' );
|
249 |
}
|
250 |
// If Alt WebP Rewriting is enabled.
|
251 |
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
|
253 |
/**
|
254 |
* Page Parsing class for working with HTML content.
|
255 |
*/
|
256 |
+
require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-eio-page-parser.php' );
|
257 |
/**
|
258 |
* Alt WebP class for parsing image urls and rewriting them for WebP support.
|
259 |
*/
|
260 |
+
require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-eio-alt-webp.php' );
|
261 |
}
|
262 |
if ( $buffer_start ) {
|
263 |
// Start an output buffer before any output starts.
|
490 |
}
|
491 |
|
492 |
/**
|
493 |
+
* Runs early for checks that need to happen on init before anything else.
|
|
|
|
|
494 |
*/
|
495 |
+
function ewww_image_optimizer_init() {
|
496 |
ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
|
497 |
|
498 |
// Check to see if this is the settings page and enable debugging temporarily if it is.
|
499 |
global $ewwwio_temp_debug;
|
500 |
+
$ewwwio_temp_debug = ! empty( $ewwwio_temp_debug ) ? $ewwwio_temp_debug : false;
|
501 |
if ( is_admin() && ! wp_doing_ajax() ) {
|
502 |
if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
|
503 |
$ewwwio_temp_debug = true;
|
538 |
}
|
539 |
}
|
540 |
}
|
541 |
+
if ( defined( 'DOING_WPLR_REQUEST' ) && DOING_WPLR_REQUEST ) {
|
542 |
+
// Unhook all automatic processing, and save an option that (does not autoload) tells the user LR Sync regenerated their images and they should run the bulk optimizer.
|
543 |
+
remove_filter( 'wp_image_editors', 'ewww_image_optimizer_load_editor', 60 );
|
544 |
+
remove_filter( 'wp_generate_attachment_metadata', 'ewww_image_optimizer_resize_from_meta_data', 15 );
|
545 |
+
add_filter( 'wp_generate_attachment_metadata', 'ewww_image_optimizer_lr_sync_update' );
|
546 |
+
return;
|
547 |
+
}
|
548 |
}
|
549 |
|
550 |
/**
|
600 |
update_option( 'ewww_image_optimizer_aux_resume', '' );
|
601 |
ewww_image_optimizer_delete_pending();
|
602 |
}
|
603 |
+
if ( get_option( 'ewww_image_optimizer_version' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_review_time' ) ) {
|
604 |
+
$review_time = rand( time(), time() + 51 * DAY_IN_SECONDS );
|
605 |
+
add_option( 'ewww_image_optimizer_review_time', $review_time, '', false );
|
606 |
+
add_site_option( 'ewww_image_optimizer_review_time', $review_time );
|
607 |
+
} elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_review_time' ) ) {
|
608 |
+
$review_time = time() + 7 * DAY_IN_SECONDS;
|
609 |
+
add_option( 'ewww_image_optimizer_review_time', $review_time, '', false );
|
610 |
+
add_site_option( 'ewww_image_optimizer_review_time', $review_time );
|
611 |
+
}
|
612 |
+
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
|
613 |
+
if ( 'external' === get_option( 'elementor_css_print_method' ) ) {
|
614 |
+
update_option( 'elementor_css_print_method', 'internal' );
|
615 |
+
}
|
616 |
+
if ( function_exists( 'et_get_option' ) && function_exists( 'et_update_option' ) && 'on' === et_get_option( 'et_pb_static_css_file', 'on' ) ) {
|
617 |
+
et_update_option( 'et_pb_static_css_file', 'off' );
|
618 |
+
et_update_option( 'et_pb_css_in_footer', 'off' );
|
619 |
+
}
|
620 |
+
}
|
621 |
ewww_image_optimizer_remove_obsolete_settings();
|
622 |
update_option( 'ewww_image_optimizer_version', EWWW_IMAGE_OPTIMIZER_VERSION );
|
623 |
ewww_image_optimizer_debug_log();
|
863 |
add_action( 'network_admin_notices', 'ewww_image_optimizer_notice_reoptimization' );
|
864 |
add_action( 'admin_notices', 'ewww_image_optimizer_notice_reoptimization' );
|
865 |
add_action( 'admin_notices', 'ewww_image_optimizer_notice_media_listmode' );
|
866 |
+
if (
|
867 |
+
is_super_admin() &&
|
868 |
+
ewww_image_optimizer_get_option( 'ewww_image_optimizer_review_time' ) &&
|
869 |
+
ewww_image_optimizer_get_option( 'ewww_image_optimizer_review_time' ) < time() &&
|
870 |
+
! ewww_image_optimizer_get_option( 'ewww_image_optimizer_dismiss_review_notice' )
|
871 |
+
) {
|
872 |
+
add_action( 'admin_notices', 'ewww_image_optimizer_notice_review' );
|
873 |
+
add_action( 'admin_footer', 'ewww_image_optimizer_notice_review_script' );
|
874 |
+
}
|
875 |
if ( ! empty( $_GET['page'] ) ) {
|
876 |
if ( 'regenerate-thumbnails' === $_GET['page']
|
877 |
|| 'force-regenerate-thumbnails' === $_GET['page']
|
882 |
add_action( 'admin_notices', 'ewww_image_optimizer_thumbnail_regen_notice' );
|
883 |
}
|
884 |
}
|
|
|
|
|
|
|
|
|
885 |
if ( ! empty( $_GET['ewww_pngout'] ) ) {
|
886 |
add_action( 'admin_notices', 'ewww_image_optimizer_pngout_installed' );
|
887 |
add_action( 'network_admin_notices', 'ewww_image_optimizer_pngout_installed' );
|
890 |
ewww_image_optimizer_privacy_policy_content();
|
891 |
ewww_image_optimizer_ajax_compat_check();
|
892 |
}
|
893 |
+
if ( class_exists( 'WooCommerce' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_wc_regen' ) ) {
|
894 |
+
add_action( 'admin_notices', 'ewww_image_optimizer_notice_wc_regen' );
|
895 |
+
add_action( 'admin_footer', 'ewww_image_optimizer_wc_regen_script' );
|
896 |
+
}
|
897 |
+
if ( class_exists( 'Meow_WPLR_Sync_Core' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_lr_sync' ) ) {
|
898 |
+
add_action( 'admin_notices', 'ewww_image_optimizer_notice_lr_sync' );
|
899 |
+
add_action( 'admin_footer', 'ewww_image_optimizer_lr_sync_script' );
|
900 |
+
}
|
901 |
// Increase the version when the next bump is coming.
|
902 |
if ( defined( 'PHP_VERSION_ID' ) && PHP_VERSION_ID < 50600 ) {
|
903 |
add_action( 'network_admin_notices', 'ewww_image_optimizer_php55_warning' );
|
1029 |
*/
|
1030 |
function ewww_image_optimizer_current_screen( $screen ) {
|
1031 |
global $ewwwio_temp_debug;
|
1032 |
+
global $eio_debug;
|
1033 |
+
if ( false === strpos( $screen->id, 'settings_page_ewww-image-optimizer' ) && false === strpos( $screen->id, 'settings_page_easy-image-optimizer' ) ) {
|
1034 |
$ewwwio_temp_debug = false;
|
1035 |
+
$eio_debug = '';
|
1036 |
}
|
1037 |
}
|
1038 |
|
1209 |
$ewwwio_admin_color = '#0073aa';
|
1210 |
}
|
1211 |
}
|
1212 |
+
|
1213 |
/**
|
1214 |
* Determines the background color to use based on the selected admin theme.
|
1215 |
*/
|
1493 |
delete_option( 'ewww_image_optimizer_bulk_image_count' );
|
1494 |
delete_option( 'ewww_image_optimizer_maxwidth' );
|
1495 |
delete_option( 'ewww_image_optimizer_maxheight' );
|
1496 |
+
delete_option( 'ewww_image_optimizer_exactdn_failures' );
|
1497 |
+
delete_option( 'ewww_image_optimizer_exactdn_checkin' );
|
1498 |
+
delete_option( 'ewww_image_optimizer_exactdn_suspended' );
|
1499 |
}
|
1500 |
|
1501 |
/**
|
1519 |
}
|
1520 |
}
|
1521 |
|
1522 |
+
/**
|
1523 |
+
* Display a notice that we could not activate an ExactDN domain.
|
1524 |
+
*/
|
1525 |
+
function ewww_image_optimizer_notice_exactdn_activation_error() {
|
1526 |
+
global $exactdn_activate_error;
|
1527 |
+
if ( empty( $exactdn_activate_error ) ) {
|
1528 |
+
$exactdn_activate_error = 'error unknown';
|
1529 |
+
}
|
1530 |
+
echo '<div id="ewww-image-optimizer-notice-exactdn-error" class="notice notice-error"><p>' .
|
1531 |
+
esc_html__( 'Could not activate ExactDN, please try again in a few minutes. If this error continues, please contact support and provide this complete error message.', 'ewww-image-optimizer' ) .
|
1532 |
+
'<br><code>' . $exactdn_activate_error . '</code>' .
|
1533 |
+
'</p></div>';
|
1534 |
+
}
|
1535 |
+
|
1536 |
+
/**
|
1537 |
+
* Let the user know ExactDN setup was successful.
|
1538 |
+
*/
|
1539 |
+
function ewww_image_optimizer_notice_exactdn_activation_success() {
|
1540 |
+
echo '<div id="ewww-image-optimizer-notice-exactdn-success" class="notice notice-success"><p>' .
|
1541 |
+
esc_html__( 'ExactDN setup and verification is complete.', 'ewww-image-optimizer' ) .
|
1542 |
+
'</p></div>';
|
1543 |
+
}
|
1544 |
+
|
1545 |
/**
|
1546 |
* Display a notice that PHP version 5.5 support is going away.
|
1547 |
*/
|
1597 |
"</script>\n";
|
1598 |
}
|
1599 |
|
1600 |
+
/**
|
1601 |
+
* Lets the user know LR Sync has regenerated thumbnails and that they need to take action.
|
1602 |
+
*/
|
1603 |
+
function ewww_image_optimizer_notice_lr_sync() {
|
1604 |
+
echo "<div id='ewww-image-optimizer-lr-sync' class='notice notice-info is-dismissible'><p>" . esc_html__( 'EWWW Image Optimizer has detected a WP/LR Sync process. To optimize new thumbnails, you may run the Bulk Optimizer from the Media menu. This notice may be dismissed after the Sync process is complete.', 'ewww-image-optimizer' ) . '</p></div>';
|
1605 |
+
}
|
1606 |
+
|
1607 |
+
/**
|
1608 |
+
* Loads the inline script to dismiss the LR sync notice.
|
1609 |
+
*/
|
1610 |
+
function ewww_image_optimizer_lr_sync_script() {
|
1611 |
+
echo
|
1612 |
+
"<script>\n" .
|
1613 |
+
"jQuery(document).on('click', '#ewww-image-optimizer-lr-sync .notice-dismiss', function() {\n" .
|
1614 |
+
"\tvar ewww_dismiss_lr_sync_data = {\n" .
|
1615 |
+
"\t\taction: 'ewww_dismiss_lr_sync',\n" .
|
1616 |
+
"\t};\n" .
|
1617 |
+
"\tjQuery.post(ajaxurl, ewww_dismiss_lr_sync_data, function(response) {\n" .
|
1618 |
+
"\t\tif (response) {\n" .
|
1619 |
+
"\t\t\tconsole.log(response);\n" .
|
1620 |
+
"\t\t}\n" .
|
1621 |
+
"\t});\n" .
|
1622 |
+
"});\n" .
|
1623 |
+
"</script>\n";
|
1624 |
+
}
|
1625 |
+
|
1626 |
/**
|
1627 |
* Let the user know they can view more options and stats in the Media Library's list mode.
|
1628 |
*/
|
1633 |
}
|
1634 |
}
|
1635 |
|
1636 |
+
/**
|
1637 |
+
* Ask the user to leave a review for the plugin on wp.org.
|
1638 |
+
*/
|
1639 |
+
function ewww_image_optimizer_notice_review() {
|
1640 |
+
echo "<div id='ewww-image-optimizer-review' class='notice notice-info is-dismissible'><p>" .
|
1641 |
+
esc_html__( "Hi, you've been using the EWWW Image Optimizer for a while, and we hope it has been a big help for you.", 'ewww-image-optimizer' ) . '<br>' .
|
1642 |
+
esc_html__( 'If you could take a few moments to rate it on WordPress.org, we would really appreciate your help making the plugin better. Thanks!', 'ewww-image-optimizer' ) .
|
1643 |
+
'<br><a target="_blank" href="https://wordpress.org/support/plugin/ewww-image-optimizer/reviews/#new-post" class="button-secondary">' . esc_html__( 'Post Review', 'ewww-image-optimizer' ) . '</a>' .
|
1644 |
+
'</p></div>';
|
1645 |
+
}
|
1646 |
+
|
1647 |
+
/**
|
1648 |
+
* Loads the inline script to dismiss the review notice.
|
1649 |
+
*/
|
1650 |
+
function ewww_image_optimizer_notice_review_script() {
|
1651 |
+
echo
|
1652 |
+
"<script>\n" .
|
1653 |
+
"jQuery(document).on('click', '#ewww-image-optimizer-review .notice-dismiss', function() {\n" .
|
1654 |
+
"\tvar ewww_dismiss_review_data = {\n" .
|
1655 |
+
"\t\taction: 'ewww_dismiss_review_notice',\n" .
|
1656 |
+
"\t};\n" .
|
1657 |
+
"\tjQuery.post(ajaxurl, ewww_dismiss_review_data, function(response) {\n" .
|
1658 |
+
"\t\tif (response) {\n" .
|
1659 |
+
"\t\t\tconsole.log(response);\n" .
|
1660 |
+
"\t\t}\n" .
|
1661 |
+
"\t});\n" .
|
1662 |
+
"});\n" .
|
1663 |
+
"</script>\n";
|
1664 |
+
}
|
1665 |
+
|
1666 |
+
/**
|
1667 |
+
* Inform the user of our beacon function so that they can opt-in.
|
1668 |
+
*/
|
1669 |
+
function ewww_image_optimizer_notice_beacon() {
|
1670 |
+
$optin_url = 'admin.php?action=eio_opt_into_hs_beacon';
|
1671 |
+
$optout_url = 'admin.php?action=eio_opt_out_of_hs_beacon';
|
1672 |
+
echo '<div id="ewww-image-optimizer-hs-beacon" class="notice notice-info"><p>' .
|
1673 |
+
esc_html__( 'Enable the EWWW I.O. support beacon, which gives you access to documentation and our support team right from your WordPress dashboard. To assist you more efficiently, we collect the current url, IP address, browser/device information, and debugging information.', 'ewww-image-optimizer' ) .
|
1674 |
+
'<br><a href="' . esc_url( $optin_url ) . '" class="button-secondary">' . esc_html__( 'Allow', 'ewww-image-optimizer' ) . '</a>' .
|
1675 |
+
' <a href="' . esc_url( $optout_url ) . '" class="button-secondary">' . esc_html__( 'Do not allow', 'ewww-image-optimizer' ) . '</a>' .
|
1676 |
+
'</p></div>';
|
1677 |
+
}
|
1678 |
+
|
1679 |
/**
|
1680 |
* Alert the user when 5 images have been re-optimized more than 10 times.
|
1681 |
*
|
2006 |
} else {
|
2007 |
$file_path = $params['file'];
|
2008 |
}
|
2009 |
+
if ( ! is_file( $file_path ) || ! filesize( $file_path ) ) {
|
2010 |
+
clearstatcache();
|
2011 |
+
return $params;
|
2012 |
+
}
|
2013 |
ewww_image_optimizer_autorotate( $file_path );
|
2014 |
$new_image = ewww_image_optimizer_autoconvert( $file_path );
|
2015 |
if ( $new_image ) {
|
2028 |
}
|
2029 |
$file_path = $new_image;
|
2030 |
}
|
|
|
2031 |
// Resize here unless the user chose to defer resizing or imsanity is enabled with a max size.
|
2032 |
if ( ! apply_filters( 'ewww_image_optimizer_defer_resizing', false ) && ! function_exists( 'imsanity_get_max_width_height' ) ) {
|
2033 |
if ( empty( $params['type'] ) ) {
|
2039 |
ewww_image_optimizer_resize_upload( $file_path );
|
2040 |
}
|
2041 |
}
|
2042 |
+
clearstatcache();
|
2043 |
return $params;
|
2044 |
}
|
2045 |
|
2832 |
* @return bool True if the variable is iterable.
|
2833 |
*/
|
2834 |
function ewww_image_optimizer_iterable( $var ) {
|
2835 |
+
return ! empty( $var ) && ( is_array( $var ) || $var instanceof Traversable );
|
2836 |
}
|
2837 |
|
2838 |
/**
|
4439 |
* @global object $wpdb
|
4440 |
* @global object $ewwwdb A clone of $wpdb unless it is lacking utf8 connectivity.
|
4441 |
* @global bool $ewww_defer Set to false to avoid deferring image optimization.
|
4442 |
+
* @global string $eio_debug Contains in-memory debug log.
|
4443 |
* @global object $ewww_image Contains more information about the image currently being processed.
|
4444 |
*
|
4445 |
* @param array $attachment {
|
4544 |
number_format_i18n( $elapsed )
|
4545 |
);
|
4546 |
if ( get_site_option( 'ewww_image_optimizer_debug' ) ) {
|
4547 |
+
global $eio_debug;
|
4548 |
+
$output['results'] .= '<div style="background-color:#f1f1f1;">' . $eio_debug . '</div>';
|
4549 |
}
|
4550 |
$next_file = ewww_image_optimizer_absolutize_path( $wpdb->get_var( "SELECT path FROM $wpdb->ewwwio_images WHERE pending=1 LIMIT 1" ) );
|
4551 |
if ( ! empty( $next_file ) ) {
|
6225 |
return $meta;
|
6226 |
}
|
6227 |
|
6228 |
+
/**
|
6229 |
+
* Only runs during WP/LR Sync to check if an attachment has been updated.
|
6230 |
+
*
|
6231 |
+
* @param array $meta The attachment metadata generated by WordPress.
|
6232 |
+
* @param int $id Optional. The attachment ID number. Default null. Accepts any non-negative integer.
|
6233 |
+
* @return array $meta Send the metadata back from whence it came.
|
6234 |
+
*/
|
6235 |
+
function ewww_image_optimizer_lr_sync_update( $meta, $id = null ) {
|
6236 |
+
update_option( 'ewww_image_optimizer_lr_sync', true, false );
|
6237 |
+
list( $file_path, $upload_path ) = ewww_image_optimizer_attachment_path( $meta, $id );
|
6238 |
+
if ( ewww_image_optimizer_stream_wrapped( $file_path ) || ! is_file( $file_path ) ) {
|
6239 |
+
return $meta;
|
6240 |
+
}
|
6241 |
+
ewwwio_debug_message( "retrieved file path: $file_path" );
|
6242 |
+
$type = ewww_image_optimizer_mimetype( $file_path, 'i' );
|
6243 |
+
$supported_types = array(
|
6244 |
+
'image/jpeg',
|
6245 |
+
'image/png',
|
6246 |
+
'image/gif',
|
6247 |
+
'application/pdf',
|
6248 |
+
);
|
6249 |
+
if ( ! in_array( $type, $supported_types, true ) ) {
|
6250 |
+
ewwwio_debug_message( "mimetype not supported: $id" );
|
6251 |
+
return $meta;
|
6252 |
+
}
|
6253 |
+
|
6254 |
+
// Get a list of all the image files optimized for this attachment.
|
6255 |
+
global $wpdb;
|
6256 |
+
$optimized_images = $wpdb->get_results( $wpdb->prepare( "SELECT id,path,image_size FROM $wpdb->ewwwio_images WHERE attachment_id = %d AND gallery = 'media' AND image_size <> 0 ORDER BY orig_size DESC", $id ), ARRAY_A );
|
6257 |
+
if ( ! ewww_image_optimizer_iterable( $optimized_images ) ) {
|
6258 |
+
return $meta;
|
6259 |
+
}
|
6260 |
+
foreach ( $optimized_images as $optimized_image ) {
|
6261 |
+
$file_size = ewww_image_optimizer_filesize( ewww_image_optimizer_absolutize_path( $optimized_image['path'] ) );
|
6262 |
+
if ( $file_size === (int) $optimized_image['image_size'] ) {
|
6263 |
+
continue;
|
6264 |
+
}
|
6265 |
+
$wpdb->update(
|
6266 |
+
$wpdb->ewwwio_images,
|
6267 |
+
array(
|
6268 |
+
'image_size' => 0,
|
6269 |
+
),
|
6270 |
+
array(
|
6271 |
+
'id' => $optimized_image['id'],
|
6272 |
+
)
|
6273 |
+
);
|
6274 |
+
}
|
6275 |
+
return $meta;
|
6276 |
+
}
|
6277 |
+
|
6278 |
/**
|
6279 |
* Check to see if Shield's location lock option is enabled.
|
6280 |
*
|
7483 |
wp_die();
|
7484 |
}
|
7485 |
|
7486 |
+
/**
|
7487 |
+
* Dismisses the LR sync notice.
|
7488 |
+
*/
|
7489 |
+
function ewww_image_optimizer_dismiss_lr_sync() {
|
7490 |
+
ewwwio_ob_clean();
|
7491 |
+
ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
|
7492 |
+
// Verify that the user is properly authorized.
|
7493 |
+
if ( ! current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', 'manage_options' ) ) ) {
|
7494 |
+
wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
|
7495 |
+
}
|
7496 |
+
delete_option( 'ewww_image_optimizer_lr_sync' );
|
7497 |
+
wp_die();
|
7498 |
+
}
|
7499 |
+
|
7500 |
/**
|
7501 |
* Disables the Media Library notice about List Mode.
|
7502 |
*/
|
7512 |
wp_die();
|
7513 |
}
|
7514 |
|
7515 |
+
/**
|
7516 |
+
* Disables the notice about leaving a review.
|
7517 |
+
*/
|
7518 |
+
function ewww_image_optimizer_dismiss_review_notice() {
|
7519 |
+
ewwwio_ob_clean();
|
7520 |
+
ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
|
7521 |
+
// Verify that the user is properly authorized.
|
7522 |
+
if ( ! current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', 'manage_options' ) ) ) {
|
7523 |
+
wp_die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
|
7524 |
+
}
|
7525 |
+
update_option( 'ewww_image_optimizer_dismiss_review_notice', true, false );
|
7526 |
+
update_site_option( 'ewww_image_optimizer_dismiss_review_notice', true );
|
7527 |
+
wp_die();
|
7528 |
+
}
|
7529 |
+
|
7530 |
/**
|
7531 |
* Load JS in media library footer for bulk actions.
|
7532 |
*/
|
7965 |
if ( is_array( $image_sizes ) ) {
|
7966 |
ewwwio_debug_message( 'sizes: ' . implode( '<br>', $image_sizes ) );
|
7967 |
}
|
|
|
|
|
|
|
7968 |
if ( ewww_image_optimizer_iterable( $image_sizes ) ) {
|
7969 |
foreach ( $image_sizes as $_size ) {
|
7970 |
if ( in_array( $_size, array( 'thumbnail', 'medium', 'medium_large', 'large' ), true ) ) {
|
7997 |
|
7998 |
/**
|
7999 |
* Wrapper that displays the EWWW IO options in the multisite network admin.
|
|
|
|
|
8000 |
*/
|
8001 |
function ewww_image_optimizer_network_options() {
|
8002 |
ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
|
8009 |
*
|
8010 |
* By default, the only options displayed are the per-site resizes list, but a network admin can
|
8011 |
* permit site admins to configure their own blog settings.
|
|
|
|
|
8012 |
*/
|
8013 |
function ewww_image_optimizer_network_singlesite_options() {
|
8014 |
ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
|
8019 |
/**
|
8020 |
* Displays the EWWW IO options along with status information, and debugging information.
|
8021 |
*
|
8022 |
+
* @global string $eio_debug In memory debug log.
|
8023 |
*
|
8024 |
* @param string $network Indicates which options should be shown in multisite installations.
|
8025 |
*/
|
8054 |
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
8055 |
}
|
8056 |
if ( 'debug-silent' !== $network ) {
|
8057 |
+
global $eio_hs_beacon;
|
8058 |
+
$eio_hs_beacon->admin_notice( $network_class );
|
8059 |
}
|
8060 |
if ( is_multisite() && is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) && ! get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) ) {
|
8061 |
$network_class = 'network-multisite';
|
8142 |
}
|
8143 |
if ( class_exists( 'Jetpack_Photon' ) && Jetpack::is_module_active( 'photon' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
|
8144 |
$status_notices .= '<p><b>ExactDN:</b> <span style="color: red">' . esc_html__( 'Inactive, please disable the Image Performance option on the Jetpack Dashboard.', 'ewww-image-optimizer' ) . '</span></p>';
|
8145 |
+
} elseif ( get_option( 'easyio_exactdn' ) ) {
|
8146 |
+
ewww_image_optimizer_webp_rewrite_verify();
|
8147 |
+
update_option( 'ewww_image_optimizer_exactdn', false );
|
8148 |
+
update_option( 'ewww_image_optimizer_lazy_load', false );
|
8149 |
+
update_option( 'ewww_image_optimizer_webp_for_cdn', false );
|
8150 |
+
$compress_score += 80;
|
8151 |
+
$resize_score += 50;
|
8152 |
} elseif ( class_exists( 'ExactDN' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
|
8153 |
$status_notices .= '<p><b>ExactDN:</b> ';
|
8154 |
global $exactdn;
|
8417 |
! ( 'network-singlesite' === $network && ! get_site_option( 'ewww_image_optimizer_allow_multisite_override' ) ) ) { // Also make sure that this isn't single site without override mode.
|
8418 |
$output[] = "<ul class='ewww-tab-nav'>\n" .
|
8419 |
"<li class='ewww-tab ewww-general-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Basic', 'ewww-image-optimizer' ) . "</span></li>\n" .
|
8420 |
+
( get_option( 'easyio_exactdn' ) ? '' : "<li class='ewww-tab ewww-exactdn-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'ExactDN', 'ewww-image-optimizer' ) . "</span></li>\n" ) .
|
8421 |
"<li class='ewww-tab ewww-optimization-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Advanced', 'ewww-image-optimizer' ) . "</span></li>\n" .
|
8422 |
"<li class='ewww-tab ewww-resize-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Resize', 'ewww-image-optimizer' ) . "</span></li>\n" .
|
8423 |
"<li class='ewww-tab ewww-conversion-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Convert', 'ewww-image-optimizer' ) . "</span></li>\n" .
|
8424 |
"<li class='ewww-tab ewww-webp-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'WebP', 'ewww-image-optimizer' ) . "</span></li>\n" .
|
|
|
8425 |
"<li class='ewww-tab ewww-overrides-nav'><span class='ewww-tab-hidden'><a href='https://docs.ewww.io/article/40-override-options' target='_blank'><span class='ewww-tab-hidden'>" . esc_html__( 'Overrides', 'ewww-image-optimizer' ) . "</a></span></li>\n" .
|
8426 |
"<li class='ewww-tab ewww-support-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Support', 'ewww-image-optimizer' ) . "</span></li>\n" .
|
8427 |
"<li class='ewww-tab ewww-contribute-nav'><span class='ewww-tab-hidden'>" . esc_html__( 'Contribute', 'ewww-image-optimizer' ) . "</span></li>\n" .
|
8796 |
$output[] = "<div id='ewww-webp-settings'>\n";
|
8797 |
$output[] = '<noscript><h2>' . esc_html__( 'WebP', 'ewww-image-optimizer' ) . '</h2></noscript>';
|
8798 |
$output[] = "<table class='form-table'>\n";
|
8799 |
+
if ( ! ewww_image_optimizer_easy_active() || ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) ) {
|
8800 |
$output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_webp'>" . esc_html__( 'JPG/PNG to WebP', 'ewww-image-optimizer' ) . '</label>' .
|
8801 |
ewwwio_help_link( 'https://docs.ewww.io/article/16-ewww-io-and-webp-images', '5854745ac697912ffd6c1c89' ) .
|
8802 |
"</th><td><span><input type='checkbox' id='ewww_image_optimizer_webp' name='ewww_image_optimizer_webp' value='true' " .
|
8812 |
esc_html__( 'WebP images will be generated and saved for all JPG/PNG images regardless of their size. The JS WebP Rewriting will not check if a file exists, only that the domain matches the home url.', 'ewww-image-optimizer' ) . "</span></td></tr>\n";
|
8813 |
ewwwio_debug_message( 'forced webp: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ? 'on' : 'off' ) );
|
8814 |
}
|
8815 |
+
if ( ! ewww_image_optimizer_ce_webp_enabled() && ! ewww_image_optimizer_easy_active() ) {
|
8816 |
$webp_paths = ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' ) ? esc_html( implode( "\n", ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_paths' ) ) ) : '';
|
8817 |
$output[] = "<tr class='$network_class'><th scope='row'><label for='ewww_image_optimizer_webp_paths'>" . esc_html__( 'WebP URLs', 'ewww-image-optimizer' ) . '</label>' .
|
8818 |
ewwwio_help_link( 'https://docs.ewww.io/article/16-ewww-io-and-webp-images', '5854745ac697912ffd6c1c89' ) . '</th><td>' .
|
8830 |
ewwwio_debug_message( 'alt webp rewriting: ' . ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) ? 'on' : 'off' ) );
|
8831 |
} elseif ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
|
8832 |
$output[] = "<tr class='$network_class'><th> </th><td><p class='description'>" . esc_html__( 'WebP images are served automatically by ExactDN.', 'ewww-image-optimizer' ) . '</p></td></tr>';
|
8833 |
+
} elseif ( get_option( 'easyio_exactdn' ) ) {
|
8834 |
+
$output[] = "<tr class='$network_class'><th> </th><td><p class='description'>" . esc_html__( 'WebP images are served automatically by Easy Image Optimizer.', 'ewww-image-optimizer' ) . '</p></td></tr>';
|
8835 |
}
|
8836 |
$output[] = "</table>\n</div>\n";
|
8837 |
|
8879 |
$output[] = "<p class='submit'><input type='submit' class='button-primary' value='" . esc_attr__( 'Save Changes', 'ewww-image-optimizer' ) . "' /></p>\n";
|
8880 |
$output[] = "</form>\n";
|
8881 |
// Make sure .htaccess rules are terminated when ExactDN is enabled.
|
8882 |
+
if ( ewww_image_optimizer_easy_active() ) {
|
8883 |
ewww_image_optimizer_webp_rewrite_verify();
|
8884 |
}
|
8885 |
+
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) && ! ewww_image_optimizer_ce_webp_enabled() && ! ewww_image_optimizer_easy_active() ) {
|
8886 |
if ( ! apache_mod_loaded( 'mod_rewrite' ) ) {
|
8887 |
ewwwio_debug_message( 'webp missing mod_rewrite' );
|
8888 |
/* translators: %s: mod_rewrite or mod_headers */
|
8945 |
return;
|
8946 |
}
|
8947 |
$output = apply_filters( 'ewww_image_optimizer_settings', $output );
|
8948 |
+
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_for_cdn' ) && ! ewww_image_optimizer_ce_webp_enabled() && ! ewww_image_optimizer_easy_active() ) {
|
8949 |
+
global $eio_alt_webp;
|
8950 |
+
$eio_alt_webp->inline_script();
|
8951 |
}
|
8952 |
|
8953 |
$help_instructions = esc_html__( 'Enable the Debugging option and refresh this page to include debugging information with your question.', 'ewww-image-optimizer' ) . ' ' .
|
8954 |
esc_html__( 'This will allow us to assist you more quickly.', 'ewww-image-optimizer' );
|
8955 |
|
8956 |
+
global $eio_debug;
|
8957 |
+
if ( ! empty( $eio_debug ) ) {
|
8958 |
$debug_output = '<p style="clear:both"><b>' . esc_html__( 'Debugging Information', 'ewww-image-optimizer' ) . ':</b> <button id="ewww-copy-debug" class="button button-secondary" type="button">' . esc_html__( 'Copy', 'ewww-image-optimizer' ) . '</button>';
|
8959 |
if ( is_file( WP_CONTENT_DIR . '/ewww/debug.log' ) ) {
|
8960 |
$debug_output .= " <a href='admin.php?action=ewww_image_optimizer_view_debug_log'>" . esc_html( 'View Debug Log', 'ewww-image-optimizer' ) . "</a> - <a href='admin.php?action=ewww_image_optimizer_delete_debug_log'>" . esc_html( 'Remove Debug Log', 'ewww-image-optimizer' ) . '</a>';
|
8961 |
}
|
8962 |
$debug_output .= '</p>';
|
8963 |
+
$debug_output .= '<div id="ewww-debug-info" style="border:1px solid #e5e5e5;background:#fff;overflow:auto;height:300px;width:800px;" contenteditable="true">' . $eio_debug . '</div>';
|
8964 |
|
8965 |
$help_instructions = esc_html__( 'Debugging information will be included with your message automatically.', 'ewww-image-optimizer' ) . ' ' .
|
8966 |
esc_html__( 'This will allow us to assist you more quickly.', 'ewww-image-optimizer' );
|
8987 |
$hs_identify = array(
|
8988 |
'email' => utf8_encode( $help_email ),
|
8989 |
);
|
8990 |
+
if ( ! empty( $eio_debug ) ) {
|
8991 |
+
$eio_debug_array = explode( '<br>', $eio_debug );
|
8992 |
+
$eio_debug_i = 0;
|
8993 |
+
foreach ( $eio_debug_array as $eio_debug_line ) {
|
8994 |
+
$hs_identify[ 'debug_info_' . $eio_debug_i ] = $eio_debug_line;
|
8995 |
+
$eio_debug_i++;
|
8996 |
}
|
8997 |
}
|
8998 |
?>
|
9091 |
return "<a class='$link_class' href='$link' target='_blank' style='margin: 3px'$beacon_attr><img title='" . esc_attr__( 'Help', 'ewww-image-optimizer' ) . "' src='$help_icon'></a>";
|
9092 |
}
|
9093 |
|
9094 |
+
/**
|
9095 |
+
* Checks to see if ExactDN or Easy I.O. is active.
|
9096 |
+
*/
|
9097 |
+
function ewww_image_optimizer_easy_active() {
|
9098 |
+
if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) || get_option( 'easyio_exactdn' ) ) {
|
9099 |
+
return true;
|
9100 |
+
}
|
9101 |
+
return false;
|
9102 |
+
}
|
9103 |
+
|
9104 |
/**
|
9105 |
* Removes the API key currently installed.
|
9106 |
*
|
9220 |
/**
|
9221 |
* Adds information to the in-memory debug log.
|
9222 |
*
|
9223 |
+
* @global string $eio_debug The in-memory debug log.
|
9224 |
*
|
9225 |
* @param string $message Debug information to add to the log.
|
9226 |
*/
|
9233 |
if ( $ewwwio_temp_debug || ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) ) {
|
9234 |
$memory_limit = ewwwio_memory_limit();
|
9235 |
if ( strlen( $message ) + 4000000 + memory_get_usage( true ) <= $memory_limit ) {
|
9236 |
+
global $eio_debug;
|
9237 |
+
$message = str_replace( "\n\n\n", '<br>', $message );
|
9238 |
+
$message = str_replace( "\n\n", '<br>', $message );
|
9239 |
+
$message = str_replace( "\n", '<br>', $message );
|
9240 |
+
$eio_debug .= "$message<br>";
|
9241 |
} else {
|
9242 |
+
global $eio_debug;
|
9243 |
+
$eio_debug = "not logging message, memory limit is $memory_limit";
|
9244 |
}
|
9245 |
}
|
9246 |
}
|
9248 |
/**
|
9249 |
* Saves the in-memory debug log to a logfile in the plugin folder.
|
9250 |
*
|
9251 |
+
* @global string $eio_debug The in-memory debug log.
|
9252 |
*/
|
9253 |
function ewww_image_optimizer_debug_log() {
|
9254 |
+
global $eio_debug;
|
9255 |
global $ewwwio_temp_debug;
|
9256 |
$debug_log = WP_CONTENT_DIR . '/ewww/debug.log';
|
9257 |
+
if ( ! empty( $eio_debug ) && empty( $ewwwio_temp_debug ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_debug' ) && is_writable( WP_CONTENT_DIR . '/ewww/' ) ) {
|
9258 |
$memory_limit = ewwwio_memory_limit();
|
9259 |
clearstatcache();
|
9260 |
$timestamp = date( 'Y-m-d H:i:s' ) . "\n";
|
9266 |
touch( $debug_log );
|
9267 |
}
|
9268 |
}
|
9269 |
+
if ( filesize( $debug_log ) + strlen( $eio_debug ) + 4000000 + memory_get_usage( true ) <= $memory_limit && is_writable( $debug_log ) ) {
|
9270 |
+
$eio_debug = str_replace( '<br>', "\n", $eio_debug );
|
9271 |
+
file_put_contents( $debug_log, $timestamp . $eio_debug, FILE_APPEND );
|
9272 |
}
|
9273 |
}
|
9274 |
+
$eio_debug = '';
|
9275 |
ewwwio_memory( __FUNCTION__ );
|
9276 |
}
|
9277 |
|
9311 |
/**
|
9312 |
* Adds version information to the in-memory debug log.
|
9313 |
*
|
9314 |
+
* @global string $eio_debug The in-memory debug log.
|
9315 |
* @global int $wp_version
|
9316 |
*/
|
9317 |
function ewwwio_debug_version_info() {
|
9318 |
+
global $eio_debug;
|
9319 |
if ( ! extension_loaded( 'suhosin' ) && function_exists( 'get_current_user' ) ) {
|
9320 |
+
$eio_debug .= get_current_user() . '<br>';
|
9321 |
}
|
9322 |
|
9323 |
+
$eio_debug .= 'EWWW IO version: ' . EWWW_IMAGE_OPTIMIZER_VERSION . '<br>';
|
9324 |
|
9325 |
// Check the WP version.
|
9326 |
global $wp_version;
|
9327 |
+
$my_version = substr( $wp_version, 0, 3 );
|
9328 |
+
$eio_debug .= "WP version: $wp_version<br>";
|
9329 |
|
9330 |
if ( defined( 'PHP_VERSION_ID' ) ) {
|
9331 |
+
$eio_debug .= 'PHP version: ' . PHP_VERSION_ID . '<br>';
|
9332 |
}
|
9333 |
if ( defined( 'LIBXML_VERSION' ) ) {
|
9334 |
+
$eio_debug .= 'libxml version: ' . LIBXML_VERSION . '<br>';
|
9335 |
}
|
9336 |
if ( ! empty( $_ENV['PANTHEON_ENVIRONMENT'] ) && in_array( $_ENV['PANTHEON_ENVIRONMENT'], array( 'test', 'live', 'dev' ), true ) ) {
|
9337 |
+
$eio_debug .= "detected pantheon env: {$_ENV['PANTHEON_ENVIRONMENT']}<br>";
|
9338 |
}
|
9339 |
if ( defined( 'EWWW_IO_CLOUD_PLUGIN' ) && EWWW_IO_CLOUD_PLUGIN ) {
|
9340 |
+
$eio_debug .= 'cloud plugin<br>';
|
9341 |
} else {
|
9342 |
+
$eio_debug .= 'core plugin<br>';
|
9343 |
}
|
9344 |
}
|
9345 |
|
9504 |
*/
|
9505 |
function ewww_image_optimizer_temp_debug_clear() {
|
9506 |
global $ewwwio_temp_debug;
|
9507 |
+
global $eio_debug;
|
9508 |
if ( $ewwwio_temp_debug ) {
|
9509 |
+
$eio_debug = '';
|
9510 |
}
|
9511 |
$ewwwio_temp_debug = false;
|
9512 |
}
|
ewww-image-optimizer.php
CHANGED
@@ -13,7 +13,7 @@ Plugin Name: EWWW Image Optimizer
|
|
13 |
Plugin URI: https://wordpress.org/plugins/ewww-image-optimizer/
|
14 |
Description: Reduce file sizes for images within WordPress including NextGEN Gallery and GRAND FlAGallery. Uses jpegtran, optipng/pngout, and gifsicle.
|
15 |
Author: Exactly WWW
|
16 |
-
Version: 4.
|
17 |
Author URI: https://ewww.io/
|
18 |
License: GPLv3
|
19 |
*/
|
@@ -108,9 +108,13 @@ if ( ! defined( 'PHP_VERSION_ID' ) || PHP_VERSION_ID < 50600 ) {
|
|
108 |
*/
|
109 |
require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'unique.php' );
|
110 |
/**
|
111 |
-
* All the 'common' functions for both EWWW I.O.
|
112 |
*/
|
113 |
require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'common.php' );
|
|
|
|
|
|
|
|
|
114 |
/**
|
115 |
* The various class extensions for parallel and background optimization.
|
116 |
*/
|
@@ -126,7 +130,7 @@ if ( ! defined( 'PHP_VERSION_ID' ) || PHP_VERSION_ID < 50600 ) {
|
|
126 |
/**
|
127 |
* EWWWIO_HS_Beacon class for embedding the HelpScout Beacon.
|
128 |
*/
|
129 |
-
require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-
|
130 |
} // End if().
|
131 |
|
132 |
if ( ! function_exists( 'ewww_image_optimizer_unsupported_php' ) ) {
|
13 |
Plugin URI: https://wordpress.org/plugins/ewww-image-optimizer/
|
14 |
Description: Reduce file sizes for images within WordPress including NextGEN Gallery and GRAND FlAGallery. Uses jpegtran, optipng/pngout, and gifsicle.
|
15 |
Author: Exactly WWW
|
16 |
+
Version: 4.9.3
|
17 |
Author URI: https://ewww.io/
|
18 |
License: GPLv3
|
19 |
*/
|
108 |
*/
|
109 |
require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'unique.php' );
|
110 |
/**
|
111 |
+
* All the 'common' functions for both EWWW I.O. plugins.
|
112 |
*/
|
113 |
require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'common.php' );
|
114 |
+
/**
|
115 |
+
* All the base functions for our plugins.
|
116 |
+
*/
|
117 |
+
require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-eio-base.php' );
|
118 |
/**
|
119 |
* The various class extensions for parallel and background optimization.
|
120 |
*/
|
130 |
/**
|
131 |
* EWWWIO_HS_Beacon class for embedding the HelpScout Beacon.
|
132 |
*/
|
133 |
+
require_once( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'classes/class-eio-hs-beacon.php' );
|
134 |
} // End if().
|
135 |
|
136 |
if ( ! function_exists( 'ewww_image_optimizer_unsupported_php' ) ) {
|
includes/eio.js
CHANGED
@@ -80,7 +80,7 @@ jQuery(document).ready(function($) {
|
|
80 |
$.post(ajaxurl, ewww_webp_rewrite_data, function(response) {
|
81 |
$('#ewww-webp-rewrite-status').html('<b>' + response + '</b>');
|
82 |
ewww_webp_image = document.getElementById("webp-image").src;
|
83 |
-
document.getElementById("webp-image").src = ewww_webp_image + '
|
84 |
});
|
85 |
return false;
|
86 |
});
|
@@ -93,7 +93,7 @@ jQuery(document).ready(function($) {
|
|
93 |
$.post(ajaxurl, ewww_webp_rewrite_data, function(response) {
|
94 |
$('#ewww-webp-rewrite-status').html('<b>' + response + '</b>');
|
95 |
ewww_webp_image = document.getElementById("webp-image").src;
|
96 |
-
document.getElementById("webp-image").src = ewww_webp_image + '
|
97 |
});
|
98 |
return false;
|
99 |
});
|
80 |
$.post(ajaxurl, ewww_webp_rewrite_data, function(response) {
|
81 |
$('#ewww-webp-rewrite-status').html('<b>' + response + '</b>');
|
82 |
ewww_webp_image = document.getElementById("webp-image").src;
|
83 |
+
document.getElementById("webp-image").src = ewww_webp_image + '?m=' + new Date().getTime();
|
84 |
});
|
85 |
return false;
|
86 |
});
|
93 |
$.post(ajaxurl, ewww_webp_rewrite_data, function(response) {
|
94 |
$('#ewww-webp-rewrite-status').html('<b>' + response + '</b>');
|
95 |
ewww_webp_image = document.getElementById("webp-image").src;
|
96 |
+
document.getElementById("webp-image").src = ewww_webp_image + '?m' + new Date().getTime();
|
97 |
});
|
98 |
return false;
|
99 |
});
|
includes/lazysizes-post.js
CHANGED
@@ -7,7 +7,10 @@ function constrainSrc(url,objectWidth,objectHeight,objectType){
|
|
7 |
var regFit = /fit=(\d+),(\d+)/;
|
8 |
var regResize = /resize=(\d+),(\d+)/;
|
9 |
var decUrl = decodeURIComponent(url);
|
10 |
-
if (
|
|
|
|
|
|
|
11 |
var resultResize = regResize.exec(decUrl);
|
12 |
if(resultResize && objectWidth < resultResize[1]){
|
13 |
return decUrl.replace(regResize, 'resize=' + objectWidth + ',' + objectHeight);
|
@@ -39,7 +42,7 @@ function constrainSrc(url,objectWidth,objectHeight,objectType){
|
|
39 |
return url + '&w=' + objectWidth;
|
40 |
}
|
41 |
}
|
42 |
-
if (url.search('\\?') == -1 && url.search(
|
43 |
if('img'===objectType){
|
44 |
return url + '?fit=' + objectWidth + ',' + objectHeight;
|
45 |
}
|
7 |
var regFit = /fit=(\d+),(\d+)/;
|
8 |
var regResize = /resize=(\d+),(\d+)/;
|
9 |
var decUrl = decodeURIComponent(url);
|
10 |
+
if (typeof eio_lazy_vars === 'undefined'){
|
11 |
+
var eio_lazy_vars = {"exactdn_domain":".exactdn.com"};
|
12 |
+
}
|
13 |
+
if (url.search('\\?') > 0 && url.search(eio_lazy_vars.exactdn_domain) > 0){
|
14 |
var resultResize = regResize.exec(decUrl);
|
15 |
if(resultResize && objectWidth < resultResize[1]){
|
16 |
return decUrl.replace(regResize, 'resize=' + objectWidth + ',' + objectHeight);
|
42 |
return url + '&w=' + objectWidth;
|
43 |
}
|
44 |
}
|
45 |
+
if (url.search('\\?') == -1 && url.search(eio_lazy_vars.exactdn_domain) > 0){
|
46 |
if('img'===objectType){
|
47 |
return url + '?fit=' + objectWidth + ',' + objectHeight;
|
48 |
}
|
includes/lazysizes.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
var ewww_webp_supported=!1;function lazysizesWebP(e,t){var a=new Image;a.onload=function(){ewww_webp_supported=0<a.width&&0<a.height,t()},a.onerror=function(){t()},a.src="data:image/webp;base64,"+{alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"}[e]}function constrainSrc(e,t,a,i){if(null===e)return e;var r=/w=(\d+)/,n=/fit=(\d+),(\d+)/,o=/resize=(\d+),(\d+)/,s=decodeURIComponent(e);if(0<e.search("\\?")&&0<e.search(ewww_lazy_vars.exactdn_domain)){var l=o.exec(s);if(l&&t<l[1])return s.replace(o,"resize="+t+","+a);var d=r.exec(e);if(d&&t<=d[1])return"bg-cover"===i?e.replace(r,"resize="+t+","+a):e.replace(r,"w="+t);var c=n.exec(s);if(c&&t<c[1])return"bg-cover"===i?e.replace(r,"resize="+t+","+a):s.replace(n,"fit="+t+","+a);if(!d&&!c&&!l)return"img"===i?e+"&fit="+t+","+a:"bg-cover"===i?e+"?resize="+t+","+a:t<a?e+"&h="+a:e+"&w="+t}return-1==e.search("\\?")&&0<e.search(ewww_lazy_vars.exactdn_domain)?"img"===i?e+"?fit="+t+","+a:"bg-cover"===i?e+"?resize="+t+","+a:t<a?e+"?h="+a:e+"?w="+t:e}window.lazySizesConfig=window.lazySizesConfig||{},window.lazySizesConfig.init=!1,function(e,t){var a=function(i,A){"use strict";if(!A.getElementsByClassName)return;var g,z,v=A.documentElement,n=i.Date,r=i.HTMLPictureElement,o="addEventListener",h="getAttribute",t=i[o],u=i.setTimeout,a=i.requestAnimationFrame||u,s=i.requestIdleCallback,f=/^picture$/i,l=["load","error","lazyincluded","_lazyloaded"],d={},p=Array.prototype.forEach,c=function(e,t){return d[t]||(d[t]=new RegExp("(\\s|^)"+t+"(\\s|$)")),d[t].test(e[h]("class")||"")&&d[t]},m=function(e,t){c(e,t)||e.setAttribute("class",(e[h]("class")||"").trim()+" "+t)},y=function(e,t){var a;(a=c(e,t))&&e.setAttribute("class",(e[h]("class")||"").replace(a," "))},b=function(t,a,e){var i=e?o:"removeEventListener";e&&b(t,a),l.forEach(function(e){t[i](e,a)})},w=function(e,t,a,i,r){var n=A.createEvent("Event");return a||(a={}),a.instance=g,n.initEvent(t,!i,!r),n.detail=a,e.dispatchEvent(n),n},C=function(e,t){var a;!r&&(a=i.picturefill||z.pf)?(t&&t.src&&!e[h]("srcset")&&e.setAttribute("srcset",t.src),a({reevaluate:!0,elements:[e]})):t&&t.src&&(e.src=t.src)},_=function(e,t){return(getComputedStyle(e,null)||{})[t]},E=function(e,t,a){for(a=a||e.offsetWidth;a<z.minSize&&t&&!e._lazysizesWidth;)a=t.offsetWidth,t=t.parentNode;return a},W=(B=[],R=[],L=B,N=function(){var e=L;for(L=B.length?R:B,M=!(S=!0);e.length;)e.shift()();S=!1},Q=function(e,t){S&&!t?e.apply(this,arguments):(L.push(e),M||(M=!0,(A.hidden?u:a)(N)))},Q._lsFlush=N,Q),e=function(a,e){return e?function(){W(a)}:function(){var e=this,t=arguments;W(function(){a.apply(e,t)})}},x=function(e){var t,a,i=function(){t=null,e()},r=function(){var e=n.now()-a;e<99?u(r,99-e):(s||i)(i)};return function(){a=n.now(),t||(t=u(r,99))}};var S,M,B,R,L,N,Q;!function(){var e,t={lazyClass:"lazyload",loadedClass:"lazyloaded",loadingClass:"lazyloading",preloadClass:"lazypreload",errorClass:"lazyerror",autosizesClass:"lazyautosizes",srcAttr:"data-src",srcsetAttr:"data-srcset",sizesAttr:"data-sizes",minSize:40,customMedia:{},init:!0,expFactor:1.5,hFac:.8,loadMode:2,loadHidden:!0,ricTimeout:0,throttleDelay:125};for(e in z=i.lazySizesConfig||i.lazysizesConfig||{},t)e in z||(z[e]=t[e]);i.lazySizesConfig=z,u(function(){z.init&&D()})}();var P=(se=/^img$/i,le=/^iframe$/i,de="onscroll"in i&&!/(gle|ing)bot/.test(navigator.userAgent),ce=0,ue=0,fe=-1,Ae=function(e){ue--,(!e||ue<0||!e.target)&&(ue=0)},ge=function(e){return null==Z&&(Z="hidden"==_(A.body,"visibility")),Z||"hidden"!=_(e.parentNode,"visibility")&&"hidden"!=_(e,"visibility")},ze=function(e,t){var a,i=e,r=ge(e);for(V-=t,K+=t,X-=t,Y+=t;r&&(i=i.offsetParent)&&i!=A.body&&i!=v;)(r=0<(_(i,"opacity")||1))&&"visible"!=_(i,"overflow")&&(a=i.getBoundingClientRect(),r=Y>a.left&&X<a.right&&K>a.top-1&&V<a.bottom+1);return r},ve=function(){var e,t,a,i,r,n,o,s,l,d,c,u,f=g.elements;if((G=z.loadMode)&&ue<8&&(e=f.length)){for(t=0,fe++,d=!z.expand||z.expand<1?500<v.clientHeight&&500<v.clientWidth?500:370:z.expand,g._defEx=d,c=d*z.expFactor,u=z.hFac,Z=null,ce<c&&ue<1&&2<fe&&2<G&&!A.hidden?(ce=c,fe=0):ce=1<G&&1<fe&&ue<6?d:0;t<e;t++)if(f[t]&&!f[t]._lazyRace)if(de)if((s=f[t][h]("data-expand"))&&(n=1*s)||(n=ce),l!==n&&(q=innerWidth+n*u,j=innerHeight+n,o=-1*n,l=n),a=f[t].getBoundingClientRect(),(K=a.bottom)>=o&&(V=a.top)<=j&&(Y=a.right)>=o*u&&(X=a.left)<=q&&(K||Y||X||V)&&(z.loadHidden||ge(f[t]))&&(J&&ue<3&&!s&&(G<3||fe<4)||ze(f[t],n))){if(Ce(f[t]),r=!0,9<ue)break}else!r&&J&&!i&&ue<4&&fe<4&&2<G&&(I[0]||z.preloadAfterLoad)&&(I[0]||!s&&(K||Y||X||V||"auto"!=f[t][h](z.sizesAttr)))&&(i=I[0]||f[t]);else Ce(f[t]);i&&!r&&Ce(i)}},ee=ve,ae=0,ie=z.throttleDelay,re=z.ricTimeout,ne=function(){te=!1,ae=n.now(),ee()},oe=s&&49<re?function(){s(ne,{timeout:re}),re!==z.ricTimeout&&(re=z.ricTimeout)}:e(function(){u(ne)},!0),he=function(e){var t;(e=!0===e)&&(re=33),te||(te=!0,(t=ie-(n.now()-ae))<0&&(t=0),e||t<9?oe():u(oe,t))},pe=function(e){var t=e.target;t._lazyCache?delete t._lazyCache:(Ae(e),m(t,z.loadedClass),y(t,z.loadingClass),b(t,ye),w(t,"lazyloaded"))},me=e(pe),ye=function(e){me({target:e.target})},be=function(e){var t,a=e[h](z.srcsetAttr);(t=z.customMedia[e[h]("data-media")||e[h]("media")])&&e.setAttribute("media",t),a&&e.setAttribute("srcset",a)},we=e(function(e,t,a,i,r){var n,o,s,l,d,c;(d=w(e,"lazybeforeunveil",t)).defaultPrevented||(i&&(a?m(e,z.autosizesClass):e.setAttribute("sizes",i)),o=e[h](z.srcsetAttr),n=e[h](z.srcAttr),r&&(s=e.parentNode,l=s&&f.test(s.nodeName||"")),c=t.firesLoad||"src"in e&&(o||n||l),d={target:e},m(e,z.loadingClass),c&&(clearTimeout(O),O=u(Ae,2500),b(e,ye,!0)),l&&p.call(s.getElementsByTagName("source"),be),o?e.setAttribute("srcset",o):n&&!l&&(le.test(e.nodeName)?function(t,a){try{t.contentWindow.location.replace(a)}catch(e){t.src=a}}(e,n):e.src=n),r&&(o||l)&&C(e,{src:n})),e._lazyRace&&delete e._lazyRace,y(e,z.lazyClass),W(function(){(!c||e.complete&&1<e.naturalWidth)&&(pe(d),e._lazyCache=!0,u(function(){"_lazyCache"in e&&delete e._lazyCache},9))},!0)}),Ce=function(e){var t,a=se.test(e.nodeName),i=a&&(e[h](z.sizesAttr)||e[h]("sizes")),r="auto"==i;(!r&&J||!a||!e[h]("src")&&!e.srcset||e.complete||c(e,z.errorClass)||!c(e,z.lazyClass))&&(t=w(e,"lazyunveilread").detail,r&&k.updateElem(e,!0,e.offsetWidth),e._lazyRace=!0,ue++,we(e,t,r,i,a))},_e=function(){if(!J)if(n.now()-$<999)u(_e,999);else{var e=x(function(){z.loadMode=3,he()});J=!0,z.loadMode=3,he(),t("scroll",function(){3==z.loadMode&&(z.loadMode=2),e()},!0)}},{_:function(){$=n.now(),g.elements=A.getElementsByClassName(z.lazyClass),I=A.getElementsByClassName(z.lazyClass+" "+z.preloadClass),t("scroll",he,!0),t("resize",he,!0),i.MutationObserver?new MutationObserver(he).observe(v,{childList:!0,subtree:!0,attributes:!0}):(v[o]("DOMNodeInserted",he,!0),v[o]("DOMAttrModified",he,!0),setInterval(he,999)),t("hashchange",he,!0),["focus","mouseover","click","load","transitionend","animationend","webkitAnimationEnd"].forEach(function(e){A[o](e,he,!0)}),/d$|^c/.test(A.readyState)?_e():(t("load",_e),A[o]("DOMContentLoaded",he),u(_e,2e4)),g.elements.length?(ve(),W._lsFlush()):he()},checkElems:he,unveil:Ce}),k=(H=e(function(e,t,a,i){var r,n,o;if(e._lazysizesWidth=i,i+="px",e.setAttribute("sizes",i),f.test(t.nodeName||""))for(r=t.getElementsByTagName("source"),n=0,o=r.length;n<o;n++)r[n].setAttribute("sizes",i);a.detail.dataAttr||C(e,a.detail)}),U=function(e,t,a){var i,r=e.parentNode;r&&(a=E(e,r,a),(i=w(e,"lazybeforesizes",{width:a,dataAttr:!!t})).defaultPrevented||(a=i.detail.width)&&a!==e._lazysizesWidth&&H(e,r,i,a))},F=x(function(){var e,t=T.length;if(t)for(e=0;e<t;e++)U(T[e])}),{_:function(){T=A.getElementsByClassName(z.autosizesClass),t("resize",F)},checkElems:F,updateElem:U}),D=function(){D.i||(D.i=!0,k._(),P._())};var T,H,U,F;var I,J,O,G,$,q,j,V,X,Y,K,Z,ee,te,ae,ie,re,ne,oe,se,le,de,ce,ue,fe,Ae,ge,ze,ve,he,pe,me,ye,be,we,Ce,_e;return g={cfg:z,autoSizer:k,loader:P,init:D,uP:C,aC:m,rC:y,hC:c,fire:w,gW:E,rAF:W}}(e,e.document);e.lazySizes=a,"object"==typeof module&&module.exports&&(module.exports=a)}(window),lazysizesWebP("alpha",lazySizes.init),document.addEventListener("lazybeforeunveil",function(e){var t=e.target,a=t.getAttribute("data-srcset");if(!a&&t.naturalWidth&&1<t.naturalWidth&&1<t.naturalHeight){var i=window.devicePixelRatio||1,r=1.25*t.clientWidth<t.naturalWidth,n=1.25*t.clientHeight<t.naturalHeight;if(r||n){var o=Math.round(t.offsetWidth*i),s=Math.round(t.offsetHeight*i),l=t.getAttribute("data-src"),d=t.getAttribute("data-src-webp");ewww_webp_supported&&d&&-1==l.search("webp=1")&&(l=d);var c=constrainSrc(l,o,s,"img");c&&l!=c&&t.setAttribute("data-src",c)}}if(ewww_webp_supported){if(a&&-1<a.search("webp=1"))return;if(a){var u=t.getAttribute("data-srcset-webp");u&&t.setAttribute("data-srcset",u)}if((l=t.getAttribute("data-src"))&&-1<l.search("webp=1"))return;if(!(d=t.getAttribute("data-src-webp")))return;t.setAttribute("data-src",d)}}),function(e,t){var a=function(){t(e.lazySizes),e.removeEventListener("lazyunveilread",a,!0)};t=t.bind(null,e,e.document),"object"==typeof module&&module.exports?t(require("lazysizes")):e.lazySizes?a():e.addEventListener("lazyunveilread",a,!0)}(window,function(s,i,l){"use strict";var d,c;i.addEventListener&&(d=function(e,t){var a=i.createElement("img");a.onload=function(){a.onload=null,a.onerror=null,a=null,t()},a.onerror=a.onload,a.src=e,a&&a.complete&&a.onload&&a.onload()},addEventListener("lazybeforeunveil",function(e){var t,a,i;if(e.detail.instance==l&&!e.defaultPrevented){if("none"==e.target.preload&&(e.target.preload="auto"),t=e.target.getAttribute("data-bg")){ewww_webp_supported&&(a=e.target.getAttribute("data-bg-webp"))&&(t=a);var r=s.devicePixelRatio||1,n=Math.round(e.target.offsetWidth*r),o=Math.round(e.target.offsetHeight*r);t=s.lazySizes.hC(e.target,"wp-block-cover")?constrainSrc(t,n,o,"bg-cover"):constrainSrc(t,n,o,"bg"),e.detail.firesLoad=!0,d(t,function(){e.target.style.backgroundImage="url("+(c.test(t)?JSON.stringify(t):t)+")",e.detail.firesLoad=!1,l.fire(e.target,"_lazyloaded",{},!0,!0)})}(i=e.target.getAttribute("data-poster"))&&(e.detail.firesLoad=!0,d(i,function(){e.target.poster=i,e.detail.firesLoad=!1,l.fire(e.target,"_lazyloaded",{},!0,!0)}))}},!(c=/\(|\)|\s|'/)))});
|
1 |
+
var ewww_webp_supported=!1;function lazysizesWebP(e,t){var a=new Image;a.onload=function(){ewww_webp_supported=0<a.width&&0<a.height,t()},a.onerror=function(){t()},a.src="data:image/webp;base64,"+{alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"}[e]}function constrainSrc(e,t,a,i){if(null===e)return e;var r=/w=(\d+)/,n=/fit=(\d+),(\d+)/,o=/resize=(\d+),(\d+)/,s=decodeURIComponent(e);if(void 0===eio_lazy_vars)var eio_lazy_vars={exactdn_domain:".exactdn.com"};if(0<e.search("\\?")&&0<e.search(eio_lazy_vars.exactdn_domain)){var l=o.exec(s);if(l&&t<l[1])return s.replace(o,"resize="+t+","+a);var d=r.exec(e);if(d&&t<=d[1])return"bg-cover"===i?e.replace(r,"resize="+t+","+a):e.replace(r,"w="+t);var c=n.exec(s);if(c&&t<c[1])return"bg-cover"===i?e.replace(r,"resize="+t+","+a):s.replace(n,"fit="+t+","+a);if(!d&&!c&&!l)return"img"===i?e+"&fit="+t+","+a:"bg-cover"===i?e+"?resize="+t+","+a:t<a?e+"&h="+a:e+"&w="+t}return-1==e.search("\\?")&&0<e.search(eio_lazy_vars.exactdn_domain)?"img"===i?e+"?fit="+t+","+a:"bg-cover"===i?e+"?resize="+t+","+a:t<a?e+"?h="+a:e+"?w="+t:e}window.lazySizesConfig=window.lazySizesConfig||{},window.lazySizesConfig.init=!1,function(e,t){var a=function(i,A){"use strict";if(!A.getElementsByClassName)return;var g,z,v=A.documentElement,n=i.Date,r=i.HTMLPictureElement,o="addEventListener",h="getAttribute",t=i[o],u=i.setTimeout,a=i.requestAnimationFrame||u,s=i.requestIdleCallback,f=/^picture$/i,l=["load","error","lazyincluded","_lazyloaded"],d={},m=Array.prototype.forEach,c=function(e,t){return d[t]||(d[t]=new RegExp("(\\s|^)"+t+"(\\s|$)")),d[t].test(e[h]("class")||"")&&d[t]},p=function(e,t){c(e,t)||e.setAttribute("class",(e[h]("class")||"").trim()+" "+t)},y=function(e,t){var a;(a=c(e,t))&&e.setAttribute("class",(e[h]("class")||"").replace(a," "))},b=function(t,a,e){var i=e?o:"removeEventListener";e&&b(t,a),l.forEach(function(e){t[i](e,a)})},w=function(e,t,a,i,r){var n=A.createEvent("Event");return a||(a={}),a.instance=g,n.initEvent(t,!i,!r),n.detail=a,e.dispatchEvent(n),n},C=function(e,t){var a;!r&&(a=i.picturefill||z.pf)?(t&&t.src&&!e[h]("srcset")&&e.setAttribute("srcset",t.src),a({reevaluate:!0,elements:[e]})):t&&t.src&&(e.src=t.src)},_=function(e,t){return(getComputedStyle(e,null)||{})[t]},E=function(e,t,a){for(a=a||e.offsetWidth;a<z.minSize&&t&&!e._lazysizesWidth;)a=t.offsetWidth,t=t.parentNode;return a},x=(B=[],R=[],L=B,N=function(){var e=L;for(L=B.length?R:B,M=!(W=!0);e.length;)e.shift()();W=!1},Q=function(e,t){W&&!t?e.apply(this,arguments):(L.push(e),M||(M=!0,(A.hidden?u:a)(N)))},Q._lsFlush=N,Q),e=function(a,e){return e?function(){x(a)}:function(){var e=this,t=arguments;x(function(){a.apply(e,t)})}},S=function(e){var t,a,i=function(){t=null,e()},r=function(){var e=n.now()-a;e<99?u(r,99-e):(s||i)(i)};return function(){a=n.now(),t||(t=u(r,99))}};var W,M,B,R,L,N,Q;!function(){var e,t={lazyClass:"lazyload",loadedClass:"lazyloaded",loadingClass:"lazyloading",preloadClass:"lazypreload",errorClass:"lazyerror",autosizesClass:"lazyautosizes",srcAttr:"data-src",srcsetAttr:"data-srcset",sizesAttr:"data-sizes",minSize:40,customMedia:{},init:!0,expFactor:1.5,hFac:.8,loadMode:2,loadHidden:!0,ricTimeout:0,throttleDelay:125};for(e in z=i.lazySizesConfig||i.lazysizesConfig||{},t)e in z||(z[e]=t[e]);i.lazySizesConfig=z,u(function(){z.init&&D()})}();var P=(se=/^img$/i,le=/^iframe$/i,de="onscroll"in i&&!/(gle|ing)bot/.test(navigator.userAgent),ce=0,ue=0,fe=-1,Ae=function(e){ue--,(!e||ue<0||!e.target)&&(ue=0)},ge=function(e){return null==Z&&(Z="hidden"==_(A.body,"visibility")),Z||"hidden"!=_(e.parentNode,"visibility")&&"hidden"!=_(e,"visibility")},ze=function(e,t){var a,i=e,r=ge(e);for(V-=t,K+=t,X-=t,Y+=t;r&&(i=i.offsetParent)&&i!=A.body&&i!=v;)(r=0<(_(i,"opacity")||1))&&"visible"!=_(i,"overflow")&&(a=i.getBoundingClientRect(),r=Y>a.left&&X<a.right&&K>a.top-1&&V<a.bottom+1);return r},ve=function(){var e,t,a,i,r,n,o,s,l,d,c,u,f=g.elements;if((G=z.loadMode)&&ue<8&&(e=f.length)){for(t=0,fe++,d=!z.expand||z.expand<1?500<v.clientHeight&&500<v.clientWidth?500:370:z.expand,g._defEx=d,c=d*z.expFactor,u=z.hFac,Z=null,ce<c&&ue<1&&2<fe&&2<G&&!A.hidden?(ce=c,fe=0):ce=1<G&&1<fe&&ue<6?d:0;t<e;t++)if(f[t]&&!f[t]._lazyRace)if(de)if((s=f[t][h]("data-expand"))&&(n=1*s)||(n=ce),l!==n&&(q=innerWidth+n*u,j=innerHeight+n,o=-1*n,l=n),a=f[t].getBoundingClientRect(),(K=a.bottom)>=o&&(V=a.top)<=j&&(Y=a.right)>=o*u&&(X=a.left)<=q&&(K||Y||X||V)&&(z.loadHidden||ge(f[t]))&&(J&&ue<3&&!s&&(G<3||fe<4)||ze(f[t],n))){if(Ce(f[t]),r=!0,9<ue)break}else!r&&J&&!i&&ue<4&&fe<4&&2<G&&(I[0]||z.preloadAfterLoad)&&(I[0]||!s&&(K||Y||X||V||"auto"!=f[t][h](z.sizesAttr)))&&(i=I[0]||f[t]);else Ce(f[t]);i&&!r&&Ce(i)}},ee=ve,ae=0,ie=z.throttleDelay,re=z.ricTimeout,ne=function(){te=!1,ae=n.now(),ee()},oe=s&&49<re?function(){s(ne,{timeout:re}),re!==z.ricTimeout&&(re=z.ricTimeout)}:e(function(){u(ne)},!0),he=function(e){var t;(e=!0===e)&&(re=33),te||(te=!0,(t=ie-(n.now()-ae))<0&&(t=0),e||t<9?oe():u(oe,t))},me=function(e){var t=e.target;t._lazyCache?delete t._lazyCache:(Ae(e),p(t,z.loadedClass),y(t,z.loadingClass),b(t,ye),w(t,"lazyloaded"))},pe=e(me),ye=function(e){pe({target:e.target})},be=function(e){var t,a=e[h](z.srcsetAttr);(t=z.customMedia[e[h]("data-media")||e[h]("media")])&&e.setAttribute("media",t),a&&e.setAttribute("srcset",a)},we=e(function(e,t,a,i,r){var n,o,s,l,d,c;(d=w(e,"lazybeforeunveil",t)).defaultPrevented||(i&&(a?p(e,z.autosizesClass):e.setAttribute("sizes",i)),o=e[h](z.srcsetAttr),n=e[h](z.srcAttr),r&&(s=e.parentNode,l=s&&f.test(s.nodeName||"")),c=t.firesLoad||"src"in e&&(o||n||l),d={target:e},p(e,z.loadingClass),c&&(clearTimeout(O),O=u(Ae,2500),b(e,ye,!0)),l&&m.call(s.getElementsByTagName("source"),be),o?e.setAttribute("srcset",o):n&&!l&&(le.test(e.nodeName)?function(t,a){try{t.contentWindow.location.replace(a)}catch(e){t.src=a}}(e,n):e.src=n),r&&(o||l)&&C(e,{src:n})),e._lazyRace&&delete e._lazyRace,y(e,z.lazyClass),x(function(){(!c||e.complete&&1<e.naturalWidth)&&(me(d),e._lazyCache=!0,u(function(){"_lazyCache"in e&&delete e._lazyCache},9))},!0)}),Ce=function(e){var t,a=se.test(e.nodeName),i=a&&(e[h](z.sizesAttr)||e[h]("sizes")),r="auto"==i;(!r&&J||!a||!e[h]("src")&&!e.srcset||e.complete||c(e,z.errorClass)||!c(e,z.lazyClass))&&(t=w(e,"lazyunveilread").detail,r&&k.updateElem(e,!0,e.offsetWidth),e._lazyRace=!0,ue++,we(e,t,r,i,a))},_e=function(){if(!J)if(n.now()-$<999)u(_e,999);else{var e=S(function(){z.loadMode=3,he()});J=!0,z.loadMode=3,he(),t("scroll",function(){3==z.loadMode&&(z.loadMode=2),e()},!0)}},{_:function(){$=n.now(),g.elements=A.getElementsByClassName(z.lazyClass),I=A.getElementsByClassName(z.lazyClass+" "+z.preloadClass),t("scroll",he,!0),t("resize",he,!0),i.MutationObserver?new MutationObserver(he).observe(v,{childList:!0,subtree:!0,attributes:!0}):(v[o]("DOMNodeInserted",he,!0),v[o]("DOMAttrModified",he,!0),setInterval(he,999)),t("hashchange",he,!0),["focus","mouseover","click","load","transitionend","animationend","webkitAnimationEnd"].forEach(function(e){A[o](e,he,!0)}),/d$|^c/.test(A.readyState)?_e():(t("load",_e),A[o]("DOMContentLoaded",he),u(_e,2e4)),g.elements.length?(ve(),x._lsFlush()):he()},checkElems:he,unveil:Ce}),k=(H=e(function(e,t,a,i){var r,n,o;if(e._lazysizesWidth=i,i+="px",e.setAttribute("sizes",i),f.test(t.nodeName||""))for(r=t.getElementsByTagName("source"),n=0,o=r.length;n<o;n++)r[n].setAttribute("sizes",i);a.detail.dataAttr||C(e,a.detail)}),U=function(e,t,a){var i,r=e.parentNode;r&&(a=E(e,r,a),(i=w(e,"lazybeforesizes",{width:a,dataAttr:!!t})).defaultPrevented||(a=i.detail.width)&&a!==e._lazysizesWidth&&H(e,r,i,a))},F=S(function(){var e,t=T.length;if(t)for(e=0;e<t;e++)U(T[e])}),{_:function(){T=A.getElementsByClassName(z.autosizesClass),t("resize",F)},checkElems:F,updateElem:U}),D=function(){D.i||(D.i=!0,k._(),P._())};var T,H,U,F;var I,J,O,G,$,q,j,V,X,Y,K,Z,ee,te,ae,ie,re,ne,oe,se,le,de,ce,ue,fe,Ae,ge,ze,ve,he,me,pe,ye,be,we,Ce,_e;return g={cfg:z,autoSizer:k,loader:P,init:D,uP:C,aC:p,rC:y,hC:c,fire:w,gW:E,rAF:x}}(e,e.document);e.lazySizes=a,"object"==typeof module&&module.exports&&(module.exports=a)}(window),lazysizesWebP("alpha",lazySizes.init),document.addEventListener("lazybeforeunveil",function(e){var t=e.target,a=t.getAttribute("data-srcset");if(!a&&t.naturalWidth&&1<t.naturalWidth&&1<t.naturalHeight){var i=window.devicePixelRatio||1,r=1.25*t.clientWidth<t.naturalWidth,n=1.25*t.clientHeight<t.naturalHeight;if(r||n){var o=Math.round(t.offsetWidth*i),s=Math.round(t.offsetHeight*i),l=t.getAttribute("data-src"),d=t.getAttribute("data-src-webp");ewww_webp_supported&&d&&-1==l.search("webp=1")&&(l=d);var c=constrainSrc(l,o,s,"img");c&&l!=c&&t.setAttribute("data-src",c)}}if(ewww_webp_supported){if(a&&-1<a.search("webp=1"))return;if(a){var u=t.getAttribute("data-srcset-webp");u&&t.setAttribute("data-srcset",u)}if((l=t.getAttribute("data-src"))&&-1<l.search("webp=1"))return;if(!(d=t.getAttribute("data-src-webp")))return;t.setAttribute("data-src",d)}}),function(e,t){var a=function(){t(e.lazySizes),e.removeEventListener("lazyunveilread",a,!0)};t=t.bind(null,e,e.document),"object"==typeof module&&module.exports?t(require("lazysizes")):e.lazySizes?a():e.addEventListener("lazyunveilread",a,!0)}(window,function(s,i,l){"use strict";var d,c;i.addEventListener&&(d=function(e,t){var a=i.createElement("img");a.onload=function(){a.onload=null,a.onerror=null,a=null,t()},a.onerror=a.onload,a.src=e,a&&a.complete&&a.onload&&a.onload()},addEventListener("lazybeforeunveil",function(e){var t,a,i;if(e.detail.instance==l&&!e.defaultPrevented){if("none"==e.target.preload&&(e.target.preload="auto"),t=e.target.getAttribute("data-bg")){ewww_webp_supported&&(a=e.target.getAttribute("data-bg-webp"))&&(t=a);var r=s.devicePixelRatio||1,n=Math.round(e.target.offsetWidth*r),o=Math.round(e.target.offsetHeight*r);t=s.lazySizes.hC(e.target,"wp-block-cover")?constrainSrc(t,n,o,"bg-cover"):s.lazySizes.hC(e.target,"elementor-bg")?constrainSrc(t,n,o,"bg-cover"):constrainSrc(t,n,o,"bg"),e.detail.firesLoad=!0,d(t,function(){e.target.style.backgroundImage="url("+(c.test(t)?JSON.stringify(t):t)+")",e.detail.firesLoad=!1,l.fire(e.target,"_lazyloaded",{},!0,!0)})}(i=e.target.getAttribute("data-poster"))&&(e.detail.firesLoad=!0,d(i,function(){e.target.poster=i,e.detail.firesLoad=!1,l.fire(e.target,"_lazyloaded",{},!0,!0)}))}},!(c=/\(|\)|\s|'/)))});
|
includes/load_webp.js
CHANGED
@@ -527,7 +527,9 @@ function ewwwLoadImages(ewww_webp_supported) {
|
|
527 |
}
|
528 |
var lazies = document.querySelectorAll('img.ewww_webp_lazy_load');
|
529 |
for (var i = 0, len = lazies.length; i < len; i++){
|
|
|
530 |
if (ewww_webp_supported) {
|
|
|
531 |
ewwwAttr(lazies[i], 'data-lazy-srcset', lazies[i].getAttribute('data-lazy-srcset-webp'));
|
532 |
ewwwAttr(lazies[i], 'data-srcset', lazies[i].getAttribute('data-srcset-webp'));
|
533 |
ewwwAttr(lazies[i], 'data-lazy-src', lazies[i].getAttribute('data-lazy-src-webp'));
|
@@ -589,6 +591,9 @@ function ewwwWebPInit(ewww_webp_supported) {
|
|
589 |
document.arrive('.ewww_webp', function() {
|
590 |
ewwwLoadImages(ewww_webp_supported);
|
591 |
});
|
|
|
|
|
|
|
592 |
var ewww_ngg_galleries_timer = 0;
|
593 |
var ewww_ngg_galleries = setInterval(function() {
|
594 |
if ( typeof galleries !== 'undefined' ) {
|
527 |
}
|
528 |
var lazies = document.querySelectorAll('img.ewww_webp_lazy_load');
|
529 |
for (var i = 0, len = lazies.length; i < len; i++){
|
530 |
+
console.log('parsing an image: ' + lazies[i].getAttribute('src'));
|
531 |
if (ewww_webp_supported) {
|
532 |
+
console.log('webp good');
|
533 |
ewwwAttr(lazies[i], 'data-lazy-srcset', lazies[i].getAttribute('data-lazy-srcset-webp'));
|
534 |
ewwwAttr(lazies[i], 'data-srcset', lazies[i].getAttribute('data-srcset-webp'));
|
535 |
ewwwAttr(lazies[i], 'data-lazy-src', lazies[i].getAttribute('data-lazy-src-webp'));
|
591 |
document.arrive('.ewww_webp', function() {
|
592 |
ewwwLoadImages(ewww_webp_supported);
|
593 |
});
|
594 |
+
document.arrive('.ewww_webp_lazy_load', function() {
|
595 |
+
ewwwLoadImages(ewww_webp_supported);
|
596 |
+
});
|
597 |
var ewww_ngg_galleries_timer = 0;
|
598 |
var ewww_ngg_galleries = setInterval(function() {
|
599 |
if ( typeof galleries !== 'undefined' ) {
|
includes/load_webp.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
var Arrive=function(c,e,d){"use strict";if(c.MutationObserver&&"undefined"!=typeof HTMLElement){var r,t,a=0,u=(r=HTMLElement.prototype.matches||HTMLElement.prototype.webkitMatchesSelector||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelector,{matchesSelector:function(e,t){return e instanceof HTMLElement&&r.call(e,t)},addMethod:function(e,t,r){var a=e[t];e[t]=function(){return r.length==arguments.length?r.apply(this,arguments):"function"==typeof a?a.apply(this,arguments):void 0}},callCallbacks:function(e,t){t&&t.options.onceOnly&&1==t.firedElems.length&&(e=[e[0]]);for(var r,a=0;r=e[a];a++)r&&r.callback&&r.callback.call(r.elem,r.elem);t&&t.options.onceOnly&&1==t.firedElems.length&&t.me.unbindEventWithSelectorAndCallback.call(t.target,t.selector,t.callback)},checkChildNodesRecursively:function(e,t,r,a){for(var i,n=0;i=e[n];n++)r(i,t,a)&&a.push({callback:t.callback,elem:i}),0<i.childNodes.length&&u.checkChildNodesRecursively(i.childNodes,t,r,a)},mergeArrays:function(e,t){var r,a={};for(r in e)e.hasOwnProperty(r)&&(a[r]=e[r]);for(r in t)t.hasOwnProperty(r)&&(a[r]=t[r]);return a},toElementsArray:function(e){return void 0===e||"number"==typeof e.length&&e!==c||(e=[e]),e}}),w=((t=function(){this._eventsBucket=[],this._beforeAdding=null,this._beforeRemoving=null}).prototype.addEvent=function(e,t,r,a){var i={target:e,selector:t,options:r,callback:a,firedElems:[]};return this._beforeAdding&&this._beforeAdding(i),this._eventsBucket.push(i),i},t.prototype.removeEvent=function(e){for(var t,r=this._eventsBucket.length-1;t=this._eventsBucket[r];r--)if(e(t)){this._beforeRemoving&&this._beforeRemoving(t);var a=this._eventsBucket.splice(r,1);a&&a.length&&(a[0].callback=null)}},t.prototype.beforeAdding=function(e){this._beforeAdding=e},t.prototype.beforeRemoving=function(e){this._beforeRemoving=e},t),l=function(i,n){var l=new w,o=this,s={fireOnAttributesModification:!1};return l.beforeAdding(function(t){var e,r=t.target;r!==c.document&&r!==c||(r=document.getElementsByTagName("html")[0]),e=new MutationObserver(function(e){n.call(this,e,t)});var a=i(t.options);e.observe(r,a),t.observer=e,t.me=o}),l.beforeRemoving(function(e){e.observer.disconnect()}),this.bindEvent=function(e,t,r){t=u.mergeArrays(s,t);for(var a=u.toElementsArray(this),i=0;i<a.length;i++)l.addEvent(a[i],e,t,r)},this.unbindEvent=function(){var r=u.toElementsArray(this);l.removeEvent(function(e){for(var t=0;t<r.length;t++)if(this===d||e.target===r[t])return!0;return!1})},this.unbindEventWithSelectorOrCallback=function(r){var e,a=u.toElementsArray(this),i=r;e="function"==typeof r?function(e){for(var t=0;t<a.length;t++)if((this===d||e.target===a[t])&&e.callback===i)return!0;return!1}:function(e){for(var t=0;t<a.length;t++)if((this===d||e.target===a[t])&&e.selector===r)return!0;return!1},l.removeEvent(e)},this.unbindEventWithSelectorAndCallback=function(r,a){var i=u.toElementsArray(this);l.removeEvent(function(e){for(var t=0;t<i.length;t++)if((this===d||e.target===i[t])&&e.selector===r&&e.callback===a)return!0;return!1})},this},i=new function(){var s={fireOnAttributesModification:!1,onceOnly:!1,existing:!1};function n(e,t,r){return!(!u.matchesSelector(e,t.selector)||(e._id===d&&(e._id=a++),-1!=t.firedElems.indexOf(e._id))||(t.firedElems.push(e._id),0))}var c=(i=new l(function(e){var t={attributes:!1,childList:!0,subtree:!0};return e.fireOnAttributesModification&&(t.attributes=!0),t},function(e,i){e.forEach(function(e){var t=e.addedNodes,r=e.target,a=[];null!==t&&0<t.length?u.checkChildNodesRecursively(t,i,n,a):"attributes"===e.type&&n(r,i)&&a.push({callback:i.callback,elem:r}),u.callCallbacks(a,i)})})).bindEvent;return i.bindEvent=function(e,t,r){t=void 0===r?(r=t,s):u.mergeArrays(s,t);var a=u.toElementsArray(this);if(t.existing){for(var i=[],n=0;n<a.length;n++)for(var l=a[n].querySelectorAll(e),o=0;o<l.length;o++)i.push({callback:r,elem:l[o]});if(t.onceOnly&&i.length)return r.call(i[0].elem,i[0].elem);setTimeout(u.callCallbacks,1,i)}c.call(this,e,t,r)},i},o=new function(){var a={};function i(e,t){return u.matchesSelector(e,t.selector)}var n=(o=new l(function(){return{childList:!0,subtree:!0}},function(e,a){e.forEach(function(e){var t=e.removedNodes,r=[];null!==t&&0<t.length&&u.checkChildNodesRecursively(t,a,i,r),u.callCallbacks(r,a)})})).bindEvent;return o.bindEvent=function(e,t,r){t=void 0===r?(r=t,a):u.mergeArrays(a,t),n.call(this,e,t,r)},o};e&&g(e.fn),g(HTMLElement.prototype),g(NodeList.prototype),g(HTMLCollection.prototype),g(HTMLDocument.prototype),g(Window.prototype);var n={};return s(i,n,"unbindAllArrive"),s(o,n,"unbindAllLeave"),n}function s(e,t,r){u.addMethod(t,r,e.unbindEvent),u.addMethod(t,r,e.unbindEventWithSelectorOrCallback),u.addMethod(t,r,e.unbindEventWithSelectorAndCallback)}function g(e){e.arrive=i.bindEvent,s(i,e,"unbindArrive"),e.leave=o.bindEvent,s(o,e,"unbindLeave")}}(window,"undefined"==typeof jQuery?null:jQuery,void 0);function check_webp_feature(e,t){var r=new Image;r.onload=function(){var e=0<r.width&&0<r.height;t(e)},r.onerror=function(){t(!1)},r.src="data:image/webp;base64,"+{alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"}[e]}function ewwwLoadImages(e){var n="data-";function t(e,t){for(var r=["align","alt","border","crossorigin","height","hspace","ismap","longdesc","usemap","vspace","width","accesskey","class","contenteditable","contextmenu","dir","draggable","dropzone","hidden","id","lang","spellcheck","style","tabindex","title","translate","sizes","data-caption","data-attachment-id","data-permalink","data-orig-size","data-comments-opened","data-image-meta","data-image-title","data-image-description","data-event-trigger","data-highlight-color","data-highlight-opacity","data-highlight-border-color","data-highlight-border-width","data-highlight-border-opacity","data-no-lazy","data-lazy","data-large_image_width","data-large_image_height"],a=0,i=r.length;a<i;a++)ewwwAttr(t,r[a],e.getAttribute(n+r[a]));return t}if(e){for(var r=document.querySelectorAll(".batch-image img, .image-wrapper a, .ngg-pro-masonry-item a, .ngg-galleria-offscreen-seo-wrapper a"),a=0,i=r.length;a<i;a++)ewwwAttr(r[a],"data-src",r[a].getAttribute("data-webp")),ewwwAttr(r[a],"data-thumbnail",r[a].getAttribute("data-webp-thumbnail"));for(a=0,i=(o=document.querySelectorAll(".rev_slider ul li")).length;a<i;a++){ewwwAttr(o[a],"data-thumb",o[a].getAttribute("data-webp-thumb"));for(var l=1;l<11;)ewwwAttr(o[a],"data-param"+l,o[a].getAttribute("data-webp-param"+l)),l++}var o;for(a=0,i=(o=document.querySelectorAll(".rev_slider img")).length;a<i;a++)ewwwAttr(o[a],"data-lazyload",o[a].getAttribute("data-webp-lazyload"));var s=document.querySelectorAll("div.woocommerce-product-gallery__image");for(a=0,i=s.length;a<i;a++)ewwwAttr(s[a],"data-thumb",s[a].getAttribute("data-webp-thumb"))}var c=document.querySelectorAll("videos");for(a=0,i=c.length;a<i;a++)ewwwAttr(c[a],"poster",e?c[a].getAttribute("data-poster-webp"):c[a].getAttribute("data-poster-image"));var d=document.querySelectorAll("img.ewww_webp_lazy_load");for(a=0,i=d.length;a<i;a++){if(e){ewwwAttr(d[a],"data-lazy-srcset",d[a].getAttribute("data-lazy-srcset-webp")),ewwwAttr(d[a],"data-srcset",d[a].getAttribute("data-srcset-webp")),ewwwAttr(d[a],"data-lazy-src",d[a].getAttribute("data-lazy-src-webp")),ewwwAttr(d[a],"data-src",d[a].getAttribute("data-src-webp")),ewwwAttr(d[a],"data-orig-file",d[a].getAttribute("data-webp-orig-file")),ewwwAttr(d[a],"data-medium-file",d[a].getAttribute("data-webp-medium-file")),ewwwAttr(d[a],"data-large-file",d[a].getAttribute("data-webp-large-file"));var u=d[a].getAttribute("srcset");null!=u&&!1!==u&&u.includes("R0lGOD")&&ewwwAttr(d[a],"src",d[a].getAttribute("data-lazy-src-webp"))}d[a].className=d[a].className.replace(/\bewww_webp_lazy_load\b/,"")}var w=document.querySelectorAll(".ewww_webp");for(a=0,i=w.length;a<i;a++){var g=document.createElement("img");e?(ewwwAttr(g,"src",w[a].getAttribute("data-webp")),ewwwAttr(g,"srcset",w[a].getAttribute("data-srcset-webp")),ewwwAttr(g,"data-orig-file",w[a].getAttribute("data-orig-file")),ewwwAttr(g,"data-orig-file",w[a].getAttribute("data-webp-orig-file")),ewwwAttr(g,"data-medium-file",w[a].getAttribute("data-medium-file")),ewwwAttr(g,"data-medium-file",w[a].getAttribute("data-webp-medium-file")),ewwwAttr(g,"data-large-file",w[a].getAttribute("data-large-file")),ewwwAttr(g,"data-large-file",w[a].getAttribute("data-webp-large-file")),ewwwAttr(g,"data-large_image",w[a].getAttribute("data-large_image")),ewwwAttr(g,"data-large_image",w[a].getAttribute("data-webp-large_image")),ewwwAttr(g,"data-src",w[a].getAttribute("data-src")),ewwwAttr(g,"data-src",w[a].getAttribute("data-webp-src"))):(ewwwAttr(g,"src",w[a].getAttribute("data-img")),ewwwAttr(g,"srcset",w[a].getAttribute("data-srcset-img")),ewwwAttr(g,"data-orig-file",w[a].getAttribute("data-orig-file")),ewwwAttr(g,"data-medium-file",w[a].getAttribute("data-medium-file")),ewwwAttr(g,"data-large-file",w[a].getAttribute("data-large-file")),ewwwAttr(g,"data-large_image",w[a].getAttribute("data-large_image")),ewwwAttr(g,"data-src",w[a].getAttribute("data-src"))),g=t(w[a],g),w[a].parentNode.insertBefore(g,w[a].nextSibling),w[a].className=w[a].className.replace(/\bewww_webp\b/,"")}window.jQuery&&jQuery.fn.isotope&&jQuery.fn.imagesLoaded&&(jQuery(".fusion-posts-container-infinite").imagesLoaded(function(){jQuery(".fusion-posts-container-infinite").hasClass("isotope")&&jQuery(".fusion-posts-container-infinite").isotope()}),jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").imagesLoaded(function(){jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").isotope()}))}function ewwwWebPInit(e){ewwwLoadImages(e),ewwwNggLoadGalleries(e),document.arrive(".ewww_webp",function(){ewwwLoadImages(e)});var t=0,r=setInterval(function(){"undefined"!=typeof galleries&&(ewwwNggParseGalleries(e),clearInterval(r)),1e3<(t+=25)&&clearInterval(r)},25)}function ewwwAttr(e,t,r){null!=r&&!1!==r&&e.setAttribute(t,r)}function ewwwNggParseGalleries(e){if(e)for(var t in galleries){var r=galleries[t];galleries[t].images_list=ewwwNggParseImageList(r.images_list)}}function ewwwNggLoadGalleries(e){e&&document.addEventListener("ngg.galleria.themeadded",function(e,t){window.ngg_galleria._create_backup=window.ngg_galleria.create,window.ngg_galleria.create=function(e,t){var r=$(e).data("id");return galleries["gallery_"+r].images_list=ewwwNggParseImageList(galleries["gallery_"+r].images_list),window.ngg_galleria._create_backup(e,t)}})}function ewwwNggParseImageList(e){for(var t in console.log("parsing gallery images"),e){var r=e[t];if(void 0!==r["image-webp"]&&(e[t].image=r["image-webp"],delete e[t]["image-webp"]),void 0!==r["thumb-webp"]&&(e[t].thumb=r["thumb-webp"],delete e[t]["thumb-webp"]),void 0!==r.full_image_webp&&(e[t].full_image=r.full_image_webp,delete e[t].full_image_webp),void 0!==r.srcsets)for(var a in r.srcsets)nggSrcset=r.srcsets[a],void 0!==r.srcsets[a+"-webp"]&&(e[t].srcsets[a]=r.srcsets[a+"-webp"],delete e[t].srcsets[a+"-webp"]);if(void 0!==r.full_srcsets)for(var i in r.full_srcsets)nggFSrcset=r.full_srcsets[i],void 0!==r.full_srcsets[i+"-webp"]&&(e[t].full_srcsets[i]=r.full_srcsets[i+"-webp"],delete e[t].full_srcsets[i+"-webp"])}return e}check_webp_feature("alpha",ewwwWebPInit);
|
1 |
+
var Arrive=function(c,e,d){"use strict";if(c.MutationObserver&&"undefined"!=typeof HTMLElement){var r,t,a=0,u=(r=HTMLElement.prototype.matches||HTMLElement.prototype.webkitMatchesSelector||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelector,{matchesSelector:function(e,t){return e instanceof HTMLElement&&r.call(e,t)},addMethod:function(e,t,r){var a=e[t];e[t]=function(){return r.length==arguments.length?r.apply(this,arguments):"function"==typeof a?a.apply(this,arguments):void 0}},callCallbacks:function(e,t){t&&t.options.onceOnly&&1==t.firedElems.length&&(e=[e[0]]);for(var r,a=0;r=e[a];a++)r&&r.callback&&r.callback.call(r.elem,r.elem);t&&t.options.onceOnly&&1==t.firedElems.length&&t.me.unbindEventWithSelectorAndCallback.call(t.target,t.selector,t.callback)},checkChildNodesRecursively:function(e,t,r,a){for(var i,n=0;i=e[n];n++)r(i,t,a)&&a.push({callback:t.callback,elem:i}),0<i.childNodes.length&&u.checkChildNodesRecursively(i.childNodes,t,r,a)},mergeArrays:function(e,t){var r,a={};for(r in e)e.hasOwnProperty(r)&&(a[r]=e[r]);for(r in t)t.hasOwnProperty(r)&&(a[r]=t[r]);return a},toElementsArray:function(e){return void 0===e||"number"==typeof e.length&&e!==c||(e=[e]),e}}),w=((t=function(){this._eventsBucket=[],this._beforeAdding=null,this._beforeRemoving=null}).prototype.addEvent=function(e,t,r,a){var i={target:e,selector:t,options:r,callback:a,firedElems:[]};return this._beforeAdding&&this._beforeAdding(i),this._eventsBucket.push(i),i},t.prototype.removeEvent=function(e){for(var t,r=this._eventsBucket.length-1;t=this._eventsBucket[r];r--)if(e(t)){this._beforeRemoving&&this._beforeRemoving(t);var a=this._eventsBucket.splice(r,1);a&&a.length&&(a[0].callback=null)}},t.prototype.beforeAdding=function(e){this._beforeAdding=e},t.prototype.beforeRemoving=function(e){this._beforeRemoving=e},t),l=function(i,n){var l=new w,o=this,s={fireOnAttributesModification:!1};return l.beforeAdding(function(t){var e,r=t.target;r!==c.document&&r!==c||(r=document.getElementsByTagName("html")[0]),e=new MutationObserver(function(e){n.call(this,e,t)});var a=i(t.options);e.observe(r,a),t.observer=e,t.me=o}),l.beforeRemoving(function(e){e.observer.disconnect()}),this.bindEvent=function(e,t,r){t=u.mergeArrays(s,t);for(var a=u.toElementsArray(this),i=0;i<a.length;i++)l.addEvent(a[i],e,t,r)},this.unbindEvent=function(){var r=u.toElementsArray(this);l.removeEvent(function(e){for(var t=0;t<r.length;t++)if(this===d||e.target===r[t])return!0;return!1})},this.unbindEventWithSelectorOrCallback=function(r){var e,a=u.toElementsArray(this),i=r;e="function"==typeof r?function(e){for(var t=0;t<a.length;t++)if((this===d||e.target===a[t])&&e.callback===i)return!0;return!1}:function(e){for(var t=0;t<a.length;t++)if((this===d||e.target===a[t])&&e.selector===r)return!0;return!1},l.removeEvent(e)},this.unbindEventWithSelectorAndCallback=function(r,a){var i=u.toElementsArray(this);l.removeEvent(function(e){for(var t=0;t<i.length;t++)if((this===d||e.target===i[t])&&e.selector===r&&e.callback===a)return!0;return!1})},this},i=new function(){var s={fireOnAttributesModification:!1,onceOnly:!1,existing:!1};function n(e,t,r){return!(!u.matchesSelector(e,t.selector)||(e._id===d&&(e._id=a++),-1!=t.firedElems.indexOf(e._id))||(t.firedElems.push(e._id),0))}var c=(i=new l(function(e){var t={attributes:!1,childList:!0,subtree:!0};return e.fireOnAttributesModification&&(t.attributes=!0),t},function(e,i){e.forEach(function(e){var t=e.addedNodes,r=e.target,a=[];null!==t&&0<t.length?u.checkChildNodesRecursively(t,i,n,a):"attributes"===e.type&&n(r,i)&&a.push({callback:i.callback,elem:r}),u.callCallbacks(a,i)})})).bindEvent;return i.bindEvent=function(e,t,r){t=void 0===r?(r=t,s):u.mergeArrays(s,t);var a=u.toElementsArray(this);if(t.existing){for(var i=[],n=0;n<a.length;n++)for(var l=a[n].querySelectorAll(e),o=0;o<l.length;o++)i.push({callback:r,elem:l[o]});if(t.onceOnly&&i.length)return r.call(i[0].elem,i[0].elem);setTimeout(u.callCallbacks,1,i)}c.call(this,e,t,r)},i},o=new function(){var a={};function i(e,t){return u.matchesSelector(e,t.selector)}var n=(o=new l(function(){return{childList:!0,subtree:!0}},function(e,a){e.forEach(function(e){var t=e.removedNodes,r=[];null!==t&&0<t.length&&u.checkChildNodesRecursively(t,a,i,r),u.callCallbacks(r,a)})})).bindEvent;return o.bindEvent=function(e,t,r){t=void 0===r?(r=t,a):u.mergeArrays(a,t),n.call(this,e,t,r)},o};e&&g(e.fn),g(HTMLElement.prototype),g(NodeList.prototype),g(HTMLCollection.prototype),g(HTMLDocument.prototype),g(Window.prototype);var n={};return s(i,n,"unbindAllArrive"),s(o,n,"unbindAllLeave"),n}function s(e,t,r){u.addMethod(t,r,e.unbindEvent),u.addMethod(t,r,e.unbindEventWithSelectorOrCallback),u.addMethod(t,r,e.unbindEventWithSelectorAndCallback)}function g(e){e.arrive=i.bindEvent,s(i,e,"unbindArrive"),e.leave=o.bindEvent,s(o,e,"unbindLeave")}}(window,"undefined"==typeof jQuery?null:jQuery,void 0);function check_webp_feature(e,t){var r=new Image;r.onload=function(){var e=0<r.width&&0<r.height;t(e)},r.onerror=function(){t(!1)},r.src="data:image/webp;base64,"+{alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"}[e]}function ewwwLoadImages(e){var n="data-";function t(e,t){for(var r=["align","alt","border","crossorigin","height","hspace","ismap","longdesc","usemap","vspace","width","accesskey","class","contenteditable","contextmenu","dir","draggable","dropzone","hidden","id","lang","spellcheck","style","tabindex","title","translate","sizes","data-caption","data-attachment-id","data-permalink","data-orig-size","data-comments-opened","data-image-meta","data-image-title","data-image-description","data-event-trigger","data-highlight-color","data-highlight-opacity","data-highlight-border-color","data-highlight-border-width","data-highlight-border-opacity","data-no-lazy","data-lazy","data-large_image_width","data-large_image_height"],a=0,i=r.length;a<i;a++)ewwwAttr(t,r[a],e.getAttribute(n+r[a]));return t}if(e){for(var r=document.querySelectorAll(".batch-image img, .image-wrapper a, .ngg-pro-masonry-item a, .ngg-galleria-offscreen-seo-wrapper a"),a=0,i=r.length;a<i;a++)ewwwAttr(r[a],"data-src",r[a].getAttribute("data-webp")),ewwwAttr(r[a],"data-thumbnail",r[a].getAttribute("data-webp-thumbnail"));for(a=0,i=(o=document.querySelectorAll(".rev_slider ul li")).length;a<i;a++){ewwwAttr(o[a],"data-thumb",o[a].getAttribute("data-webp-thumb"));for(var l=1;l<11;)ewwwAttr(o[a],"data-param"+l,o[a].getAttribute("data-webp-param"+l)),l++}var o;for(a=0,i=(o=document.querySelectorAll(".rev_slider img")).length;a<i;a++)ewwwAttr(o[a],"data-lazyload",o[a].getAttribute("data-webp-lazyload"));var s=document.querySelectorAll("div.woocommerce-product-gallery__image");for(a=0,i=s.length;a<i;a++)ewwwAttr(s[a],"data-thumb",s[a].getAttribute("data-webp-thumb"))}var c=document.querySelectorAll("videos");for(a=0,i=c.length;a<i;a++)ewwwAttr(c[a],"poster",e?c[a].getAttribute("data-poster-webp"):c[a].getAttribute("data-poster-image"));var d=document.querySelectorAll("img.ewww_webp_lazy_load");for(a=0,i=d.length;a<i;a++){if(e){ewwwAttr(d[a],"data-lazy-srcset",d[a].getAttribute("data-lazy-srcset-webp")),ewwwAttr(d[a],"data-srcset",d[a].getAttribute("data-srcset-webp")),ewwwAttr(d[a],"data-lazy-src",d[a].getAttribute("data-lazy-src-webp")),ewwwAttr(d[a],"data-src",d[a].getAttribute("data-src-webp")),ewwwAttr(d[a],"data-orig-file",d[a].getAttribute("data-webp-orig-file")),ewwwAttr(d[a],"data-medium-file",d[a].getAttribute("data-webp-medium-file")),ewwwAttr(d[a],"data-large-file",d[a].getAttribute("data-webp-large-file"));var u=d[a].getAttribute("srcset");null!=u&&!1!==u&&u.includes("R0lGOD")&&ewwwAttr(d[a],"src",d[a].getAttribute("data-lazy-src-webp"))}d[a].className=d[a].className.replace(/\bewww_webp_lazy_load\b/,"")}var w=document.querySelectorAll(".ewww_webp");for(a=0,i=w.length;a<i;a++){var g=document.createElement("img");e?(ewwwAttr(g,"src",w[a].getAttribute("data-webp")),ewwwAttr(g,"srcset",w[a].getAttribute("data-srcset-webp")),ewwwAttr(g,"data-orig-file",w[a].getAttribute("data-orig-file")),ewwwAttr(g,"data-orig-file",w[a].getAttribute("data-webp-orig-file")),ewwwAttr(g,"data-medium-file",w[a].getAttribute("data-medium-file")),ewwwAttr(g,"data-medium-file",w[a].getAttribute("data-webp-medium-file")),ewwwAttr(g,"data-large-file",w[a].getAttribute("data-large-file")),ewwwAttr(g,"data-large-file",w[a].getAttribute("data-webp-large-file")),ewwwAttr(g,"data-large_image",w[a].getAttribute("data-large_image")),ewwwAttr(g,"data-large_image",w[a].getAttribute("data-webp-large_image")),ewwwAttr(g,"data-src",w[a].getAttribute("data-src")),ewwwAttr(g,"data-src",w[a].getAttribute("data-webp-src"))):(ewwwAttr(g,"src",w[a].getAttribute("data-img")),ewwwAttr(g,"srcset",w[a].getAttribute("data-srcset-img")),ewwwAttr(g,"data-orig-file",w[a].getAttribute("data-orig-file")),ewwwAttr(g,"data-medium-file",w[a].getAttribute("data-medium-file")),ewwwAttr(g,"data-large-file",w[a].getAttribute("data-large-file")),ewwwAttr(g,"data-large_image",w[a].getAttribute("data-large_image")),ewwwAttr(g,"data-src",w[a].getAttribute("data-src"))),g=t(w[a],g),w[a].parentNode.insertBefore(g,w[a].nextSibling),w[a].className=w[a].className.replace(/\bewww_webp\b/,"")}window.jQuery&&jQuery.fn.isotope&&jQuery.fn.imagesLoaded&&(jQuery(".fusion-posts-container-infinite").imagesLoaded(function(){jQuery(".fusion-posts-container-infinite").hasClass("isotope")&&jQuery(".fusion-posts-container-infinite").isotope()}),jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").imagesLoaded(function(){jQuery(".fusion-portfolio:not(.fusion-recent-works) .fusion-portfolio-wrapper").isotope()}))}function ewwwWebPInit(e){ewwwLoadImages(e),ewwwNggLoadGalleries(e),document.arrive(".ewww_webp",function(){ewwwLoadImages(e)}),document.arrive(".ewww_webp_lazy_load",function(){ewwwLoadImages(e)});var t=0,r=setInterval(function(){"undefined"!=typeof galleries&&(ewwwNggParseGalleries(e),clearInterval(r)),1e3<(t+=25)&&clearInterval(r)},25)}function ewwwAttr(e,t,r){null!=r&&!1!==r&&e.setAttribute(t,r)}function ewwwNggParseGalleries(e){if(e)for(var t in galleries){var r=galleries[t];galleries[t].images_list=ewwwNggParseImageList(r.images_list)}}function ewwwNggLoadGalleries(e){e&&document.addEventListener("ngg.galleria.themeadded",function(e,t){window.ngg_galleria._create_backup=window.ngg_galleria.create,window.ngg_galleria.create=function(e,t){var r=$(e).data("id");return galleries["gallery_"+r].images_list=ewwwNggParseImageList(galleries["gallery_"+r].images_list),window.ngg_galleria._create_backup(e,t)}})}function ewwwNggParseImageList(e){for(var t in e){var r=e[t];if(void 0!==r["image-webp"]&&(e[t].image=r["image-webp"],delete e[t]["image-webp"]),void 0!==r["thumb-webp"]&&(e[t].thumb=r["thumb-webp"],delete e[t]["thumb-webp"]),void 0!==r.full_image_webp&&(e[t].full_image=r.full_image_webp,delete e[t].full_image_webp),void 0!==r.srcsets)for(var a in r.srcsets)nggSrcset=r.srcsets[a],void 0!==r.srcsets[a+"-webp"]&&(e[t].srcsets[a]=r.srcsets[a+"-webp"],delete e[t].srcsets[a+"-webp"]);if(void 0!==r.full_srcsets)for(var i in r.full_srcsets)nggFSrcset=r.full_srcsets[i],void 0!==r.full_srcsets[i+"-webp"]&&(e[t].full_srcsets[i]=r.full_srcsets[i+"-webp"],delete e[t].full_srcsets[i+"-webp"])}return e}check_webp_feature("alpha",ewwwWebPInit);
|
includes/ls.print.js
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
This lazySizes extension adds better support for print.
|
3 |
+
In case the user starts to print lazysizes will load all images.
|
4 |
+
*/
|
5 |
+
(function(window, factory) {
|
6 |
+
var globalInstall = function(){
|
7 |
+
factory(window.lazySizes);
|
8 |
+
window.removeEventListener('lazyunveilread', globalInstall, true);
|
9 |
+
};
|
10 |
+
|
11 |
+
factory = factory.bind(null, window, window.document);
|
12 |
+
|
13 |
+
if(typeof module == 'object' && module.exports){
|
14 |
+
factory(require('lazysizes'));
|
15 |
+
} else if(window.lazySizes) {
|
16 |
+
globalInstall();
|
17 |
+
} else {
|
18 |
+
window.addEventListener('lazyunveilread', globalInstall, true);
|
19 |
+
}
|
20 |
+
}(window, function(window, document, lazySizes) {
|
21 |
+
/*jshint eqnull:true */
|
22 |
+
'use strict';
|
23 |
+
var config, elements, onprint, printMedia;
|
24 |
+
// see also: http://tjvantoll.com/2012/06/15/detecting-print-requests-with-javascript/
|
25 |
+
if(window.addEventListener){
|
26 |
+
config = lazySizes && lazySizes.cfg;
|
27 |
+
elements = config.lazyClass || 'lazyload';
|
28 |
+
onprint = function(){
|
29 |
+
var i, len;
|
30 |
+
if(typeof elements == 'string'){
|
31 |
+
elements = document.getElementsByClassName(elements);
|
32 |
+
}
|
33 |
+
|
34 |
+
if(lazySizes){
|
35 |
+
for(i = 0, len = elements.length; i < len; i++){
|
36 |
+
lazySizes.loader.unveil(elements[i]);
|
37 |
+
}
|
38 |
+
}
|
39 |
+
};
|
40 |
+
|
41 |
+
addEventListener('beforeprint', onprint, false);
|
42 |
+
|
43 |
+
if(!('onbeforeprint' in window) && window.matchMedia && (printMedia = matchMedia('print')) && printMedia.addListener){
|
44 |
+
printMedia.addListener(function(){
|
45 |
+
if(printMedia.matches){
|
46 |
+
onprint();
|
47 |
+
}
|
48 |
+
});
|
49 |
+
}
|
50 |
+
}
|
51 |
+
}));
|
includes/ls.print.min.js
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
/*! lazysizes - v5.1.0 */
|
2 |
+
!function(a,b){var c=function(){b(a.lazySizes),a.removeEventListener("lazyunveilread",c,!0)};b=b.bind(null,a,a.document),"object"==typeof module&&module.exports?b(require("lazysizes")):a.lazySizes?c():a.addEventListener("lazyunveilread",c,!0)}(window,function(a,b,c){"use strict";var d,e,f,g;a.addEventListener&&(d=c&&c.cfg,e=d.lazyClass||"lazyload",f=function(){var a,d;if("string"==typeof e&&(e=b.getElementsByClassName(e)),c)for(a=0,d=e.length;a<d;a++)c.loader.unveil(e[a])},addEventListener("beforeprint",f,!1),!("onbeforeprint"in a)&&a.matchMedia&&(g=matchMedia("print"))&&g.addListener&&g.addListener(function(){g.matches&&f()}))});
|
includes/ls.unveilhooks.js
CHANGED
@@ -85,7 +85,9 @@ For background images, use data-bg attribute:
|
|
85 |
var dPR = (window.devicePixelRatio || 1);
|
86 |
var targetWidth = Math.round(e.target.offsetWidth * dPR);
|
87 |
var targetHeight = Math.round(e.target.offsetHeight * dPR);
|
88 |
-
if(window.lazySizes.hC(e.target,'wp-block-cover')){
|
|
|
|
|
89 |
bg = constrainSrc(bg,targetWidth,targetHeight,'bg-cover');
|
90 |
} else {
|
91 |
bg = constrainSrc(bg,targetWidth,targetHeight,'bg');
|
85 |
var dPR = (window.devicePixelRatio || 1);
|
86 |
var targetWidth = Math.round(e.target.offsetWidth * dPR);
|
87 |
var targetHeight = Math.round(e.target.offsetHeight * dPR);
|
88 |
+
if (window.lazySizes.hC(e.target,'wp-block-cover')) {
|
89 |
+
bg = constrainSrc(bg,targetWidth,targetHeight,'bg-cover');
|
90 |
+
} else if (window.lazySizes.hC(e.target,'elementor-bg')){
|
91 |
bg = constrainSrc(bg,targetWidth,targetHeight,'bg-cover');
|
92 |
} else {
|
93 |
bg = constrainSrc(bg,targetWidth,targetHeight,'bg');
|
readme.txt
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
=== EWWW Image Optimizer ===
|
2 |
Contributors: nosilver4u
|
3 |
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MKMQKCBFFG3WW
|
4 |
-
Tags: image,
|
5 |
Requires at least: 5.0
|
6 |
Tested up to: 5.2
|
7 |
Requires PHP: 5.6
|
8 |
-
Stable tag: 4.
|
9 |
License: GPLv3
|
10 |
|
11 |
Speed up your website and improve your visitors' experience by automatically compressing and resizing images and PDFs. Boost SEO and improve sales.
|
@@ -22,7 +22,7 @@ EWWW I.O. will optimize images uploaded and created by any plugin, and features
|
|
22 |
1. **Smooth Handling** with pixel-perfect optimization using industry-leading tools and progressive rendering.
|
23 |
1. **High Torque** as we bring you the best compression/quality ratio available with our lossy options for JPG, PNG, and PDF files.
|
24 |
1. **Adaptive Steering** with intelligent conversion options to get the right image format for the job (JPG, PNG, or GIF).
|
25 |
-
1. **Free Parking** The core plugin is free and always will be.
|
26 |
1. **Comprehensive Coverage:** no image gets left behind, optimize everything on your site, beyond just the WordPress Media Library.
|
27 |
1. **Safety First:** all communications are secured with top SSL encryption.
|
28 |
1. **Roadside Assistance:** top-notch support is in our DNA. While API customers get top priority, we answer [every single support question with care](https://ewww.io/contact-us/).
|
@@ -159,9 +159,8 @@ Using the command *gifsicle -b -O3 --careful original file*. This is particularl
|
|
159 |
|
160 |
= I want to know more about image optimization, and why you chose these options/tools. =
|
161 |
|
162 |
-
That's not a question, but since I made it up, I'll answer it. See
|
163 |
-
https://developers.google.com/
|
164 |
-
http://developer.yahoo.com/performance/rules.html#opt_images
|
165 |
|
166 |
== Screenshots ==
|
167 |
|
@@ -174,31 +173,34 @@ http://developer.yahoo.com/performance/rules.html#opt_images
|
|
174 |
* Feature requests can be viewed and submitted at https://github.com/nosilver4u/ewww-image-optimizer/labels/enhancement
|
175 |
* If you would like to help translate this plugin in your language, get started here: https://translate.wordpress.org/projects/wp-plugins/ewww-image-optimizer/
|
176 |
|
177 |
-
= 4.
|
178 |
-
*
|
179 |
-
*
|
180 |
-
*
|
181 |
-
*
|
182 |
-
*
|
183 |
-
*
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
*
|
188 |
-
*
|
189 |
-
*
|
190 |
-
|
191 |
-
|
192 |
-
*
|
193 |
-
|
194 |
-
|
195 |
-
*
|
196 |
-
*
|
197 |
-
*
|
198 |
-
*
|
199 |
-
*
|
200 |
-
*
|
201 |
-
*
|
|
|
|
|
|
|
202 |
|
203 |
= Earlier versions =
|
204 |
Please refer to the separate changelog.txt file.
|
1 |
=== EWWW Image Optimizer ===
|
2 |
Contributors: nosilver4u
|
3 |
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MKMQKCBFFG3WW
|
4 |
+
Tags: optimize, image, convert, webp, resize, compress, lazy load, optimization, lossless, lossy, seo, scale
|
5 |
Requires at least: 5.0
|
6 |
Tested up to: 5.2
|
7 |
Requires PHP: 5.6
|
8 |
+
Stable tag: 4.9.3
|
9 |
License: GPLv3
|
10 |
|
11 |
Speed up your website and improve your visitors' experience by automatically compressing and resizing images and PDFs. Boost SEO and improve sales.
|
22 |
1. **Smooth Handling** with pixel-perfect optimization using industry-leading tools and progressive rendering.
|
23 |
1. **High Torque** as we bring you the best compression/quality ratio available with our lossy options for JPG, PNG, and PDF files.
|
24 |
1. **Adaptive Steering** with intelligent conversion options to get the right image format for the job (JPG, PNG, or GIF).
|
25 |
+
1. **Free Parking** The core plugin is free and always will be. However, our paid services offer up to 80% compression, and a [host of other features](https://ewww.io/plans/)!
|
26 |
1. **Comprehensive Coverage:** no image gets left behind, optimize everything on your site, beyond just the WordPress Media Library.
|
27 |
1. **Safety First:** all communications are secured with top SSL encryption.
|
28 |
1. **Roadside Assistance:** top-notch support is in our DNA. While API customers get top priority, we answer [every single support question with care](https://ewww.io/contact-us/).
|
159 |
|
160 |
= I want to know more about image optimization, and why you chose these options/tools. =
|
161 |
|
162 |
+
That's not a question, but since I made it up, I'll answer it. See this resource:
|
163 |
+
https://developers.google.com/web/tools/lighthouse/audits/optimize-images
|
|
|
164 |
|
165 |
== Screenshots ==
|
166 |
|
173 |
* Feature requests can be viewed and submitted at https://github.com/nosilver4u/ewww-image-optimizer/labels/enhancement
|
174 |
* If you would like to help translate this plugin in your language, get started here: https://translate.wordpress.org/projects/wp-plugins/ewww-image-optimizer/
|
175 |
|
176 |
+
= 4.9.3 =
|
177 |
+
* fixed: ExactDN incorrectly scales Elementor background images rather than cropping
|
178 |
+
* fixed: ExactDN cannot work with Divi/Elementor background images due to use of external CSS files
|
179 |
+
* fixed: JS WebP rewriting picture tags that already have WebP markup in Force WebP mode
|
180 |
+
* fixed: JS WebP incorrectly parses GIF/SVG images in Force WebP mode
|
181 |
+
* fixed: JS WebP does not support lazy load + infinite scroll
|
182 |
+
* fixed: Lazy Load auto-scaling breaks if background image is enclosed in encoded quotes
|
183 |
+
* fixed: GRAND FlaGallery integration broken by hook suffix change
|
184 |
+
|
185 |
+
= 4.9.2 =
|
186 |
+
* fixed: generating lazy load PNG placeholders with large heights causes 500 errors
|
187 |
+
* fixed: error when importing media via WordPress Importer plugin
|
188 |
+
* fixed: error with WP/LR Sync
|
189 |
+
|
190 |
+
= 4.9.1 =
|
191 |
+
* fixed: error on settings screen when JS WebP is enabled
|
192 |
+
|
193 |
+
= 4.9.0 =
|
194 |
+
* added: Lazy Load background image support for section elements
|
195 |
+
* added: ExactDN background image support for li,span, and section elements
|
196 |
+
* added: lazysizes print plugin, enable via EWWW_IMAGE_OPTIMIZER_LAZY_PRINT constant
|
197 |
+
* added: compatibility with upcoming Easy Image Optimizer
|
198 |
+
* changed: automatic compression disabled during WP/LR Sync with admin notice
|
199 |
+
* changed: Lazy Load PNG placeholders capped at 1920px wide to prevent errors
|
200 |
+
* changed: use ExactDN, when active, for Lazy Load PNG placeholders
|
201 |
+
* changed: EWWW_MEMORY_LIMIT renamed to EIO_MEMORY_LIMIT for setting plugin memory limit
|
202 |
+
* fixed: WebP test image not refreshing after inserting .htaccess rules
|
203 |
+
* fixed: errors when manually adding lazysizes script
|
204 |
|
205 |
= Earlier versions =
|
206 |
Please refer to the separate changelog.txt file.
|
tests/test-utility.php
CHANGED
@@ -39,15 +39,15 @@ class EWWWIO_Utility_Tests extends WP_UnitTestCase {
|
|
39 |
*/
|
40 |
function test_mimetype() {
|
41 |
$binaries = scandir( EWWW_IMAGE_OPTIMIZER_BINARY_PATH );
|
42 |
-
global $
|
43 |
-
$
|
44 |
ewww_image_optimizer_set_option( 'ewww_image_optimizer_debug', true );
|
45 |
foreach ( $binaries as $binary ) {
|
46 |
$binary = trailingslashit( EWWW_IMAGE_OPTIMIZER_BINARY_PATH ) . $binary;
|
47 |
if ( ! is_file( $binary ) ) {
|
48 |
continue;
|
49 |
}
|
50 |
-
$this->assertTrue( (bool) ewww_image_optimizer_mimetype( $binary, 'b' ), $binary . ":\n" . str_replace( '<br>', "\n", $
|
51 |
}
|
52 |
}
|
53 |
|
39 |
*/
|
40 |
function test_mimetype() {
|
41 |
$binaries = scandir( EWWW_IMAGE_OPTIMIZER_BINARY_PATH );
|
42 |
+
global $eio_debug;
|
43 |
+
$eio_debug .= '';
|
44 |
ewww_image_optimizer_set_option( 'ewww_image_optimizer_debug', true );
|
45 |
foreach ( $binaries as $binary ) {
|
46 |
$binary = trailingslashit( EWWW_IMAGE_OPTIMIZER_BINARY_PATH ) . $binary;
|
47 |
if ( ! is_file( $binary ) ) {
|
48 |
continue;
|
49 |
}
|
50 |
+
$this->assertTrue( (bool) ewww_image_optimizer_mimetype( $binary, 'b' ), $binary . ":\n" . str_replace( '<br>', "\n", $eio_debug ) );
|
51 |
}
|
52 |
}
|
53 |
|
unique.php
CHANGED
@@ -687,9 +687,32 @@ function ewww_image_optimizer_notice_utils( $quiet = null ) {
|
|
687 |
} elseif ( ! is_writable( EWWW_IMAGE_OPTIMIZER_TOOL_PATH ) ) {
|
688 |
ewww_image_optimizer_tool_folder_permissions_notice();
|
689 |
}
|
690 |
-
|
691 |
-
|
692 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
693 |
ewwwio_memory( __FUNCTION__ );
|
694 |
}
|
695 |
}
|
@@ -2805,16 +2828,6 @@ function ewww_image_optimizer_install_pngout() {
|
|
2805 |
return $sendback;
|
2806 |
}
|
2807 |
|
2808 |
-
/**
|
2809 |
-
* Downloads a file to the EWWW IO folder.
|
2810 |
-
*
|
2811 |
-
* @param string $url The remote url to fetch.
|
2812 |
-
* @return string|WP_Error The location of the downloaded file, or a WP_Error object on failure.
|
2813 |
-
*/
|
2814 |
-
function ewwwio_download_url( $url ) {
|
2815 |
-
return $location;
|
2816 |
-
}
|
2817 |
-
|
2818 |
/**
|
2819 |
* Removes any binaries that have been installed in the wp-content/ewww/ folder.
|
2820 |
*/
|
687 |
} elseif ( ! is_writable( EWWW_IMAGE_OPTIMIZER_TOOL_PATH ) ) {
|
688 |
ewww_image_optimizer_tool_folder_permissions_notice();
|
689 |
}
|
690 |
+
if ( 'pngout' === $msg ) {
|
691 |
+
echo "<div id='ewww-image-optimizer-warning-opt-missing' class='notice notice-error'><p>" .
|
692 |
+
sprintf(
|
693 |
+
/* translators: 1: automatically (link) 2: manually (link) */
|
694 |
+
esc_html__( 'You are missing pngout. Install %1$s or %2$s.', 'ewww-image-optimizer' ),
|
695 |
+
'<a href="admin.php?action=ewww_image_optimizer_install_pngout">' . esc_html__( 'automatically', 'ewww-image-optimizer' ) . '</a>',
|
696 |
+
'<a href="https://docs.ewww.io/article/13-installing-pngout" data-beacon-article="5854531bc697912ffd6c1afa">' . esc_html__( 'manually', 'ewww-image-optimizer' ) . '</a>'
|
697 |
+
) .
|
698 |
+
'</p></div>';
|
699 |
+
} else {
|
700 |
+
echo "<div id='ewww-image-optimizer-warning-opt-missing' class='notice notice-error'><p>" .
|
701 |
+
sprintf(
|
702 |
+
/* translators: 1-6: jpegtran, optipng, pngout, pngquant, gifsicle, and cwebp (links) 7: Settings Page (link) 8: Installation Instructions (link) */
|
703 |
+
esc_html__( 'EWWW Image Optimizer uses %1$s, %2$s, %3$s, %4$s, %5$s, and %6$s. You are missing: %7$s. Please install via the %8$s or the %9$s.', 'ewww-image-optimizer' ),
|
704 |
+
"<a href='http://jpegclub.org/jpegtran/'>jpegtran</a>",
|
705 |
+
"<a href='http://optipng.sourceforge.net/'>optipng</a>",
|
706 |
+
"<a href='http://advsys.net/ken/utils.htm'>pngout</a>",
|
707 |
+
"<a href='http://pngquant.org/'>pngquant</a>",
|
708 |
+
"<a href='http://www.lcdf.org/gifsicle/'>gifsicle</a>",
|
709 |
+
"<a href='https://developers.google.com/speed/webp/'>cwebp</a>",
|
710 |
+
$msg,
|
711 |
+
"<a href='$settings_page'>" . esc_html__( 'Settings Page', 'ewww-image-optimizer' ) . '</a>',
|
712 |
+
"<a href='https://docs.ewww.io/article/6-the-plugin-says-i-m-missing-something' data-beacon-article='585371e3c697912ffd6c0ba1' target='_blank'>" . esc_html__( 'Installation Instructions', 'ewww-image-optimizer' ) . '</a>'
|
713 |
+
) .
|
714 |
+
'</p></div>';
|
715 |
+
}
|
716 |
ewwwio_memory( __FUNCTION__ );
|
717 |
}
|
718 |
}
|
2828 |
return $sendback;
|
2829 |
}
|
2830 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2831 |
/**
|
2832 |
* Removes any binaries that have been installed in the wp-content/ewww/ folder.
|
2833 |
*/
|