PluginProbe
HurryTimer – An Scarcity and Urgency Countdown Timer for WordPress & WooCommerce / 2.2.16
HurryTimer – An Scarcity and Urgency Countdown Timer for WordPress & WooCommerce v2.2.16
2.15.0 trunk 1.0.0 1.0.1 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.1.2 2.1.3 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 All 62 releases
← All changes | includes/Campaign.php +672 -177 2.0.42.2.16 View file →
@@ -1,9 +1,11 @@
1 1 <?php
2 2
3 3 namespace Hurrytimer;
4 4
5 -use \Hurrytimer\Utils\Helpers;
5 +use Carbon\Carbon;
6 +use Carbon\CarbonPeriod;
7 +use Hurrytimer\Utils\Helpers;
6 8
7 9 class Campaign
8 10 {
9 11
@@ -32,8 +34,73 @@
32 34 */
33 35 public $duration;
34 36
35 37 /**
38 + * Recurrence duration
39 + *
40 + * @var int
41 + */
42 + public $recurringDuration;
43 +
44 + /**
45 + * Recurrence start date/time
46 + *
47 + * @var string
48 + */
49 + public $recurringStartTime;
50 +
51 + /**
52 + * Recurrence end option
53 + *
54 + * @var int
55 + */
56 + public $recurringEnd = C::RECURRING_END_NEVER;
57 +
58 + /**
59 + * Recurrence frequency
60 + *
61 + * @see C
62 + * @var string
63 + */
64 + public $recurringFrequency = C::RECURRING_DAILY;
65 +
66 + /**
67 + * Recurrence interval
68 + *
69 + * @var int
70 + */
71 + public $recurringInterval = 1;
72 +
73 + /**
74 + * Recurrence count
75 + *
76 + * @var int
77 + */
78 + public $recurringCount = 2;
79 +
80 + /**
81 + * Recurrence end date/time
82 + *
83 + * @var
84 + */
85 + public $recurringUntil;
86 +
87 + /**
88 + * Recurrence allowed days
89 + *
90 + * @var array
91 + */
92 + public $recurringDays = [ 0, 1, 2, 3, 4, 5, 6 ];
93 +
94 + /**
95 + * Recurrence timezone
96 + *
97 + * @todo Not used
98 + * @var mixed|string|void
99 + */
100 + public $recurringTimezone;
101 +
102 + /**
36 103 * Restart option after expiration.
37 104 *
38 105 * @see \Hurrytimer\CampaignRestart
39 106 *
@@ -45,9 +112,9 @@
45 112 * Headline text.
46 113 *
47 114 * @var string
48 115 */
49 - public $headline;
116 + public $headline = "Hurry Up!";
50 117
51 118 /**
52 119 * Headline color.
53 120 *
@@ -59,9 +126,9 @@
59 126 * Headline size.
60 127 *
61 128 * @var int
62 129 */
63 - public $headlineSize = 16;
130 + public $headlineSize = 30;
64 131
65 132 /**
66 133 * Headline position.
67 134 *
@@ -75,8 +142,10 @@
75 142 * @var boolean
76 143 */
77 144 public $headlineVisibility = C::YES;
78 145
146 + public $headlineSpacing = 5;
147 +
79 148 /**
80 149 * Control labels visibility.
81 150 *
82 151 * @var string
@@ -123,14 +192,14 @@
123 192 *
124 193 * @var array
125 194 */
126 195 public $labels
127 - = [
128 - 'days' => 'days',
129 - 'hours' => 'hrs',
130 - 'minutes' => 'mins',
131 - 'seconds' => 'secs',
132 - ];
196 + = [
197 + 'days' => 'days',
198 + 'hours' => 'hrs',
199 + 'minutes' => 'mins',
200 + 'seconds' => 'secs',
201 + ];
133 202
134 203 /**
135 204 * Digit color.
136 205 *
@@ -142,9 +211,9 @@
142 211 * Digit size.
143 212 *
144 213 * @var int
145 214 */
146 - public $digitSize = 25;
215 + public $digitSize = 35;
147 216
148 217 /**
149 218 * Redirect action url.
150 219 *
@@ -200,8 +269,10 @@
200 269 * @var int
201 270 */
202 271 public $wcProductsSelectionType;
203 272
273 + public $wcConditions;
274 +
204 275 /**
205 276 * Timer block border color.
206 277 *
207 278 * @var string
@@ -263,17 +334,143 @@
263 334 * Label case
264 335 *
265 336 * @var string
266 337 */
267 - public $labelCase = C::TRANSFORM_LOWERCASE;
338 + public $labelCase = C::TRANSFORM_UPPERCASE;
268 339
340 + /**
341 + * Custom CSS
342 + *
343 + * @var string
344 + */
269 345 public $customCss = '';
270 346
271 - public function __construct($id)
347 + /**
348 + * Block elements display
349 + * Values: block, inline
350 + *
351 + * @var string
352 + */
353 + public $blockDisplay = 'block';
354 +
355 + /**
356 + * Enable sticky bar.
357 + */
358 + public $enableSticky = C::NO;
359 +
360 + /**
361 + * Sticky bar background color.
362 + *
363 + * @var string
364 + */
365 + public $stickyBarBgColor = '#eee';
366 +
367 + /**
368 + * Sticky bar close button color.
369 + *
370 + * @var string
371 + */
372 + public $stickyBarCloseBtnColor = '#fff';
373 +
374 + /**
375 + * Sticky bar position.
376 + * Values: top, bottom
377 + *
378 + * @var string
379 + */
380 + public $stickyBarPosition = 'top';
381 +
382 + /**
383 + * Sticky bar padding.
384 + *
385 + * @var integer
386 + */
387 + public $stickyBarPadding = 5;
388 +
389 + /**
390 + * Sticky bar display pages.
391 + *
392 + * @var array
393 + */
394 + public $stickyBarPages = [];
395 +
396 + /**
397 + * Where to display the sticky bar option
398 + *
399 + * @var string
400 + */
401 + public $stickyBarDisplayOn = 'all_pages';
402 +
403 + /**
404 + * Show sticky bar close button?
405 + *
406 + * @var string
407 + */
408 + public $stickyBarDismissible = C::YES;
409 +
410 + /**
411 + * CTA settings.
412 + *
413 + * @var array
414 + */
415 + public $callToAction
416 + = [
417 + 'enabled' => C::NO,
418 + 'new_tab' => C::NO,
419 + 'url' => '',
420 + 'text' => 'Learn More',
421 + 'text_size' => 15,
422 + 'text_color' => '#fff',
423 + 'bg_color' => '#000',
424 + 'y_padding' => 10,
425 + 'x_padding' => 15,
426 + 'border_radius' => 3,
427 + 'spacing' => 5,
428 + ];
429 +
430 + /**
431 + * Campaign elements display
432 + * values: block,inline
433 + *
434 + * @var string
435 + */
436 + public $campaignDisplay = 'block';
437 +
438 + /**
439 + * Campaign aligments
440 + * values: center,left,right
441 + *
442 + * @var string
443 + */
444 + public $campaignAlign = 'center';
445 +
446 + /**
447 + * Campaign spacing.
448 + *
449 + * @var integer
450 + */
451 + public $campaignSpacing = 10;
452 +
453 + /**
454 + * Campaign horizontal padding.
455 + *
456 + * @var integer
457 + */
458 + public $campaignXPadding = 10;
459 +
460 + /**
461 + * Campaign vertical padding.
462 + *
463 + * @var integer
464 + */
465 + public $campaignYPadding = 10;
466 +
467 + public function __construct( $id )
272 468 {
273 -
274 - $this->id = $id;
275 - //$this->loadSettings();
469 + // Default recurring timezone.
470 + $this->recurringTimezone = Utils\Helpers::getSiteTimezone();
471 + $this->recurringStartTime = Carbon::now( hurryt_tz() )->format( 'Y-m-d h:i A' );
472 + $this->id = $id;
276 473 }
277 474
278 475 /**
279 476 * Returns compaign post iD.
@@ -284,8 +481,71 @@
284 481 {
285 482 return $this->id;
286 483 }
287 484
485 + public function showStickyBarOn( $pageId )
486 + {
487 + if ( $this->enableSticky === C::NO ) {
488 + return true;
489 + }
490 +
491 + $can_show = false;
492 + switch ( $this->getStickyBarDisplayOn() ) {
493 + case 'all_pages':
494 + $can_show = true;
495 + break;
496 + case 'wc_products_pages':
497 + if ( function_exists( 'is_product' ) && is_product() ) {
498 + $wc_campaign = new WCCampaign();
499 + $can_show = ( $wc_campaign->hasActiveCampaign( $this, $pageId ) );
500 + } else {
501 + $can_show = false;
502 + }
503 + break;
504 + case 'specific_pages':
505 + $pages = $this->getStickyBarPages();
506 + $can_show = in_array( $pageId, $pages );
507 + break;
508 + }
509 +
510 + return apply_filters( 'hurryt_show_sticky_bar', $can_show, $this->getId() );
511 +
512 + }
513 +
514 + public function getStickyBarPages()
515 + {
516 + $pagesIds = $this->getRawSetting( 'sticky_bar_pages' );
517 +
518 + return array_filter( array_map( 'intval', $pagesIds ) );
519 + }
520 +
521 + public function setStickyBarPages( $value )
522 + {
523 + $this->storeRawSetting( 'sticky_bar_pages', $value );
524 + }
525 +
526 + public function getStickyBarDisplayOn()
527 + {
528 +
529 + // backward compat.
530 + $all_pages = $this->getRawSetting( 'sticky_bar_show_on_all_pages', false );
531 +
532 + if ( $all_pages === C::YES ) {
533 + $this->setStickyBarDisplayOn( 'all_pages' );
534 + }
535 +
536 + $this->deleteRawSetting( 'sticky_bar_show_on_all_pages' );
537 +
538 + $value = $this->getRawSetting( '_hurryt_sticky_bar_display_on', false );
539 +
540 + return ! empty( $value ) ? $value : $this->stickyBarDisplayOn;
541 + }
542 +
543 + public function setStickyBarDisplayOn( $value )
544 + {
545 + $this->storeRawSetting( '_hurryt_sticky_bar_display_on', $value );
546 + }
547 +
288 548 /**
289 549 * Get raw setting.
290 550 *
291 551 * @param string $name
@@ -292,25 +552,30 @@
292 552 * @param boolean
293 553 *
294 554 * @return mixed
295 555 */
296 - public function getRawSetting($name, $useDefault = true)
556 + public function getRawSetting( $name, $useDefault = true )
297 557 {
298 - $value = get_post_meta($this->id, $name, true);
299 - if (!empty($value)) {
558 + $value = get_post_meta( $this->id, $name, true );
559 + if ( ! empty( $value ) ) {
300 560 return $value;
301 561 }
302 - if ($useDefault) {
303 - return $this->{Helpers::snakeToCamelCase($name)};
562 + if ( $useDefault ) {
563 + return $this->{Helpers::snakeToCamelCase( $name )};
304 564 }
305 565
306 566 return $value;
307 567 }
308 568
309 - public function storeRawSetting($name, $value)
569 + public function storeRawSetting( $name, $value )
310 570 {
311 - $value = !empty($value) ? $value : $this->{Helpers::snakeToCamelCase($name)};
312 - update_post_meta($this->id, $name, $value);
571 + $value = ! empty( $value ) ? $value : '';
572 + $getterMethod = Helpers::snakeToCamelCase( $name );
573 + if ( empty( $value ) && method_exists( $this, $getterMethod ) ) {
574 + $value = $this->{$getterMethod}();
575 + }
576 +
577 + update_post_meta( $this->id, $name, $value );
313 578 }
314 579
315 580 /**
316 581 * Bulk save for compaign settings.
@@ -316,54 +581,79 @@
316 581 * Bulk save for compaign settings.
317 582 *
318 583 * @param $data
319 584 */
320 - public function storeSettings($data)
585 + public function storeSettings( $data )
321 586 {
322 - foreach ($data as $prop => $value) {
323 - $method = Helpers::snakeToCamelCase("set_{$prop}");
324 - if (method_exists($this, $method)) {
325 - $this->$method($value ?: $this->$prop);
326 - } elseif (property_exists(__CLASS__, Helpers::snakeToCamelCase($prop))) {
327 - $this->storeRawSetting($prop, $value);
587 + foreach ( $data as $prop => $value ) {
588 + $method = Helpers::snakeToCamelCase( "set_{$prop}" );
589 + if ( method_exists( $this, $method ) ) {
590 + $this->$method( $value ?: $this->$prop );
591 + } elseif ( property_exists( __CLASS__, Helpers::snakeToCamelCase( $prop ) ) ) {
592 + $this->storeRawSetting( $prop, $value );
328 593 }
329 594 }
330 -
595 + if ( ! isset( $data[ 'wc_conditions' ] ) ) {
596 + $this->setWcConditions( [] );
597 + }
598 + if ( ! isset( $data[ 'sticky_bar_pages' ] ) ) {
599 + $this->setStickyBarPages( [] );
600 + }
331 601 self::buildCss();
332 602 }
333 603
604 + //removeIf(pro)
334 605 /**
335 - * Build CSS file,
336 - * Then merge it with default one.
606 + * @param int $mode
607 + */
608 + public function setMode($mode)
609 + {
610 + if($mode == C::MODE_RECURRING){
611 + return;
612 + }
613 + $this->storeRawSetting('mode',$mode);
614 + }
615 + //endRemoveIf(pro)
616 + /**
617 + * Build User CSS,
618 + * Then merge it with base one.
337 619 *
338 620 * @return void
339 621 */
340 - static public function buildCss()
622 + public static function buildCss()
341 623 {
342 624
625 + // Build and return CSS
343 626 ob_start();
344 627 include HURRYT_DIR . 'includes/css.php';
345 - $css = ob_get_clean();
346 - $base = file_get_contents(HURRYT_DIR . '/assets/css/base.css');
628 + $css = ob_get_clean();
629 + $base = file_get_contents( HURRYT_DIR . '/assets/css/base.css' );
630 +
631 + // Merge built and base css.
347 632 $base .= $css;
348 - file_put_contents(HURRYT_DIR . '/assets/css/hurrytimer.css', $base);
633 +
634 + // Save to public file.
635 + file_put_contents( HURRYT_DIR . '/assets/css/hurrytimer.css', $base );
349 636 }
350 637
351 - /**
352 - * Load settings from database,
353 - * and set object props according their matched name.
354 - */
638 + private function setRecurringDates( $dates )
639 + {
640 + foreach ( $dates as $d ) {
641 + add_post_meta( $this->getId(), '_hurryt_recurring_dates', $d );
642 + }
643 + }
644 +
355 645 public function loadSettings()
356 646 {
357 647
358 - $reflection = new \ReflectionObject($this);
359 - foreach ($reflection->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) {
360 - $name = $prop->getName();
361 - $method = 'get' . ucfirst($name);
362 - if (method_exists($this, $method)) {
648 + $reflection = new \ReflectionObject( $this );
649 + foreach ( $reflection->getProperties( \ReflectionProperty::IS_PUBLIC ) as $prop ) {
650 + $name = $prop->getName();
651 + $method = 'get' . ucfirst( $name );
652 + if ( method_exists( $this, $method ) ) {
363 653 $this->{$name} = $this->$method();
364 654 } else {
365 - $this->{$name} = $this->getRawSetting(Helpers::camelToSnakeCase($name));
655 + $this->{$name} = $this->getRawSetting( Helpers::camelToSnakeCase( $name ) );
366 656 }
367 657 }
368 658 }
369 659
@@ -373,14 +663,14 @@
373 663 * @return mixed
374 664 */
375 665 public function getHeadline()
376 666 {
377 - return get_the_title($this->id);
667 + return $this->id ? get_the_title( $this->id ) : $this->headline;
378 668 }
379 669
380 670 public function isPublished()
381 671 {
382 - return get_post_status($this->id) === "publish";
672 + return get_post_status( $this->id ) === "publish";
383 673 }
384 674
385 675 public function isWcEnabled()
386 676 {
@@ -393,24 +683,30 @@
393 683 * @return bool
394 684 */
395 685 public function isEvergreen()
396 686 {
397 - return $this->getRawSetting('mode') == C::MODE_EVERGREEN;
687 + return $this->getRawSetting( 'mode' ) == C::MODE_EVERGREEN;
398 688 }
399 689
400 690 public function isRegular()
401 691 {
402 - return $this->getRawSetting('mode') == C::MODE_REGULAR;
692 + return $this->getRawSetting( 'mode' ) == C::MODE_REGULAR;
403 693 }
404 694
695 + public function isRecurring()
696 + {
697 + return $this->getRawSetting( 'mode' ) == C::MODE_RECURRING;
698 +
699 + }
700 +
405 701 /**
406 702 * Save compaign endtime for regular mode.
407 703 *
408 704 * @param $date
409 705 */
410 - public function setEndDatetime($date)
706 + public function setEndDatetime( $date )
411 707 {
412 - $this->storeRawSetting('end_datetime', $date ?: $this->defaultEndDatetime());
708 + $this->storeRawSetting( 'end_datetime', $date ?: $this->defaultEndDatetime() );
413 709 }
414 710
415 711 /**
416 712 * Returns default end datetime for regular mode.
@@ -418,9 +714,9 @@
418 714 * @return false|string
419 715 */
420 716 private function defaultEndDatetime()
421 717 {
422 - return date('Y-m-d h:i A', strtotime('+1 week'));
718 + return date( 'Y-m-d h:i A', strtotime( '+1 week' ) );
423 719 }
424 720
425 721 /**
426 722 * Save digit color.
@@ -426,11 +722,11 @@
426 722 * Save digit color.
427 723 *
428 724 * @param $color
429 725 */
430 - public function setDigitColor($color)
726 + public function setDigitColor( $color )
431 727 {
432 - $this->storeRawSetting('digit_color', $color);
728 + $this->storeRawSetting( 'digit_color', $color );
433 729 }
434 730
435 731 /**
436 732 * Returns headline visibility.
@@ -441,22 +737,23 @@
441 737 public function getHeadlineVisibility()
442 738 {
443 739 $meta = 'headline_visibility';
444 740
445 - $value = $this->getRawSetting($meta, false);
446 - if ($value === C::NO || $value === C::YES) {
741 + $value = $this->getRawSetting( $meta, false );
742 + if ( $value === C::NO || $value === C::YES ) {
447 743 return $value;
448 744 }
449 745
450 - $legacyMeta = 'display_headline';
451 - $legacyValue = filter_var($this->getLegacySetting($legacyMeta), FILTER_VALIDATE_BOOLEAN);
746 + $legacyMeta = 'display_headline';
747 + $legacyValue = filter_var( $this->getLegacySetting( $legacyMeta ),
748 + FILTER_VALIDATE_BOOLEAN );
452 749 $legacyValue = $legacyValue ? C::YES : C::NO;
453 750
454 - $this->storeRawSetting($meta, $legacyValue);
751 + $this->storeRawSetting( $meta, $legacyValue );
455 752
456 - $this->deleteRawSetting($legacyMeta);
753 + $this->deleteRawSetting( $legacyMeta );
457 754
458 - return $this->getRawSetting($meta);
755 + return $this->getRawSetting( $meta );
459 756 }
460 757
461 758 /**
462 759 * Returns digit color.
@@ -465,31 +762,31 @@
465 762 * @return mixed
466 763 */
467 764 public function getDigitColor()
468 765 {
469 - $value = $this->getRawSetting('digit_color', false);
470 - if ($value) {
766 + $value = $this->getRawSetting( 'digit_color', false );
767 + if ( $value ) {
471 768 return $value;
472 769 }
473 770
474 - $legacy = $this->getLegacySetting('text_color');
475 - if (!$legacy) {
771 + $legacy = $this->getLegacySetting( 'text_color' );
772 + if ( ! $legacy ) {
476 773 return $this->digitColor;
477 774 }
478 775
479 - $this->setDigitColor($legacy);
480 - if (!$this->getRawSetting('label_color', false)) {
481 - $this->setLabelColor($legacy);
776 + $this->setDigitColor( $legacy );
777 + if ( ! $this->getRawSetting( 'label_color', false ) ) {
778 + $this->setLabelColor( $legacy );
482 779 }
483 780
484 - $this->deleteRawSetting('text_color');
781 + $this->deleteRawSetting( 'text_color' );
485 782
486 - return $this->getRawSetting('digit_color');
783 + return $this->getRawSetting( 'digit_color' );
487 784 }
488 785
489 - public function setLabelColor($color)
786 + public function setLabelColor( $color )
490 787 {
491 - $this->storeRawSetting('label_color', $color);
788 + $this->storeRawSetting( 'label_color', $color );
492 789 }
493 790
494 791 /**
495 792 * Get label color
@@ -497,56 +794,55 @@
497 794 * @return mixed
498 795 */
499 796 public function getLabelColor()
500 797 {
501 - $value = $this->getRawSetting('label_color', false);
502 - if ($value) {
798 + $value = $this->getRawSetting( 'label_color', false );
799 + if ( $value ) {
503 800 return $value;
504 801 }
505 802
506 - $legacy = $this->getLegacySetting('text_color');
507 - if (!$legacy) {
803 + $legacy = $this->getLegacySetting( 'text_color' );
804 + if ( ! $legacy ) {
508 805 return $this->labelColor;
509 806 }
510 807
511 - $this->setLabelColor($legacy);
512 - if (!$this->getRawSetting('digit_color', false)) {
513 - $this->setDigitColor($legacy);
808 + $this->setLabelColor( $legacy );
809 + if ( ! $this->getRawSetting( 'digit_color', false ) ) {
810 + $this->setDigitColor( $legacy );
514 811 }
515 812
516 - $this->deleteRawSetting('text_color');
813 + $this->deleteRawSetting( 'text_color' );
517 814
518 - return $this->getRawSetting('label_color');
815 + return $this->getRawSetting( 'label_color' );
519 816
520 817 }
521 818
522 -
523 819 /**
524 820 *
525 821 * Return timer digit size.
526 822 * Backward comapt. with older versions.
527 823 *
824 + * @return int
528 825 * @since 1.2.4
529 - * @return int
530 826 */
531 827 public function getDigitSize()
532 828 {
533 - $meta = 'digit_size';
534 - $value = $this->getRawSetting($meta, false);
535 - if (!empty($value)) {
829 + $meta = 'digit_size';
830 + $value = $this->getRawSetting( $meta, false );
831 + if ( ! empty( $value ) ) {
536 832 return $value;
537 833 }
538 - $legacy = $this->getLegacySetting('text_size');
834 + $legacy = $this->getLegacySetting( 'text_size' );
539 835
540 - if (empty($legacy)) {
836 + if ( empty( $legacy ) ) {
541 837 return $this->digitSize;
542 838 }
543 839
544 - $this->setDigitSize($legacy);
545 -
546 - $this->deleteRawSetting('text_size');
840 + $this->setDigitSize( $legacy );
547 841
548 - return $this->getRawSetting('digit_size');
842 + $this->deleteRawSetting( 'text_size' );
843 +
844 + return $this->getRawSetting( 'digit_size' );
549 845 }
550 846
551 847 /**
552 848 * Save timer digit size.
@@ -552,11 +848,11 @@
552 848 * Save timer digit size.
553 849 *
554 850 * @param $size
555 851 */
556 - public function setDigitSize($size)
852 + public function setDigitSize( $size )
557 853 {
558 - $this->storeRawSetting('digit_size', $size);
854 + $this->storeRawSetting( 'digit_size', $size );
559 855 }
560 856
561 857 /**
562 858 * Save timer label size.
@@ -562,16 +858,16 @@
562 858 * Save timer label size.
563 859 *
564 860 * @param $size
565 861 */
566 - public function setLabelSize($size)
862 + public function setLabelSize( $size )
567 863 {
568 - $this->storeRawSetting('label_size', $size);
864 + $this->storeRawSetting( 'label_size', $size );
569 865 }
570 866
571 - public function setHeadlineSize($size)
867 + public function setHeadlineSize( $size )
572 868 {
573 - $this->storeRawSetting('headline_size', $size);
869 + $this->storeRawSetting( 'headline_size', $size );
574 870 }
575 871
576 872 /**
577 873 * Returns evergreen duration.
@@ -579,20 +875,46 @@
579 875 * @return array
580 876 */
581 877 public function getDuration()
582 878 {
583 - $default = [0, 0, 0, 0];
584 - $duration = $this->getRawSetting('duration');
585 - if (is_array($duration)) {
586 - $duration = array_merge($duration, $default);
879 + $default = [ 0, 0, 0, 0 ];
880 + $duration = $this->getRawSetting( 'duration' );
881 + if ( is_array( $duration ) ) {
882 + $duration = array_merge( $duration, $default );
587 883
588 - return array_map('intval', $duration);
884 + return array_map( 'intval', $duration );
589 885 }
590 886
591 887 return $default;
592 888 }
593 889
890 + public function setRecurringDuration( $value )
891 + {
892 + $this->storeRawSetting( '_hurryt_recurring_duration', $value );
893 + }
894 +
895 + public function setRecurringPauseDuration( $value )
896 + {
897 + $this->storeRawSetting( '_hurryt_recurring_pause_duration', $value );
898 + }
899 +
594 900 /**
901 + * Returns evergreen duration.
902 + *
903 + * @return array
904 + */
905 + public function getRecurringDuration()
906 + {
907 + $default = [ 0, 0, 0, 0 ];
908 + $duration = $this->getRawSetting( '_hurryt_recurring_duration', false );
909 + if ( is_array( $duration ) ) {
910 + return array_map( 'intval', array_merge( $duration, $default ) );
911 + }
912 +
913 + return $default;
914 + }
915 +
916 + /**
595 917 * Returns actions array.
596 918 *
597 919 * @return array
598 920 */
@@ -597,62 +919,64 @@
597 919 * @return array
598 920 */
599 921 public function getActions()
600 922 {
601 - $legacy = $this->getLegacySetting('end_action');
602 - if ($legacy) {
603 - $redirectUrl = $this->getLegacySetting('redirect_url');
604 - $actions = [
923 + $legacy = $this->getLegacySetting( 'end_action' );
924 + if ( $legacy ) {
925 + $redirectUrl = $this->getLegacySetting( 'redirect_url' );
926 + $actions = [
605 927 [
606 - 'id' => intval($legacy),
928 + 'id' => intval( $legacy ),
607 929 'redirectUrl' => $redirectUrl,
608 930 ],
609 931 ];
610 - $this->storeRawSetting('actions', $actions);
611 - $this->deleteRawSetting('end_action');
612 - $this->deleteRawSetting('redirect_url');
932 + $this->storeRawSetting( 'actions', $actions );
933 + $this->deleteRawSetting( 'end_action' );
934 + $this->deleteRawSetting( 'redirect_url' );
613 935
614 - return $this->mergeActions($actions);
936 + return $this->mergeActions( $actions );
615 937 }
616 938
617 - return $this->mergeActions($this->getRawSetting('actions'));
939 + return $this->mergeActions( $this->getRawSetting( 'actions' ) );
618 940 }
619 941
620 - private function mergeActions($actions)
942 + private function mergeActions( $actions )
621 943 {
622 944 $defaults = [
623 945 [
624 - 'id' => C::ACTION_NONE,
625 - 'redirectUrl' => '',
626 - 'message' => '',
946 + 'id' => C::ACTION_NONE,
947 + 'redirectUrl' => '',
948 + 'message' => '',
627 949 'wcStockStatus' => '',
628 950 ],
629 951 ];
630 952
631 - if (count($actions) === 0) {
953 + if ( count( $actions ) === 0 ) {
632 954 return $defaults;
633 955 }
634 956
635 - return array_map(function ($action) use ($defaults) {
636 - $action['id'] = (int) $action['id'];
957 + return array_map( function ( $action ) use ( $defaults ) {
958 + $action[ 'id' ] = (int)$action[ 'id' ];
637 959
638 - return array_merge($defaults[0], $action);
639 - }, $actions);
960 + return array_merge( $defaults[ 0 ], $action );
961 + }, $actions );
640 962 }
641 963
642 964 /**
643 965 * Returns evergreen duration in seconds.
644 966 *
967 + * @param array $duration
968 + *
645 969 * @return int
646 970 */
647 - public function getDurationInSeconds()
971 + public function durationArrayToSeconds( $duration = [] )
648 972 {
649 - list($d, $h, $m, $s) = $this->getDuration();
973 + list( $d, $h, $m, $s ) = empty( $duration ) ? $this->getDuration() : $duration;
650 974
651 975 return $d * DAY_IN_SECONDS +
652 - $h * HOUR_IN_SECONDS +
653 - $m * MINUTE_IN_SECONDS +
654 - $s;
976 + $h * HOUR_IN_SECONDS +
977 + $m * MINUTE_IN_SECONDS +
978 + $s;
655 979 }
656 980
657 981 /**
658 982 * Returns end datetime.
@@ -660,12 +984,147 @@
660 984 * @return string
661 985 */
662 986 public function getEndDatetime()
663 987 {
664 - return $this->getRawSetting('end_datetime') ?: $this->defaultEndDatetime();
988 + return $this->getRawSetting( 'end_datetime' ) ?: $this->defaultEndDatetime();
665 989 }
666 990
667 991 /**
992 + * Return true if the recurrence is expired.
993 + *
994 + * @return bool
995 + */
996 + public function isRecurringExpired()
997 + {
998 + $deadline = $this->getRecurringDeadline();
999 + if ( ! ( $deadline instanceof Carbon ) ) {
1000 + return false;
1001 + }
1002 +
1003 + $now = Carbon::now( hurryt_tz() );
1004 +
1005 + return $now->isAfter( $deadline );
1006 + }
1007 +
1008 + function getTimeToNextRecurrence()
1009 + {
1010 + $this->loadSettings();
1011 + $interval = absint( $this->recurringInterval );
1012 +
1013 + if ( $this->recurringFrequency === C::RECURRING_DAILY ) {
1014 + $frequencyInSeconds = DAY_IN_SECONDS;
1015 + } elseif ( $this->recurringFrequency === C::RECURRING_WEEKLY ) {
1016 + $frequencyInSeconds = WEEK_IN_SECONDS;
1017 +
1018 + } elseif ( $this->recurringFrequency === C::RECURRING_HOURLY ) {
1019 + $frequencyInSeconds = HOUR_IN_SECONDS;
1020 +
1021 + } else {
1022 + $frequencyInSeconds = MINUTE_IN_SECONDS;
1023 + }
1024 +
1025 + $duration = $this->durationArrayToSeconds( $this->getRecurringDuration() );
1026 +
1027 + return max( 0, ( $frequencyInSeconds * $interval ) - $duration );
1028 + }
1029 +
1030 + /**
1031 + * Return true if the current campaign can recur today.
1032 + *
1033 + * @return bool
1034 + */
1035 + public function canRecurToday()
1036 + {
1037 + $this->loadSettings();
1038 + $day = absint( Carbon::now( hurryt_tz() )->format( 'w' ) );
1039 + $recur = in_array( $day, array_map( 'absint', $this->recurringDays ) );
1040 +
1041 + return apply_filters( 'hurryt_recur_today', $recur, $this->getId() );
1042 + }
1043 +
1044 + /**
1045 + * Return current recurrence date
1046 + *
1047 + * @return \Carbon\CarbonInterface|null
1048 + */
1049 + public function getRecurringCurrentDate()
1050 + {
1051 + $this->loadSettings();
1052 + $dtStart = Carbon::parse( $this->recurringStartTime, hurryt_tz() );
1053 + $now = Carbon::now( hurryt_tz() );
1054 +
1055 + $range = CarbonPeriod::since( $dtStart );
1056 + $interval = absint( $this->recurringInterval );
1057 +
1058 + if ( $this->recurringFrequency === C::RECURRING_DAILY ) {
1059 + $range->days( $interval );
1060 + } elseif ( $this->recurringFrequency === C::RECURRING_WEEKLY ) {
1061 + $range->weeks( $interval );
1062 + } elseif ( $this->recurringFrequency === C::RECURRING_HOURLY ) {
1063 + $range->hours( $interval );
1064 + } else {
1065 + $range->minutes( $interval );
1066 + }
1067 +
1068 + // Recurs forever
1069 + if ( absint( $this->recurringEnd ) === C::RECURRING_END_NEVER ) {
1070 + $range->until( $now );
1071 + // Recurs until
1072 + } elseif ( absint( $this->recurringEnd ) === C::RECURRING_END_TIME ) {
1073 + $range->until( Carbon::parse( $this->recurringUntil, hurryt_tz() ) );
1074 +
1075 + $range->addFilter( function ( $date ) use ( $now ) {
1076 + /**
1077 + * @var Carbon $date
1078 + */
1079 + return $date->isBefore( $now );
1080 + } );
1081 +
1082 + // Recurs N times.
1083 + } elseif ( absint( $this->recurringEnd ) === C::RECURRING_END_OCCURRENCES ) {
1084 +
1085 + // Virtual endDate
1086 + $range->until( Carbon::now( hurryt_tz() )->addCenturies( 1 ) );
1087 +
1088 + // Limit to the number of occurences in `$this->recurringCount`
1089 + $range->setRecurrences( absint( $this->recurringCount ) );
1090 +
1091 + // Set the endDate to the last occurence date
1092 + $range->setEndDate( $range->last() );
1093 + $range->addFilter( function ( $date ) use ( $now ) {
1094 +
1095 + /**
1096 + * @var Carbon $date
1097 + */
1098 + return $date->isBefore( $now );
1099 + } );
1100 +
1101 + }
1102 +
1103 + return $range->last();
1104 + }
1105 +
1106 + /**
1107 + * Get the next/current deadline based on the current date.
1108 + *
1109 + * @return null|Carbon
1110 + */
1111 + public function getRecurringDeadline()
1112 + {
1113 + $date = $this->getRecurringCurrentDate();
1114 + if ( ! $date ) {
1115 + return null;
1116 + }
1117 + $date = clone Carbon::instance( $date );
1118 +
1119 + $duration = $this->durationArrayToSeconds( $this->getRecurringDuration() );
1120 +
1121 + $date->addSeconds( $duration );
1122 +
1123 + return $date;
1124 + }
1125 +
1126 + /**
668 1127 * Returns compaign publish datetime.
669 1128 *
670 1129 * @return mixed
671 1130 */
@@ -670,9 +1129,9 @@
670 1129 * @return mixed
671 1130 */
672 1131 public function getStartTimestamp()
673 1132 {
674 - return get_the_date($this->id);
1133 + return get_the_date( $this->id );
675 1134 }
676 1135
677 1136 /**
678 1137 * Returns position in WooCommerce product page.
@@ -680,22 +1139,22 @@
680 1139 * @return mixed
681 1140 */
682 1141 public function getWcPosition()
683 1142 {
684 - $legacy = $this->getLegacySetting('position');
1143 + $legacy = $this->getLegacySetting( 'position' );
685 1144
686 - if (!$legacy) {
687 - return $this->getRawSetting('wc_position');
1145 + if ( ! $legacy ) {
1146 + return $this->getRawSetting( 'wc_position' );
688 1147 }
689 - $this->storeRawSetting('wc_position', $legacy);
690 - $this->deleteRawSetting('position');
1148 + $this->storeRawSetting( 'wc_position', $legacy );
1149 + $this->deleteRawSetting( 'position' );
691 1150
692 1151 return $legacy;
693 1152 }
694 1153
695 - private function getLegacySetting($name)
1154 + private function getLegacySetting( $name )
696 1155 {
697 - return get_post_meta($this->id, $name, true);
1156 + return get_post_meta( $this->id, $name, true );
698 1157 }
699 1158
700 1159 /**
701 1160 * Returns true if WooCommerce integration is enabled.
@@ -703,22 +1162,22 @@
703 1162 * @return mixed
704 1163 */
705 1164 public function getWcEnable()
706 1165 {
707 - $value = $this->getRawSetting('wc_enable', false);
1166 + $value = $this->getRawSetting( 'wc_enable', false );
708 1167
709 - if ($value === C::YES || $value === C::NO) {
1168 + if ( $value === C::YES || $value === C::NO ) {
710 1169 return $value;
711 1170 }
712 1171
713 - $legacy = filter_var($value, FILTER_VALIDATE_BOOLEAN);
714 - if ($legacy) {
715 - $this->storeRawSetting('wc_enable', C::YES);
1172 + $legacy = filter_var( $value, FILTER_VALIDATE_BOOLEAN );
1173 + if ( $legacy ) {
1174 + $this->storeRawSetting( 'wc_enable', C::YES );
716 1175 } else {
717 - $this->storeRawSetting('wc_enable', C::NO);
1176 + $this->storeRawSetting( 'wc_enable', C::NO );
718 1177 }
719 1178
720 - return $this->getRawSetting('wc_enable');
1179 + return $this->getRawSetting( 'wc_enable' );
721 1180 }
722 1181
723 1182 /**
724 1183 * Returns true if label should be displayed.
@@ -726,20 +1185,21 @@
726 1185 * @return mixed
727 1186 */
728 1187 public function getLabelVisibility()
729 1188 {
730 - $meta = 'label_visibility';
731 - $value = $this->getRawSetting($meta, false);
732 - if ($value === C::NO || $value === C::YES) {
1189 + $meta = 'label_visibility';
1190 + $value = $this->getRawSetting( $meta, false );
1191 + if ( $value === C::NO || $value === C::YES ) {
733 1192 return $value;
734 1193 }
735 1194
736 - $legacy = filter_var($this->getLegacySetting('display_labels'), FILTER_VALIDATE_BOOLEAN);
1195 + $legacy = filter_var( $this->getLegacySetting( 'display_labels' ),
1196 + FILTER_VALIDATE_BOOLEAN );
737 1197 $legacy = $legacy ? C::YES : C::NO;
738 - $this->storeRawSetting($meta, $legacy);
739 - $this->deleteRawSetting('display_labels');
1198 + $this->storeRawSetting( $meta, $legacy );
1199 + $this->deleteRawSetting( 'display_labels' );
740 1200
741 - return $this->getRawSetting($meta);
1201 + return $this->getRawSetting( $meta );
742 1202
743 1203 }
744 1204
745 1205 /**
@@ -749,9 +1209,9 @@
749 1209 * @return int
750 1210 */
751 1211 public function getRestart()
752 1212 {
753 - return $this->getRawSetting('restart') ?: C::RESTART_NONE;
1213 + return $this->getRawSetting( 'restart' ) ?: C::RESTART_NONE;
754 1214 }
755 1215
756 1216 /**
757 1217 * Returns WooCommerce products selection type.
@@ -759,14 +1219,14 @@
759 1219 * @return string
760 1220 */
761 1221 public function getWcProductsSelectionType()
762 1222 {
763 - $legacy = $this->getLegacySetting('products_type');
764 - if (!$legacy) {
765 - return $this->getRawSetting('wc_products_selection_type');
1223 + $legacy = $this->getLegacySetting( 'products_type' );
1224 + if ( ! $legacy ) {
1225 + return $this->getRawSetting( 'wc_products_selection_type' );
766 1226 }
767 - $this->storeRawSetting('wc_products_selection_type', $legacy);
768 - $this->deleteRawSetting('products_type');
1227 + $this->storeRawSetting( 'wc_products_selection_type', $legacy );
1228 + $this->deleteRawSetting( 'products_type' );
769 1229
770 1230 return $legacy;
771 1231 }
772 1232
@@ -774,11 +1234,11 @@
774 1234 * Delete setting item.
775 1235 *
776 1236 * @param $name
777 1237 */
778 - public function deleteRawSetting($name)
1238 + public function deleteRawSetting( $name )
779 1239 {
780 - delete_post_meta($this->id, $name);
1240 + delete_post_meta( $this->id, $name );
781 1241 }
782 1242
783 1243 /**
784 1244 * Returns products selection IDs.
@@ -786,14 +1246,14 @@
786 1246 * @return array
787 1247 */
788 1248 public function getWcProductsSelection()
789 1249 {
790 - $legacy = $this->getLegacySetting('products');
791 - if (!$legacy) {
792 - return $this->getRawSetting('wc_products_selection');
1250 + $legacy = $this->getLegacySetting( 'products' );
1251 + if ( ! $legacy ) {
1252 + return $this->getRawSetting( 'wc_products_selection' );
793 1253 }
794 - $this->storeRawSetting('wc_products_selection', $legacy);
795 - $this->deleteRawSetting('products');
1254 + $this->storeRawSetting( 'wc_products_selection', $legacy );
1255 + $this->deleteRawSetting( 'products' );
796 1256
797 1257 return $legacy;
798 1258 }
799 1259
@@ -801,12 +1261,12 @@
801 1261 * Store custom labels.
802 1262 *
803 1263 * @param $labels
804 1264 */
805 - public function setLabels($labels)
1265 + public function setLabels( $labels )
806 1266 {
807 - $labels = array_merge($this->labels, array_filter($labels));
808 - update_post_meta($this->id, 'labels', $labels);
1267 + $labels = array_merge( $this->labels, array_filter( $labels ) );
1268 + update_post_meta( $this->id, 'labels', $labels );
809 1269 }
810 1270
811 1271 /**
812 1272 * Returns true if compaign can be published.
@@ -814,9 +1274,10 @@
814 1274 * @return bool
815 1275 */
816 1276 public function isActive()
817 1277 {
818 - return get_post_status($this->id) === "publish" || get_post_status($this->id) === "future";
1278 + return get_post_status( $this->id ) === "publish"
1279 + || get_post_status( $this->id ) === "future";
819 1280
820 1281 }
821 1282
822 1283 /**
@@ -825,24 +1286,46 @@
825 1286 * @return bool
826 1287 */
827 1288 public function isScheduled()
828 1289 {
829 - return get_post_status($this->getId()) === "future";
1290 + $scheduled = get_post_status( $this->getId() ) === "future";
1291 + if ( $scheduled ) {
1292 + return true;
1293 + }
1294 +
1295 + if ( $this->isRecurring() ) {
1296 + $start_date = Carbon::parse( $this->recurringStartTime, hurryt_tz() );
1297 + $now = Carbon::now( hurryt_tz() );
1298 + if ( $now->isBefore( $start_date ) ) {
1299 + return true;
1300 + }
1301 + }
1302 +
1303 + return $scheduled;
830 1304 }
831 1305
832 1306 /**
833 1307 * Returns true if fixed campaign datetime is expired.
834 1308 *
1309 + * @param string|null $date
1310 + *
835 1311 * @return bool
836 1312 */
837 - public function isExpired()
1313 + public function isExpired( $date = null )
838 1314 {
839 - $endDate = date_create($this->endDatetime)->format("Y-m-d H:i");
840 - $today = date_create(current_time("mysql"))->format("Y-m-d H:i");
1315 + $endDate = $date === null ? date_create( $this->endDatetime ) : $date;
1316 + $today = date_create( current_time( "mysql" ) );
841 1317
842 1318 return $endDate < $today;
843 1319 }
844 1320
1321 + public function isStickyDismissed()
1322 + {
1323 + return isset( $_COOKIE[ CookieDetection::COOKIE_PREFIX . $this->getId() . '_dismissed' ] )
1324 + && $this->stickyBarDismissible === C::YES
1325 + && $this->enableSticky === C::YES;
1326 + }
1327 +
845 1328 /**
846 1329 * Returns compaign template wrapper.
847 1330 *
848 1331 * @param string
@@ -848,12 +1331,13 @@
848 1331 * @param string
849 1332 *
850 1333 * @return string
851 1334 */
852 - public function wrapTemplate($content)
1335 + public function wrapTemplate( $content )
853 1336 {
854 - $campaignBuilder = new CampaignBuilder($this);
855 - return $campaignBuilder->build($content);
1337 + $campaignBuilder = new CampaignBuilder( $this );
1338 +
1339 + return $campaignBuilder->build( $content );
856 1340 }
857 1341
858 1342 /*
859 1343 * Returns campaign template content.
@@ -859,9 +1343,20 @@
859 1343 * Returns campaign template content.
860 1344 */
861 1345 public function buildTemplate()
862 1346 {
863 - $campaignBuilder = new CampaignBuilder($this);
1347 + $campaignBuilder = new CampaignBuilder( $this );
864 1348
865 1349 return $campaignBuilder->template();
866 1350 }
1351 +
1352 + public function setWcConditions( $value )
1353 + {
1354 + $this->storeRawSetting( '_hurryt_wc_conditions', ! empty( $value ) ? $value : [] );
1355 + }
1356 +
1357 + public function getWcConditions()
1358 + {
1359 + return $this->getRawSetting( '_hurryt_wc_conditions', false );
1360 + }
1361 +
867 1362 }