ACF.php
1 year ago
AdvancedMathCaptcha.php
3 years ago
AeliaCurrencySwitcher.php
3 years ago
BeaverBuilder.php
4 years ago
CF_Helper.php
3 years ago
Cloudflare.php
2 years ago
CommonHelpers.php
3 years ago
CookieNotice.php
4 years ago
DownloadManager.php
4 years ago
Elementor.php
3 years ago
Ezoic.php
4 years ago
FusionBuilder.php
4 years ago
GeoTargetingWP.php
2 years ago
GravityForms.php
2 years ago
JetPackNP.php
3 years ago
NginxHelper.php
2 years ago
RC.php
3 years ago
RankMathNP.php
3 years ago
ShortPixel.php
4 years ago
SquirrlySEO.php
3 years ago
TheEventsCalendar.php
3 years ago
ThriveTheme.php
4 years ago
WCML.php
3 years ago
WPBakeryNP.php
3 years ago
WPCacheHelper.php
3 years ago
WPForms.php
3 years ago
WPML.php
1 year ago
WPRocket.php
4 years ago
WooCommerce.php
1 year ago
WoocommerceCacheHandler.php
4 years ago
YoastSEO.php
3 years ago
WooCommerce.php
204 lines
| 1 | <?php |
| 2 | |
| 3 | namespace NitroPack\Integration\Plugin; |
| 4 | |
| 5 | class WooCommerce { |
| 6 | const STAGE = "very_early"; |
| 7 | |
| 8 | public static function isActive() { |
| 9 | if (class_exists('WooCommerce')) return true; |
| 10 | return false; |
| 11 | } |
| 12 | |
| 13 | public function init($stage) { |
| 14 | add_action('init', [$this, 'cache_sale_products']); |
| 15 | add_action('updated_post_meta', [$this, 'update_cached_sale_products'], 10, 4); |
| 16 | add_action('added_post_meta', [$this, 'update_cached_sale_products'], 10, 4); |
| 17 | add_action('deleted_post_meta', [$this, 'update_cached_sale_products'], 10, 4); |
| 18 | if (nitropack_is_optimizer_request()) { |
| 19 | add_action('template_redirect', [$this, 'purge_site_cache_on_sale_start_and_end']); |
| 20 | } |
| 21 | } |
| 22 | /** |
| 23 | * Retrieves the sale dates for a given WooCommerce product. |
| 24 | * |
| 25 | * @param \WC_Product $product The WooCommerce product object. |
| 26 | * @return array An associative array containing the start and end dates of the sale. |
| 27 | */ |
| 28 | private function get_sale_dates($product) { |
| 29 | $sale_start = $product->get_date_on_sale_from(); |
| 30 | $sale_end = $product->get_date_on_sale_to(); |
| 31 | $result = []; |
| 32 | |
| 33 | if ($sale_start) { |
| 34 | $sale_start = strtotime(date('Y-m-d', $sale_start->getTimestamp())); |
| 35 | $result['from'] = $sale_start; |
| 36 | } |
| 37 | if ($sale_end) { |
| 38 | $sale_end = strtotime(date('Y-m-d', $sale_end->getTimestamp())); |
| 39 | $result['to'] = $sale_end; |
| 40 | } |
| 41 | |
| 42 | return $result; |
| 43 | } |
| 44 | /** |
| 45 | * This method sets the expiration date for the cache. |
| 46 | * |
| 47 | * @param int $date The expiration date as a timestamp. |
| 48 | * @return void |
| 49 | */ |
| 50 | private function add_cache_expiration($date) { |
| 51 | global $np_customExpirationTimes; |
| 52 | |
| 53 | $np_customExpirationTimes[] = $date; |
| 54 | nitropack_set_custom_expiration(); |
| 55 | } |
| 56 | /** |
| 57 | * Update cached products when post meta is updated, deleted, or added. |
| 58 | * |
| 59 | * This function updates the cached sale product dates when the post meta |
| 60 | * keys '_sale_price_dates_from' or '_sale_price_dates_to' are modified. |
| 61 | * It ensures that the cached products are updated accordingly and removes |
| 62 | * the product from the cache if both dates are empty. |
| 63 | * |
| 64 | * @param int $meta_id The ID of the meta entry being updated. |
| 65 | * @param int $post_id The ID of the post being updated. |
| 66 | * @param string $meta_key The meta key being updated. |
| 67 | * @param string $meta_value The new value of the meta key. |
| 68 | * @return void |
| 69 | */ |
| 70 | public function update_cached_sale_products($meta_id, $post_id, $meta_key, $meta_value) { |
| 71 | //bail if we dont update future sale dates |
| 72 | if ($meta_key != '_sale_price_dates_from' && $meta_key != '_sale_price_dates_to') return; |
| 73 | |
| 74 | $cached_products = get_transient('nitropack_sale_product_dates'); |
| 75 | // If $cached_products is empty, initialize it as an array |
| 76 | if (empty($cached_products)) { |
| 77 | $cached_products = []; |
| 78 | } |
| 79 | |
| 80 | // Ensure that the $post_id key exists in the $cached_products array |
| 81 | if (!isset($cached_products[$post_id])) { |
| 82 | $cached_products[$post_id] = []; |
| 83 | } |
| 84 | //update |
| 85 | if ($meta_key === '_sale_price_dates_from') { |
| 86 | $cached_products[$post_id]['from'] = $meta_value; |
| 87 | } |
| 88 | if ($meta_key === '_sale_price_dates_to') { |
| 89 | $cached_products[$post_id]['to'] = $meta_value; |
| 90 | } |
| 91 | //delete product |
| 92 | if (empty($cached_products[$post_id]['from']) && empty($cached_products[$post_id]['to'])) { |
| 93 | unset($cached_products[$post_id]); |
| 94 | } |
| 95 | set_transient('nitropack_sale_product_dates', $cached_products); |
| 96 | } |
| 97 | /** |
| 98 | * Cache all products with sale dates. |
| 99 | * |
| 100 | * This method identifies all products that have sale dates and caches them |
| 101 | * to improve performance and reduce load times for users viewing sale items. |
| 102 | * |
| 103 | * @return void |
| 104 | */ |
| 105 | public function cache_sale_products() { |
| 106 | $cached_products = get_transient('nitropack_sale_product_dates'); |
| 107 | if ($cached_products !== false) return; |
| 108 | |
| 109 | $scheduled_sale_products = $this->get_products_with_sale(); |
| 110 | $sale_dates = array(); |
| 111 | if (!empty($scheduled_sale_products)) { |
| 112 | |
| 113 | foreach ($scheduled_sale_products as $scheduled_sale_product_id) { |
| 114 | $current_product_sale_dates = $this->get_sale_dates(wc_get_product($scheduled_sale_product_id)); |
| 115 | $sale_dates[$scheduled_sale_product_id] = $current_product_sale_dates; |
| 116 | } |
| 117 | } |
| 118 | //mostly it will be empty array |
| 119 | set_transient('nitropack_sale_product_dates', $sale_dates); |
| 120 | } |
| 121 | |
| 122 | /** |
| 123 | * Purges the site cache when a sale starts or ends. |
| 124 | * |
| 125 | * This function sets the X-Nitro-Expire header to the earliest future date |
| 126 | * based on the sale start or end date. It ensures that the cache is |
| 127 | * appropriately purged to reflect the changes in sale status. |
| 128 | */ |
| 129 | public function purge_site_cache_on_sale_start_and_end() { |
| 130 | $sale_dates = get_transient('nitropack_sale_product_dates'); |
| 131 | if ($sale_dates === false) return; |
| 132 | |
| 133 | $current_time = time(); |
| 134 | $valid_timestamps = []; |
| 135 | foreach ($sale_dates as $product_id => $dates) { |
| 136 | $timestamps = []; |
| 137 | |
| 138 | if (isset($dates['from']) && $dates['from'] >= $current_time) { |
| 139 | $timestamps[] = $dates['from']; |
| 140 | } |
| 141 | |
| 142 | if (isset($dates['to']) && $dates['to'] >= $current_time) { |
| 143 | $timestamps[] = $dates['to']; |
| 144 | } |
| 145 | |
| 146 | if (!empty($timestamps)) { |
| 147 | // Use the earliest timestamp that is greater than or equal to the current time |
| 148 | $valid_timestamps[$product_id] = min($timestamps); |
| 149 | } |
| 150 | } |
| 151 | |
| 152 | // Find the earliest date from the valid timestamps |
| 153 | if (!empty($valid_timestamps)) { |
| 154 | $earliest_key = array_search(min($valid_timestamps), $valid_timestamps); |
| 155 | $earliest_date = $valid_timestamps[$earliest_key]; |
| 156 | |
| 157 | |
| 158 | $this->add_cache_expiration($earliest_date); |
| 159 | } |
| 160 | } |
| 161 | /** |
| 162 | * Retrieves all products that have sale dates. |
| 163 | * |
| 164 | * @return array An array of products that are currently on sale. |
| 165 | */ |
| 166 | public function get_products_with_sale() { |
| 167 | |
| 168 | $product_ids = []; |
| 169 | $args = array( |
| 170 | 'post_type' => array('product', 'product_variation'), |
| 171 | 'post_status' => 'publish', |
| 172 | 'posts_per_page' => -1, |
| 173 | 'meta_query' => array( |
| 174 | 'relation' => 'OR', |
| 175 | array( |
| 176 | 'key' => '_sale_price_dates_from', |
| 177 | 'value' => time(), |
| 178 | 'compare' => '>=', |
| 179 | 'type' => 'NUMERIC', |
| 180 | ), |
| 181 | array( |
| 182 | 'key' => '_sale_price_dates_to', |
| 183 | 'value' => time(), |
| 184 | 'compare' => '>=', |
| 185 | 'type' => 'NUMERIC', |
| 186 | ), |
| 187 | ), |
| 188 | ); |
| 189 | |
| 190 | $query = new \WP_Query($args); |
| 191 | |
| 192 | if ($query->have_posts()) { |
| 193 | while ($query->have_posts()) { |
| 194 | global $post; |
| 195 | $query->the_post(); |
| 196 | $product_ids[] = $post->ID; |
| 197 | } |
| 198 | } |
| 199 | wp_reset_postdata(); |
| 200 | |
| 201 | return $product_ids; |
| 202 | } |
| 203 | } |
| 204 |