/** * Detects if WooCommerce is installed. * * @since 1.0.5 * @access public */ public static function detect() { if (!defined('WOOCOMMERCE_VERSION')) { return; }
self::cls()->add_hooks(); }
/** * Add hooks to woo actions * * @since 1.6.3 * @access public */ public function add_hooks() { $this->_option_append();
// Purging a product on stock change should only occur during product purchase. This function will add the purging callback when an order is complete. add_action('woocommerce_product_set_stock', array($this, 'purge_product')); add_action('woocommerce_variation_set_stock', array($this, 'purge_product')); // #984479 Update variations stock
if (apply_filters('litespeed_conf', self::O_CART_VARY)) { add_filter('litespeed_vary_cookies', function ($list) { $list[] = 'woocommerce_cart_hash'; return array_unique($list); }); } }
/** * Purge esi private tag * * @since 1.6.3 * @access public */ public function purge_esi() { do_action('litespeed_debug', '3rd woo purge ESI in action: ' . current_filter()); do_action('litespeed_purge_private_esi', 'storefront-cart-header'); }
/** * Purge private all * * @since 3.0 * @access public */ public function purge_private_all() { do_action('litespeed_purge_private_all'); }
/** * Check if need to give an ESI block for cart * * @since 1.7.2 * @access public */ public function check_if_need_esi($template) { if ($this->vary_needed()) { do_action('litespeed_debug', 'API: 3rd woo added ESI'); add_action('litespeed_tpl_normal', array($this, 'set_swap_header_cart')); }
return $template; }
/** * Keep vary on if cart is not empty * * @since 1.7.2 * @access public */ public function vary_maintain($vary) { if ($this->vary_needed()) { do_action('litespeed_debug', 'API: 3rd woo added vary due to cart not empty'); $vary['woo_cart'] = 1; }
return $vary; }
/** * Check if vary need to be on based on cart * * @since 1.7.2 * @access private */ private function vary_needed() { if (!function_exists('WC')) { return false; }
/** * Hooked to the litespeed_is_not_esi_template action. * If the request is not an esi request, I want to set my own hook in woocommerce_before_template_part to see if it's something I can ESI. * * @since 1.1.0 * @access public */ public function set_block_template() { add_action('woocommerce_before_template_part', array($this, 'block_template'), 999, 4); }
/** * Hooked to the litespeed_is_not_esi_template action. * If the request is not an esi request, I want to set my own hook * in storefront_header to see if it's something I can ESI. * * Will remove storefront_header_cart in storefront_header. * * @since 1.1.0 * @since 1.6.3 Removed static * @access public */ public function set_swap_header_cart() { $priority = has_action('storefront_header', 'storefront_header_cart'); if ($priority !== false) { remove_action('storefront_header', 'storefront_header_cart', $priority); add_action('storefront_header', array($this, 'esi_cart_header'), $priority); } }
/** * Hooked to the woocommerce_before_template_part action. * Checks if the template contains 'add-to-cart'. If so, and if I want to ESI the request, block it and build my esi code block. * * The function parameters will be passed to the esi request. * * @since 1.1.0 * @access public */ public function block_template($template_name, $template_path, $located, $args) { if (strpos($template_name, 'add-to-cart') === false) { if (strpos($template_name, 'related.php') !== false) { remove_action('woocommerce_before_template_part', array($this, 'block_template'), 999); add_filter('woocommerce_related_products_args', array($this, 'add_related_tags')); add_action('woocommerce_after_template_part', array($this, 'end_template'), 999); } return; } return;
/** * Hooked to the woocommerce_after_add_to_cart_form action. * If this is hit first, clean the buffer and remove this function and * end_template. * * @since 1.1.0 * @since 1.6.3 Removed static * @access public */ public function end_form($template_name = '') { if (!empty($template_name) && strpos($template_name, 'add-to-cart') === false) { return; } echo apply_filters('litespeed_clean_wrapper_end', ''); remove_action('woocommerce_after_add_to_cart_form', array($this, 'end_form')); remove_action('woocommerce_after_template_part', array($this, 'end_form'), 999); }
/** * If related products are loaded, need to add the extra product ids. * * The page will be purged if any of the products are changed. * * @since 1.1.0 * @since 1.6.3 Removed static * @access public * @param array $args The arguments used to build the related products section. * @return array The unchanged arguments. */ public function add_related_tags($args) { if (empty($args) || !isset($args['post__in'])) { return $args; } $related_posts = $args['post__in']; foreach ($related_posts as $related) { do_action('litespeed_tag_add_post', $related); } return $args; }
/** * Hooked to the woocommerce_after_template_part action. * If the template contains 'add-to-cart', clean the buffer. * * @since 1.1.0 * @since 1.6.3 Removed static * @access public * @param type $template_name */ public function end_template($template_name) { if (strpos($template_name, 'related.php') !== false) { remove_action('woocommerce_after_template_part', array($this, 'end_template'), 999); $this->set_block_template(); } }
/** * Hooked to the storefront_header header. * If I want to ESI the request, block it and build my esi code block. * * @since 1.1.0 * @since 1.6.3 Removed static * @access public */ public function esi_cart_header() { echo apply_filters('litespeed_esi_url', 'storefront-cart-header', 'STOREFRONT_CART_HEADER'); }
/** * Hooked to the litespeed_esi_load-storefront-cart-header action. * Generates the cart header for esi display. * * @since 1.1.0 * @since 1.6.3 Removed static * @access public */ public function load_cart_header() { storefront_header_cart(); }
/** * Hooked to the litespeed_esi_load-wc-add-to-cart-form action. * Parses the esi input parameters and generates the add to cart form * for esi display. * * @since 1.1.0 * @since 1.6.3 Removed static * @access public * @global type $post * @global type $wp_query * @param type $params */ public function load_add_to_cart_form_block($params) { global $post, $wp_query; $post = get_post($params[self::ESI_PARAM_POSTID]); $wp_query->setup_postdata($post); function_exists('wc_get_template') && wc_get_template($params[self::ESI_PARAM_NAME], $params[self::ESI_PARAM_ARGS], $params[self::ESI_PARAM_PATH]); }
/** * Update woocommerce when someone visits a product and has the * recently viewed products widget. * * Currently, this widget should not be cached. * * @since 1.1.0 * @since 1.6.3 Removed static * @access public * @param array $params Widget parameter array */ public function register_post_view($params) { if ($params[API::PARAM_NAME] !== 'WC_Widget_Recently_Viewed') { return; } if (!isset($params[self::ESI_PARAM_POSTID])) { return; } $id = $params[self::ESI_PARAM_POSTID]; $esi_post = get_post($id); $product = function_exists('wc_get_product') ? wc_get_product($esi_post) : false;
if (empty($product)) { return; }
global $post; $post = $esi_post; function_exists('wc_track_product_view') && wc_track_product_view(); }
/** * Adds the post id to the widget ESI parameters for the Recently Viewed widget. * * This is needed in the ESI request to update the cookie properly. * * @since 1.1.0 * @access public */ public function add_post_id($params, $block_id) { if ($block_id == 'widget') { if ($params[API::PARAM_NAME] == 'WC_Widget_Recently_Viewed') { $params[self::ESI_PARAM_POSTID] = get_the_ID(); } }
return $params; }
/** * Hooked to the litespeed_widget_default_options filter. * * The recently viewed widget must be esi to function properly. * This function will set it to enable and no cache by default. * * @since 1.1.0 * @access public */ public function wc_widget_default($options, $widget) { if (!is_array($options)) { return $options; } $widget_name = get_class($widget); if ($widget_name === 'WC_Widget_Recently_Viewed') { $options[API::WIDGET_O_ESIENABLE] = API::VAL_ON2; $options[API::WIDGET_O_TTL] = 0; } elseif ($widget_name === 'WC_Widget_Recent_Reviews') { $options[API::WIDGET_O_ESIENABLE] = API::VAL_ON; $options[API::WIDGET_O_TTL] = 86400; } return $options; }
/** * Set WooCommerce cache tags based on page type. * * @since 1.0.9 * @since 1.6.3 Removed static * @access public */ public function set_tag() { $id = get_the_ID(); if ($id === false) { return; }
// Check if product has a cache ttl limit or not $sale_from = (int) get_post_meta($id, '_sale_price_dates_from', true); $sale_to = (int) get_post_meta($id, '_sale_price_dates_to', true); $now = current_time('timestamp'); $ttl = false; if ($sale_from && $now < $sale_from) { $ttl = $sale_from - $now; } elseif ($sale_to && $now < $sale_to) { $ttl = $sale_to - $now; } if ($ttl && $ttl < apply_filters('litespeed_control_ttl', 0)) { do_action('litespeed_control_set_ttl', $ttl, "WooCommerce set scheduled TTL to $ttl"); }
if (function_exists('is_shop') && is_shop()) { do_action('litespeed_tag_add', self::CACHETAG_SHOP); } if (function_exists('is_product_taxonomy') && !is_product_taxonomy()) { return; } if (isset($GLOBALS['product_cat']) && is_string($GLOBALS['product_cat'])) { // todo: need to check previous woo version to find if its from old woo versions or not! $term = get_term_by('slug', $GLOBALS['product_cat'], 'product_cat'); } elseif (isset($GLOBALS['product_tag']) && is_string($GLOBALS['product_tag'])) { $term = get_term_by('slug', $GLOBALS['product_tag'], 'product_tag'); } else { $term = false; }
if ($term === false) { return; } while (isset($term)) { do_action('litespeed_tag_add', self::CACHETAG_TERM . $term->term_id); if ($term->parent == 0) { break; } $term = get_term($term->parent); } }
/** * Check if the page is cacheable according to WooCommerce. * * @since 1.0.5 * @since 1.6.3 Removed static * @access public * @param string $esi_id The ESI block id if a request is an ESI request. * @return boolean True if cacheable, false if not. */ public function set_control($esi_id) { if (!apply_filters('litespeed_control_cacheable', false)) { return; }
/** * Avoid possible 500 issue * @since 1.6.2.1 */ if (!function_exists('WC')) { return; }
$woocom = WC(); if (!$woocom || empty($woocom->session)) { return; }
// For later versions, DONOTCACHEPAGE should be set. // No need to check uri/qs. if (version_compare($woocom->version, '1.4.2', '>=')) { if (version_compare($woocom->version, '3.2.0', '<') && defined('DONOTCACHEPAGE') && DONOTCACHEPAGE) { do_action('litespeed_control_set_nocache', '3rd party woocommerce not cache by constant'); return; } elseif (version_compare($woocom->version, '2.1.0', '>=')) { $err = false;
// Check if is variation, purge stock too #984479 if ($product->is_type('variation')) { do_action('litespeed_purge_post', $product->get_parent_id()); }
// Check if WPML is enabled ##972971 if (defined('WPML_PLUGIN_BASENAME')) { // Check if it is a variable product and get post/parent ID $wpml_purge_id = $product->is_type('variation') ? $product->get_parent_id() : $product->get_id(); $type = apply_filters('wpml_element_type', get_post_type($wpml_purge_id)); $trid = apply_filters('wpml_element_trid', false, $wpml_purge_id, $type); $translations = apply_filters('wpml_get_element_translations', array(), $trid, $type); foreach ($translations as $lang => $translation) { do_action('litespeed_debug', '[3rd] Woo WPML purge language: ' . $translation->language_code . ' , post ID: ' . $translation->element_id); do_action('litespeed_purge_post', $translation->element_id); // use the $translation->element_id as it is post ID of other languages }
// Check other languages category and purge if configured. // wp_get_post_terms() only returns default language category ID $default_cats = wp_get_post_terms($wpml_purge_id, 'product_cat'); $languages = apply_filters('wpml_active_languages', null);
/** * Delete object-term relationship. If the post is a product and * the term ids array is not empty, will add purge tags to the deleted * terms. * * @since 1.0.9 * @since 1.6.3 Removed static * @access public * @param int $post_id Object ID. * @param array $term_ids An array of term taxonomy IDs. */ public function delete_rel($post_id, $term_ids) { if (!function_exists('wc_get_product')) { return; }
if (empty($term_ids) || wc_get_product($post_id) === false) { return; } foreach ($term_ids as $term_id) { do_action('litespeed_purge', self::CACHETAG_TERM . $term_id); } }
/** * Purge a product's categories and tags pages in case they are affected. * * @since 1.0.9 * @since 1.6.3 Removed static * @access public * @param int $post_id Post id that is about to be purged */ public function backend_purge($post_id) { if (!function_exists('wc_get_product')) { return; }
if (!isset($post_id) || wc_get_product($post_id) === false) { return; }
$cats = $this->get_cats($post_id); if (!empty($cats)) { foreach ($cats as $cat) { do_action('litespeed_purge', self::CACHETAG_TERM . $cat); } }
if (!function_exists('wc_get_product_terms')) { return; }
/** * When a product has a new review added, purge the recent reviews widget. * * @since 1.1.0 * @since 1.6.3 Removed static * @access public * @param $unused * @param integer $comment_approved Whether the comment is approved or not. * @param array $commentdata Information about the comment. */ public function add_review($unused, $comment_approved, $commentdata) { if (!function_exists('wc_get_product')) { return; }
global $wp_widget_factory; if (!isset($wp_widget_factory->widgets['WC_Widget_Recent_Reviews'])) { return; }
$recent_reviews = $wp_widget_factory->widgets['WC_Widget_Recent_Reviews']; if (!is_null($recent_reviews)) { do_action('litespeed_tag_add_widget', $recent_reviews->id); } }
/** * Append new options * * @since 1.6.3 Removed static * @since 3.0 new API */ private function _option_append() { // Append option save value filter do_action('litespeed_conf_multi_switch', self::O_UPDATE_INTERVAL, 3); // This need to be before conf_append
/** * Hooked to `litespeed_settings_tab` action. * Adds the integration configuration options (currently, to determine purge rules) * * @since 1.6.3 Removed static */ public function settings_add_tab($setting_page) { if ($setting_page != 'cache') { return; }
require 'woocommerce.tab.tpl.php'; }
/** * Hook to show config content * * @since 3.0 */ public function settings_add_content($setting_page) { if ($setting_page != 'cache') { return; }
require 'woocommerce.content.tpl.php'; }
/** * Helper function to select the function(s) to use to get the product * category ids. * * @since 1.0.10 * @since 1.6.3 Removed static * @access private * @param int $product_id The product id * @return array An array of category ids. */ private function get_cats($product_id) { if (!function_exists('WC')) { return; }
/** * 3rd party prepload * * @since 2.9.8.4 */ public static function preload() { /** * Auto puge for WooCommerce Advanced Bulk Edit plugin, * Bulk edit hook need to add to preload as it will die before detect. */ add_action('wp_ajax_wpmelon_adv_bulk_edit', __CLASS__ . '::bulk_edit_purge', 1); }
/** * Auto puge for WooCommerce Advanced Bulk Edit plugin, * * @since 2.9.8.4 */ public static function bulk_edit_purge() { if (empty($_POST['type']) || $_POST['type'] != 'saveproducts' || empty($_POST['data'])) { return; }