'false', 'data-no-defer' => '1', 'data-no-minify' => '1', 'data-no-optimize' => '1', ); /** * Request URI. * * @var string $request_uri */ public $request_uri = ''; /** * Register (once) actions and filters for Lazy Load. */ public function __construct() { parent::__construct(); $this->debug_message( '' . __METHOD__ . '()' ); $this->content_url(); $this->request_uri = \add_query_arg( '', '' ); if ( false === \strpos( $this->request_uri, 'page=ewww-image-optimizer-options' ) ) { $this->debug_message( "request uri is {$this->request_uri}" ); } else { $this->debug_message( 'request uri is EWWW IO settings' ); } \add_filter( 'eio_do_lazyload', array( $this, 'should_process_page' ), 10, 2 ); /** * Allow pre-empting Lazy Load by page. * * @param bool Whether to parse the page for images to lazy load, default true. * @param string The URL of the page. */ if ( ! \apply_filters( 'eio_do_lazyload', true, $this->request_uri ) ) { return; } $this->piip_folder = $this->content_dir . 'lazy/'; global $eio_lazy_load; if ( \is_object( $eio_lazy_load ) ) { $this->debug_message( 'you are doing it wrong' ); return 'you are doing it wrong'; } \add_action( 'wp_head', array( $this, 'no_js_css' ) ); if ( \method_exists( 'autoptimizeImages', 'imgopt_active' ) && \autoptimizeImages::imgopt_active() ) { add_filter( 'autoptimize_filter_html_before_minify', array( $this, 'filter_page_output' ) ); } else { add_filter( $this->prefix . 'filter_page_output', array( $this, 'filter_page_output' ), 15 ); } \add_filter( 'vc_get_vc_grid_data_response', array( $this, 'filter_page_output' ) ); \add_filter( 'woocommerce_prl_ajax_response_html', array( $this, 'filter_html_array' ) ); // Filter for FacetWP JSON responses. \add_filter( 'facetwp_render_output', array( $this, 'filter_facetwp_json_output' ) ); if ( \class_exists( __NAMESPACE__ . '\ExactDN' ) && $this->get_option( $this->prefix . 'exactdn' ) ) { global $exactdn; $this->exactdn_domain = $exactdn->get_exactdn_domain(); if ( $this->exactdn_domain ) { $this->parsing_exactdn = true; $this->debug_message( 'parsing an exactdn page' ); $this->allowed_urls[] = 'https://' . $this->exactdn_domain; $this->allowed_urls[] = 'http://' . $this->exactdn_domain; $this->allowed_urls[] = '//' . $this->exactdn_domain; } } if ( ! \is_dir( $this->piip_folder ) ) { $this->allow_piip = \wp_mkdir_p( $this->piip_folder ) && ( $this->gd_support() || $this->imagick_support() ); } else { $this->allow_piip = \is_writable( $this->piip_folder ) && ( $this->gd_support() || $this->imagick_support() ); } \add_filter( 'wp_lazy_loading_enabled', array( $this, 'wp_lazy_loading_enabled' ), 10, 2 ); if ( ! \defined( 'EIO_LL_AUTOSCALE' ) && ! $this->get_option( $this->prefix . 'll_autoscale' ) ) { $this->debug_message( 'autoscale disabled' ); \define( 'EIO_LL_AUTOSCALE', false ); } // Override for number of images to consider "above the fold". \add_filter( 'eio_lazy_fold', array( $this, 'override_lazy_fold' ), 9 ); // Filter early, so that others at the default priority take precendence. \add_filter( 'eio_use_piip', array( $this, 'maybe_piip' ), 9 ); \add_filter( 'eio_use_siip', array( $this, 'maybe_siip' ), 9 ); // Overrides for admin-ajax images. \add_filter( 'eio_allow_admin_lazyload', array( $this, 'allow_admin_lazyload' ) ); // Load the appropriate JS. if ( \defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG || \defined( \strtoupper( $this->prefix ) . 'SCRIPT_DEBUG' ) && \constant( \strtoupper( $this->prefix ) . 'SCRIPT_DEBUG' ) ) { // Load the non-minified and separate versions of the lazy load scripts. \add_action( 'wp_enqueue_scripts', array( $this, 'debug_script' ), 1 ); } else { // Load the minified, combined version of the lazy load script. \add_action( 'wp_enqueue_scripts', array( $this, 'min_script' ), 1 ); } $this->inline_script_attrs = (array) \apply_filters( 'ewwwio_inline_script_attrs', $this->inline_script_attrs ); $this->validate_user_exclusions(); $this->validate_css_element_inclusions(); $this->get_allowed_domains(); } /** * Check if pages should be processed, especially for things like page builders. * * @since 6.2.2 * * @param boolean $should_process Whether LL should process the page. * @param string $uri The URI of the page (no domain or scheme included). * @return boolean True to process the page, false to skip. */ public function should_process_page( $should_process = true, $uri = '' ) { // Don't foul up the admin side of things, unless a plugin needs to. if ( \is_admin() && /** * Provide plugins a way of running Lazy Load for images in the WordPress Admin, usually for admin-ajax.php. * * @param bool false Allow Lazy Load to run on the Dashboard. Default to false. */ false === \apply_filters( 'eio_allow_admin_lazyload', false ) ) { $this->debug_message( 'is_admin' ); return false; } if ( empty( $uri ) ) { $uri = $this->request_uri; } if ( $this->is_iterable( $this->user_page_exclusions ) ) { foreach ( $this->user_page_exclusions as $page_exclusion ) { if ( '/' === $page_exclusion && '/' === $uri ) { return false; } elseif ( '/' === $page_exclusion ) { continue; } if ( false !== \strpos( $uri, $page_exclusion ) ) { return false; } } } if ( false !== \strpos( $uri, 'bricks=run' ) ) { return false; } if ( false !== \strpos( $uri, '?brizy-edit' ) ) { return false; } if ( false !== \strpos( $uri, '&builder=true' ) ) { return false; } if ( false !== \strpos( $uri, 'cornerstone=' ) || false !== \strpos( $uri, 'cornerstone-endpoint' ) || false !== \strpos( $uri, 'cornerstone/edit/' ) ) { return false; } if ( false !== \strpos( $uri, 'ct_builder=' ) ) { return false; } if ( false !== \strpos( $uri, 'ct_render_shortcode=' ) || false !== \strpos( $uri, 'action=oxy_render' ) ) { return false; } if ( \did_action( 'cornerstone_boot_app' ) || \did_action( 'cs_before_preview_frame' ) ) { return false; } if ( \did_action( 'cs_element_rendering' ) || \did_action( 'cornerstone_before_boot_app' ) || \apply_filters( 'cs_is_preview_render', false ) ) { return false; } if ( false !== \strpos( $uri, 'elementor-preview=' ) ) { return false; } if ( false !== \strpos( $uri, 'et_fb=' ) ) { return false; } if ( false !== \strpos( $uri, 'fb-edit=' ) ) { return false; } if ( false !== \strpos( $uri, '?fl_builder' ) ) { return false; } if ( false !== \strpos( $uri, '?giveDonationFormInIframe' ) ) { return false; } if ( false !== \strpos( $uri, 'is-editor-iframe=' ) ) { return false; } if ( '/print/' === \substr( $uri, -7 ) ) { return false; } if ( \defined( 'REST_REQUEST' ) && REST_REQUEST ) { return false; } if ( false !== \strpos( $uri, 'tatsu=' ) ) { return false; } if ( false !== \strpos( $uri, 'tve=true' ) ) { return false; } if ( ! empty( $_POST['action'] ) && 'tatsu_get_concepts' === \sanitize_text_field( \wp_unslash( $_POST['action'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification return false; } if ( \is_customize_preview() ) { $this->debug_message( 'is_customize_preview' ); return false; } global $wp_query; if ( ! isset( $wp_query ) || ! ( $wp_query instanceof \WP_Query ) ) { return $should_process; } if ( ! \did_action( 'parse_query' ) ) { return $should_process; } if ( \function_exists( '\affwp_is_affiliate_portal' ) && \affwp_is_affiliate_portal() ) { return false; } if ( $this->is_amp() ) { return false; } if ( \is_embed() ) { $this->debug_message( 'is_embed' ); return false; } if ( \is_feed() ) { $this->debug_message( 'is_feed' ); return false; } if ( \is_preview() ) { $this->debug_message( 'is_preview' ); return false; } if ( \wp_script_is( 'twentytwenty-twentytwenty', 'enqueued' ) ) { $this->debug_message( 'twentytwenty enqueued' ); return false; } return $should_process; } /** * Disable native lazy load for img elements. * * @param bool $default_value True if it is an img or iframe element. Should be false otherwise. * @param string $tag_name The type of HTML tag/element being parsed. * @return bool False for img elements, leave as-is for others. */ public function wp_lazy_loading_enabled( $default_value, $tag_name = 'img' ) { if ( 'img' === $tag_name ) { if ( \defined( 'EIO_ENABLE_NATIVE_LAZY' ) && EIO_ENABLE_NATIVE_LAZY ) { return true; } return false; } return $default_value; } /** * Search for img elements and rewrite them for Lazy Load with fallback to noscript elements. * * @param string $buffer The full HTML page generated since the output buffer was started. * @return string The altered buffer containing the full page with Lazy Load attributes. */ public function filter_page_output( $buffer ) { $this->debug_message( '' . __METHOD__ . '()' ); if ( empty( $buffer ) ) { return $buffer; } if ( \preg_match( '/^<\?xml/', $buffer ) ) { $this->debug_message( 'not html, xml tag found' ); return $buffer; } if ( \strpos( $buffer, 'amp-boilerplate' ) ) { $this->debug_message( 'AMP page processing' ); return $buffer; } if ( $this->is_json( $buffer ) ) { return $buffer; } if ( ! $this->should_process_page() ) { return $buffer; } if ( ! \apply_filters( 'eio_do_lazyload', true, $this->request_uri ) ) { return $buffer; } $above_the_fold = \apply_filters( 'eio_lazy_fold', 0 ); $images_processed = 0; $replacements = array(); // Clean the buffer of incompatible sections. $search_buffer = \preg_replace( '/