PluginProbe ʕ •ᴥ•ʔ
ShopPress – Shop Builder for Elementor and WooCommerce / trunk
ShopPress – Shop Builder for Elementor and WooCommerce vtrunk
shop-press / Modules / FlashSalesCountdown.php
shop-press / Modules Last commit date
VariationSwatches 1 week ago Wishlist 1 week ago AdminMessage.php 1 week ago AjaxSearch.php 1 week ago Backorder.php 1 week ago CatalogMode.php 1 year ago Compare.php 1 week ago DefaultTemplates.php 2 years ago FlashSalesCountdown.php 1 year ago MenuCart.php 4 months ago MobilePanel.php 1 week ago MultiStep.php 1 year ago Notifications.php 1 week ago QuickView.php 1 week ago RecentlyViewedProducts.php 1 year ago RenameLabel.php 4 months ago Shopify.php 1 year ago SingleAjaxAddToCart.php 1 week ago SizeChart.php 1 week ago StickyAddToCart.php 1 week ago
FlashSalesCountdown.php
522 lines
1 <?php
2 /**
3 * Flash Sale Countdown.
4 *
5 * @package ShopPress
6 */
7
8 namespace ShopPress\Modules;
9
10 defined( 'ABSPATH' ) || exit;
11
12 class FlashSalesCountdown {
13 /**
14 * Init.
15 *
16 * @since 1.2.0
17 */
18 public static function init() {
19 if ( ! sp_get_module_settings( 'flash_sale_countdown', 'status' ) ) {
20 return;
21 }
22
23 add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue_scripts' ), 99 );
24 $position = sp_get_module_settings( 'flash_sale_countdown', 'position' )['value'] ?? '';
25 if ( ! empty( $position ) && false === sp_is_template_active( 'single' ) ) {
26 add_action( $position, array( __CLASS__, 'fc_countdown_html' ) );
27 }
28 add_filter( 'woocommerce_get_price_html', array( __CLASS__, 'fs_label_price' ), 10, 2 );
29 add_action( 'woocommerce_product_variation_get_price', array( __CLASS__, 'fsc_product_variation_get_price' ), 10, 2 );
30 add_filter( 'woocommerce_product_variation_get_sale_price', array( __CLASS__, 'fsc_product_variation_get_price' ), 10, 2 );
31 add_filter( 'woocommerce_variation_prices_price', array( __CLASS__, 'fsc_product_variation_get_price' ), 10, 2 );
32 add_filter( 'woocommerce_variation_prices_sale_price', array( __CLASS__, 'fsc_product_variation_get_price' ), 10, 2 );
33 add_filter( 'woocommerce_product_get_price', array( __CLASS__, 'fsc_product_get_price' ), 10, 2 );
34 add_filter( 'woocommerce_product_get_sale_price', array( __CLASS__, 'fsc_product_get_price' ), 10, 2 );
35 add_filter( 'shoppress/elementor/widgets', array( __CLASS__, 'add_flash_sale_widgets' ), 9 );
36
37 add_filter( 'shoppress/product-loop/collections', array( __CLASS__, 'filter_products_loop_collections' ), 10, 2 );
38 add_action( 'shoppress/elementor/widget/products_loop/section_content/end', array( __CLASS__, 'add_control_to_products_loop_widget' ) );
39 }
40
41 /**
42 * Adds the flash sale widgets to the existing list of widgets.
43 *
44 * @param array $widgets The array of widgets.
45 *
46 * @since 1.2.0
47 *
48 * @return array The updated array of widgets.
49 */
50 public static function add_flash_sale_widgets( $widgets ) {
51
52 $widgets['loop-flash-sale-countdown'] = array(
53 'editor_type' => 'loop',
54 'class_name' => 'LoopBuilder\FlashSalesCountdown',
55 'is_pro' => false,
56 'path_key' => 'loop/flash-sale-countdown',
57 );
58
59 $widgets['single-flash-sale-countdown'] = array(
60 'editor_type' => 'single',
61 'class_name' => 'FlashSalesCountdown',
62 'is_pro' => false,
63 'path_key' => 'single-product/flash-sale-countdown',
64 );
65
66 return $widgets;
67 }
68
69 /**
70 * Return sale events
71 *
72 * @param int $product_id
73 * @param bool $check_user
74 *
75 * @since 1.2.0
76 *
77 * @return array
78 */
79 public static function get_available_sale_events( $product_id = 0, $check_user = true ) {
80 $_sale_events = sp_get_module_settings( 'flash_sale_countdown', 'sale_events' );
81 $sale_events = array();
82 if ( ! is_array( $_sale_events ) ) {
83 return $sale_events;
84 }
85
86 $user_id = get_current_user_id();
87 if ( $user_id ) {
88 $user = get_userdata( $user_id );
89 $user_roles = $user->roles;
90 }
91
92 if ( $product_id ) {
93
94 $product = wc_get_product( $product_id );
95 $parent_id = $product->get_parent_id();
96 $product_id = $parent_id ? $parent_id : $product_id;
97 }
98
99 foreach ( $_sale_events as $key => $sale_event ) {
100
101 $status = $sale_event['event_enable'] ?? false;
102 if ( empty( $sale_event ) || ! $status ) {
103 continue;
104 }
105
106 $product_categories_operator = $sale_event['event_product_categories_operator']['value'] ?? 'all';
107 $sale_event['event_product_categories_operator'] = $product_categories_operator;
108 $sale_event['event_product_categories'] = isset( $sale_event['event_product_categories'] ) && is_array( $sale_event['event_product_categories'] ) ? array_column( $sale_event['event_product_categories'], 'value' ) : array();
109
110 $products_operator = $sale_event['event_products_operator']['value'] ?? 'all';
111 $sale_event['event_products_operator'] = $products_operator;
112 $sale_event['event_products'] = isset( $sale_event['event_products'] ) && is_array( $sale_event['event_products'] ) ? array_column( $sale_event['event_products'], 'value' ) : array();
113
114 $event_apply_user_roles = $sale_event['event_apply_user_roles'] ?? false;
115 $sale_event['event_apply_user_roles'] = is_array( $event_apply_user_roles ) ? array_column( $event_apply_user_roles, 'value' ) : array();
116
117 $discount_type = $sale_event['event_discount_type']['value'] ?? '';
118 $sale_event['event_discount_type'] = $discount_type;
119 $discount_value = $sale_event['event_discount_value'] ?? false;
120 if ( ! $discount_type || ! $discount_value ) {
121 continue;
122 }
123
124 $current_timestamp = current_time( 'timestamp' );
125 $event_valid_from = $sale_event['event_valid_from'] ?? false;
126 if ( ! $event_valid_from || strtotime( $event_valid_from . ' 00:00' ) > $current_timestamp ) {
127 continue;
128 }
129
130 $event_valid_to = $sale_event['event_valid_to'] ?? false;
131 if ( ! $event_valid_to || strtotime( $event_valid_to . ' 23:59:59' ) < $current_timestamp ) {
132 continue;
133 }
134
135 if ( $product_id ) {
136
137 $product_category_ids = wp_get_post_terms( $product_id, 'product_cat', array( 'fields' => 'ids' ) );
138 $product_categories_intersect = array_intersect( $product_category_ids, $sale_event['event_product_categories'] );
139
140 if (
141 ! empty( $sale_event['event_product_categories'] )
142 &&
143 (
144 ( 'include' == $product_categories_operator && empty( $product_categories_intersect ) )
145 ||
146 ( 'exclude' == $product_categories_operator && ! empty( $product_categories_intersect ) )
147 )
148 ) {
149 continue;
150 }
151
152 if (
153 ! empty( $sale_event['event_products'] )
154 &&
155 (
156 ( 'include' == $products_operator && ! in_array( $product_id, $sale_event['event_products'] ) )
157 ||
158 ( 'exclude' == $products_operator && in_array( $product_id, $sale_event['event_products'] ) )
159 )
160 ) {
161 continue;
162 }
163 }
164
165 if ( $check_user ) {
166
167 $event_apply_discount_registered = $sale_event['event_apply_discount_registered'] ?? false;
168 if ( $event_apply_discount_registered && ! is_user_logged_in() ) {
169 continue;
170 }
171
172 if ( ! empty( $sale_event['event_apply_user_roles'] ) ) {
173
174 if ( ! is_user_logged_in() ) {
175
176 continue;
177 }
178
179 if ( empty( array_intersect( $sale_event['event_apply_user_roles'], $user_roles ) ) ) {
180
181 continue;
182 }
183 }
184 }
185
186 $sale_events[ $key ] = $sale_event;
187 }
188
189 return $sale_events;
190 }
191
192 /**
193 * Return sale events
194 *
195 * @param int $product_id
196 * @param bool $check_user
197 *
198 * @since 1.2.0
199 *
200 * @return array|false
201 */
202 public static function get_available_sale_event( $product_id = 0, $check_user = true ) {
203
204 $sale_events = static::get_available_sale_events( $product_id, $check_user );
205
206 return is_array( $sale_events ) && count( $sale_events ) ? current( $sale_events ) : false;
207 }
208
209 /**
210 * Return flash sale product price
211 *
212 * @param \WC_Product $product
213 * @param array $sale_event
214 *
215 * @since 1.2.0
216 *
217 * @return int|float
218 */
219 public static function get_flash_sale_price( $product, $sale_event, $price = '', $price_type = 'regular' ) {
220
221 $product_id = $product->get_id();
222
223 return static::get_price(
224 sp_get_module_settings( 'flash_sale_countdown', 'override_sale_price' ),
225 $sale_event['event_discount_type'],
226 $sale_event['event_discount_value'],
227 $product_id,
228 $price
229 );
230 }
231
232 /**
233 * Change Label Price.
234 *
235 * @param $html
236 * @param $product
237 *
238 * @since 1.1.2
239 *
240 * @return string
241 */
242 public static function fs_label_price( $html, $product ) {
243 $product_id = $product->get_id();
244
245 $sale_event = static::get_available_sale_event( $product_id );
246 if ( empty( $sale_event ) ) {
247 return $html;
248 }
249
250 $flash_sale_price = '';
251
252 if ( ! $product->is_type( 'variable' ) && ! $product->is_type( 'grouped' ) ) {
253 $flash_sale_price = wc_price( static::get_flash_sale_price( $product, $sale_event ) );
254 }
255
256 $manage_price_label = '<span class="sp-fsc-price-main">' . $html . '</span>';
257
258 if ( is_admin() ) {
259 return $flash_sale_price;
260 } elseif ( empty( $manage_price_label ) ) {
261 return $flash_sale_price;
262 } else {
263 return $manage_price_label;
264 }
265 }
266
267 /**
268 * fsc Product Variation get Price.
269 *
270 * @param $price
271 * @param $product
272 *
273 * @since 1.1.2
274 *
275 * @return string
276 */
277 public static function fsc_product_variation_get_price( $price, $product ) {
278 $product_id = $product->get_id();
279
280 $sale_event = static::get_available_sale_event( $product_id );
281 if ( empty( $sale_event ) ) {
282 return $price;
283 }
284
285 return static::get_flash_sale_price( $product, $sale_event, $price );
286 }
287
288 /**
289 * fc Countdown Html.
290 *
291 * @since 1.1.2
292 *
293 * @return void
294 */
295 public static function fc_countdown_html() {
296
297 if ( ! is_product() ) {
298 return;
299 }
300
301 if ( ! sp_get_module_settings( 'flash_sale_countdown', 'show_product_page' ) ) {
302 return;
303 }
304
305 global $shoppress_sticky_add_to_cart;
306 if ( $shoppress_sticky_add_to_cart ) {
307 return;
308 }
309
310 $atts = array(
311 'title' => sp_get_module_settings( 'flash_sale_countdown', 'timer_title' ),
312 );
313 global $product;
314 static::display_countdown( $product, $atts );
315 }
316
317 /**
318 * Return Countdown Html.
319 *
320 * @param \WC_Product $product
321 *
322 * @since 1.2.0
323 *
324 * @return void
325 */
326 public static function display_countdown( $product = null, $atts = array() ) {
327
328 $title = $atts['title'] ?? '';
329 $product = ! is_null( $product ) ? $product : $GLOBALS['product'];
330 $product_id = $product->get_id();
331
332 $sale_event = static::get_available_sale_event( $product_id );
333 if ( empty( $sale_event ) ) {
334 return;
335 }
336
337 $time_end = $sale_event['event_valid_to'];
338 if ( $time_end ) :
339 ?>
340 <div class="fs-countdown-wrapper">
341 <?php if ( $title ) : ?>
342 <h6 class="fs-countdown-title"><?php echo wp_kses_post( $title ); ?></h6>
343 <?php endif; ?>
344 <div class="fs-countdown" data-timeend="<?php echo esc_attr( $time_end ); ?>"></div>
345 </div>
346 <?php
347 endif;
348 }
349
350 /**
351 * fsc Product Get Price.
352 *
353 * @param $price
354 * @param $product
355 *
356 * @since 1.1.2
357 *
358 * @return string
359 */
360 public static function fsc_product_get_price( $price, $product ) {
361 $product_id = $product->get_id();
362
363 $sale_event = static::get_available_sale_event( $product_id );
364 if ( empty( $sale_event ) ) {
365 return $price;
366 }
367
368 return static::get_flash_sale_price( $product, $sale_event, $price );
369 }
370
371 /**
372 * Get Variable Price.
373 *
374 * @param $product
375 * @param $override_price
376 * @param $discount_type
377 * @param $discount_value
378 * @param $price
379 *
380 * @since 1.1.2
381 *
382 * @return float|int
383 */
384 public static function get_variable_price( $product, $override_price, $discount_type, $discount_value, $price ) {
385 $base_price = (float) $product->get_regular_price();
386 if ( $override_price ) {
387 $base_price = (float) $price;
388 }
389
390 $flash_sale_price = 0;
391 if ( $discount_type == 'percentage_discount' ) {
392 $flash_sale_price = ( 1 - (float) $discount_value / 100 ) * $base_price;
393 } elseif ( $discount_type == 'fixed_discount' ) {
394 $flash_sale_price = $base_price - (float) $discount_value;
395 } elseif ( $discount_type == 'fixed_price' ) {
396 $flash_sale_price = (float) $discount_value;
397 }
398 return $flash_sale_price;
399 }
400
401 /**
402 * Calculate Price By Discount.
403 *
404 * @param string $product_id
405 * @param $override_price
406 * @param $discount_type
407 * @param $discount_value
408 * @param string $price
409 *
410 * @since 1.1.2
411 *
412 * @return float|int
413 */
414 public static function get_price( $override_price, $discount_type, $discount_value, $product_id = '', $price = '' ) {
415 $regular = get_post_meta( $product_id, '_regular_price', true );
416 $sale = get_post_meta( $product_id, '_sale_price', true );
417
418 $base_price = (float) $regular;
419
420 if ( $override_price && $sale ) {
421 $base_price = (float) $sale;
422 }
423
424 if ( $price ) {
425 $base_price = (float) $price;
426 }
427
428 $flash_sale_price = 0;
429 if ( $discount_type == 'percentage_discount' ) {
430 $flash_sale_price = ( 1 - (float) $discount_value / 100 ) * $base_price;
431 } elseif ( $discount_type == 'fixed_discount' ) {
432 $discount_value = (float) $discount_value;
433 if ( $base_price > $discount_value ) {
434 $flash_sale_price = $base_price - $discount_value;
435 } else {
436 $flash_sale_price = 0;
437 }
438 } elseif ( $discount_type == 'fixed_price' ) {
439 $flash_sale_price = (float) $discount_value;
440 }
441 return $flash_sale_price;
442 }
443
444 /**
445 * enqueue scripts.
446 *
447 * @since 1.1.2
448 */
449 public static function enqueue_scripts() {
450 // if ( is_product() ) {
451 wp_enqueue_script( 'sp-flash-sale-countdown' );
452 wp_enqueue_style( 'sp-flash-sale-countdown' );
453
454 if ( is_rtl() ) {
455 return array( 'sp-flash-sale-countdown-rtl' );
456 }
457 // }
458 }
459
460 /**
461 * Return list sales events
462 *
463 * @since 1.3.5
464 *
465 * @return array
466 */
467 public static function get_list_sale_events() {
468 $sale_events = self::get_available_sale_events( 0, false );
469 $sale_events_options = array();
470
471 foreach ( $sale_events as $id => $value ) {
472
473 $sale_events_options[ $id ] = $value['event_name'];
474 }
475
476 return $sale_events_options;
477 }
478
479 /**
480 * Filter products loop collections
481 *
482 * @param array $collections
483 * @param ProductLoop $class
484 *
485 * @since 1.3.5
486 *
487 * @return array
488 */
489 public static function filter_products_loop_collections( $collections, $class ) {
490
491 $collections['sp-flash-sales-products'] = __( 'Flash Sales', 'shop-press' );
492
493 return $collections;
494 }
495
496 /**
497 * Add control to products loop widget
498 *
499 * @param ProductLoop $class
500 *
501 * @since 1.3.5
502 *
503 * @return void
504 */
505 public static function add_control_to_products_loop_widget( $class ) {
506
507 $sale_events = self::get_list_sale_events();
508 $class->add_control(
509 'flash_sale',
510 array(
511 'label' => esc_html__( 'Select Flash Sale', 'shop-press' ),
512 'type' => \Elementor\Controls_Manager::SELECT,
513 'options' => $sale_events,
514 'default' => key( $sale_events ),
515 'condition' => array(
516 'product_collection' => 'sp-flash-sales-products',
517 ),
518 )
519 );
520 }
521 }
522