get_all_settings(); if ( ! empty( $settings['woo_disable_cart_fragments'] ) ) { add_action( 'wp_enqueue_scripts', array( $this, 'disable_cart_fragments' ), 99 ); } if ( ! empty( $settings['woo_dequeue_outside_shop'] ) ) { add_action( 'wp_enqueue_scripts', array( $this, 'dequeue_outside_shop' ), 100 ); } if ( ! empty( $settings['woo_disable_password_strength'] ) ) { add_action( 'wp_enqueue_scripts', array( $this, 'disable_password_strength' ), 100 ); } if ( ! empty( $settings['woo_disable_scripts_outside_checkout'] ) ) { add_action( 'wp_enqueue_scripts', array( $this, 'checkout_only_scripts' ), 101 ); } // Purge product/shop caches when stock or product saved. add_action( 'woocommerce_update_product', array( $this, 'purge_product' ), 20, 1 ); add_action( 'woocommerce_product_set_stock_status', array( $this, 'purge_product' ), 20, 1 ); add_action( 'woocommerce_variation_set_stock_status', array( $this, 'purge_product' ), 20, 1 ); add_filter( 'qwsc_js_protected_handles', array( $this, 'protected_handles' ) ); } /** * When empty-cart caching is allowed, drop session cookies from the "block all cache" list * if the cart is empty (page cache can serve anonymous HTML). * * @param string[] $prefixes Prefixes. * @return string[] */ public function filter_sensitive_cookies( $prefixes ) { $settings = \QWSpeedCache\Plugin::instance()->get_all_settings(); $prefixes = is_array( $prefixes ) ? $prefixes : array(); // Empty cart: allow anonymous page cache (session cookie alone is not enough to bypass). $allow_empty = ! empty( $settings['woo_cache_empty_cart'] ) || ! isset( $settings['woo_cache_empty_cart'] ); if ( $allow_empty ) { $count = self::cart_item_count_from_request(); if ( 0 === $count && ! self::has_woocommerce_session_cookie() ) { $drop = array( 'wp_woocommerce_session_', 'woocommerce_cart_hash', 'woocommerce_items_in_cart' ); $prefixes = array_values( array_filter( $prefixes, function ( $p ) use ( $drop ) { return ! in_array( (string) $p, $drop, true ); } ) ); } } return $prefixes; } /** * Cart quantity from WC or cookies (no session start required). * * @return int */ /** Never treat an existing WooCommerce session as an anonymous cache-safe request. */ private static function has_woocommerce_session_cookie() { foreach ( array_keys( $_COOKIE ) as $cookie_name ) { if ( 0 === strpos( (string) $cookie_name, 'wp_woocommerce_session_' ) ) { return true; } } return false; } public static function cart_item_count_from_request() { if ( did_action( 'wp_loaded' ) && function_exists( 'WC' ) && WC()->cart ) { return (int) WC()->cart->get_cart_contents_count(); } if ( empty( $_COOKIE['woocommerce_items_in_cart'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended return 0; } $v = isset( $_COOKIE['woocommerce_items_in_cart'] ) && is_scalar( $_COOKIE['woocommerce_items_in_cart'] ) ? sanitize_text_field( wp_unslash( (string) $_COOKIE['woocommerce_items_in_cart'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended if ( '1' === $v || 'yes' === strtolower( $v ) ) { return 1; } return is_numeric( $v ) ? (int) $v : 1; } public function default_uris( $uris ) { $extra = array( '/cart', '/checkout', '/my-account', '/wc-api/', '/cart/', '/checkout/', '/my-account/', '/order-pay', '/order-received', '/add-to-cart', ); return array_unique( array_merge( (array) $uris, $extra ) ); } public function maybe_donotcache() { if ( function_exists( 'is_cart' ) && ( is_cart() || is_checkout() || is_account_page() ) ) { if ( ! defined( 'DONOTCACHEPAGE' ) ) { define( 'DONOTCACHEPAGE', true ); } } if ( function_exists( 'is_wc_endpoint_url' ) && is_wc_endpoint_url() ) { if ( ! defined( 'DONOTCACHEPAGE' ) ) { define( 'DONOTCACHEPAGE', true ); } } } /** * Cart fragments AJAX is heavy; disable off cart/checkout/account when empty cart. */ public function disable_cart_fragments() { if ( $this->is_woo_endpoint() ) { return; } if ( function_exists( 'WC' ) && WC()->cart && WC()->cart->get_cart_contents_count() > 0 ) { return; } wp_dequeue_script( 'wc-cart-fragments' ); wp_deregister_script( 'wc-cart-fragments' ); } /** * Dequeue Woo scripts/styles on non-commerce pages. */ public function dequeue_outside_shop() { if ( $this->is_woo_endpoint() ) { return; } $styles = array( 'woocommerce-general', 'woocommerce-layout', 'woocommerce-smallscreen', 'woocommerce_frontend_styles', 'wc-blocks-style', 'wc-blocks-vendors-style', ); $scripts = array( 'woocommerce', 'wc-add-to-cart', 'wc-cart-fragments', 'wc-credit-card-form', 'wc-single-product', 'wc-checkout', 'wc-cart', 'wc-chosen', 'prettyPhoto', 'prettyPhoto-init', 'jquery-blockui', 'jquery-placeholder', 'jquery-payment', 'js-cookie', 'wc-order-attribution', 'sourcebuster-js', 'wc-add-to-cart-variation', 'zoom', 'flexslider', 'photoswipe', 'photoswipe-ui-default', 'wc-password-strength-meter', ); foreach ( $styles as $h ) { wp_dequeue_style( $h ); wp_deregister_style( $h ); } foreach ( $scripts as $h ) { wp_dequeue_script( $h ); wp_deregister_script( $h ); } } /** * Password strength meter only on account / lost password screens. */ public function disable_password_strength() { if ( function_exists( 'is_account_page' ) && is_account_page() ) { return; } wp_dequeue_script( 'wc-password-strength-meter' ); wp_deregister_script( 'wc-password-strength-meter' ); } /** * Heavy checkout-only libraries off product/shop listing pages. */ public function checkout_only_scripts() { if ( function_exists( 'is_checkout' ) && is_checkout() ) { return; } if ( function_exists( 'is_cart' ) && is_cart() ) { return; } $handles = array( 'wc-credit-card-form', 'jquery-payment', 'wc-checkout', 'selectWoo', 'select2', 'wc-country-select', 'wc-address-i18n', ); foreach ( $handles as $h ) { wp_dequeue_script( $h ); } } /** * @param int|\WC_Product $product Product. */ public function purge_product( $product ) { $id = 0; if ( is_object( $product ) && method_exists( $product, 'get_id' ) ) { $id = (int) $product->get_id(); } else { $id = (int) $product; } if ( $id <= 0 ) { return; } if ( class_exists( '\QWSpeedCache\Cache\Purge' ) ) { $purge = new \QWSpeedCache\Cache\Purge(); if ( method_exists( $purge, 'purge_urls' ) ) { $urls = array( get_permalink( $id ) ); if ( function_exists( 'wc_get_page_id' ) ) { $shop = (int) wc_get_page_id( 'shop' ); if ( $shop > 0 ) { $urls[] = get_permalink( $shop ); } } $urls[] = home_url( '/' ); $purge->purge_urls( array_filter( $urls ) ); } } } /** * @return bool */ private function is_woo_endpoint() { if ( function_exists( 'is_cart' ) && ( is_cart() || is_checkout() || is_account_page() ) ) { return true; } if ( function_exists( 'is_product' ) && is_product() ) { return true; } if ( function_exists( 'is_shop' ) && is_shop() ) { return true; } if ( function_exists( 'is_product_category' ) && ( is_product_category() || is_product_tag() ) ) { return true; } if ( function_exists( 'is_product_taxonomy' ) && is_product_taxonomy() ) { return true; } return false; } /** * Pure: should cart fragments load? * * @param bool $is_woo_page Is commerce page. * @param int $cart_count Cart item count. * @return bool */ public static function should_load_cart_fragments( $is_woo_page, $cart_count ) { if ( $is_woo_page ) { return true; } return (int) $cart_count > 0; } /** * @param string[] $handles Handles. * @return string[] */ public function protected_handles( $handles ) { $woo = array( 'woocommerce', 'wc-add-to-cart', 'wc-cart-fragments', 'wc-checkout', 'wc-cart', 'wc-single-product', 'stripe', 'wc-stripe-upe-classic', 'jquery-blockui', 'js-cookie', 'selectWoo', 'wc-password-strength-meter', ); return array_values( array_unique( array_merge( (array) $handles, $woo ) ) ); } }