| @@ -1,11 +1,8 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | |
| 3 | 3 | namespace Hurrytimer; |
| 4 | 4 | |
| 5 | -use DateInterval; | |
| 6 | -use DatePeriod; | |
| 7 | -use DateTime; | |
| 8 | 5 | use Hurrytimer\Dependencies\Carbon\Carbon; |
| 9 | 6 | use Hurrytimer\Dependencies\Carbon\CarbonPeriod; |
| 10 | 7 | use Hurrytimer\Utils\Helpers; |
| 11 | 8 | |
| @@ -42,12 +39,9 @@ | ||
| 42 | 39 | * |
| 43 | 40 | * @var int |
| 44 | 41 | */ |
| 45 | 42 | public $recurringDuration; |
| 46 | - public $recurringPauseDuration = ['days' => 0, 'hours' => 0, 'minutes' => 0, 'seconds' => 0]; | |
| 47 | 43 | |
| 48 | - public $recurringDurationOption = 'none'; | |
| 49 | - | |
| 50 | 44 | /** |
| 51 | 45 | * Recurrence start date/time |
| 52 | 46 | * |
| 53 | 47 | * @var string |
| @@ -305,9 +299,9 @@ | ||
| 305 | 299 | * |
| 306 | 300 | * @var int |
| 307 | 301 | */ |
| 308 | 302 | |
| 309 | - public $blockSize = 'auto'; | |
| 303 | + public $blockSize = 50; | |
| 310 | 304 | |
| 311 | 305 | /** |
| 312 | 306 | * Block background color. |
| 313 | 307 | * |
| @@ -501,33 +495,17 @@ | ||
| 501 | 495 | C::DETECTION_METHOD_COOKIE, |
| 502 | 496 | C::DETECTION_METHOD_IP, |
| 503 | 497 | ]; |
| 504 | 498 | |
| 505 | - public $timezoneType = 'site'; | |
| 506 | - public $timezone; | |
| 507 | 499 | |
| 508 | - | |
| 509 | 500 | public $recurringMonthlyDayType = C::RECURRING_MONTHLY_DAY_OF_MONTH; |
| 510 | 501 | |
| 511 | 502 | |
| 512 | - public $recurringUnselectedDaysAction = 'skip'; | |
| 503 | + public $recurringUnselectedDaysAction = 'hide'; | |
| 513 | 504 | |
| 514 | - public $evergreenEndDay = 0; | |
| 515 | - public $evergreenEndTime = ''; | |
| 516 | - public $evergreenEndType = 'duration'; | |
| 517 | - | |
| 518 | - /** | |
| 519 | - * Regular mode date ranges. | |
| 520 | - * Each entry: ['start' => 'Y-m-d h:i A', 'end' => 'Y-m-d h:i A'] | |
| 521 | - * When only one range exists (or empty), falls back to the single endDatetime field. | |
| 522 | - * | |
| 523 | - * @var array | |
| 524 | - */ | |
| 525 | - public $dateRanges = []; | |
| 526 | - | |
| 527 | 505 | public function __construct($id) |
| 528 | 506 | { |
| 529 | - $this->recurringStartTime = Carbon::now(hurryt_tz($this->getTimezone()))->format('Y-m-d h:i A'); | |
| 507 | + $this->recurringStartTime = Carbon::now(hurryt_tz())->format('Y-m-d h:i A'); | |
| 530 | 508 | $this->id = $id; |
| 531 | 509 | } |
| 532 | 510 | |
| 533 | 511 | /** |
| @@ -572,9 +550,9 @@ | ||
| 572 | 550 | |
| 573 | 551 | case 'specific_pages': |
| 574 | 552 | $pageIds = $this->getStickyBarPages(); |
| 575 | 553 | |
| 576 | - if (!empty($pageId) && !empty($pageIds) && in_array($pageId, $pageIds)) { | |
| 554 | + if (!empty($pageId) && !empty($pageIds) && in_array($pageId, $pageIds, true)) { | |
| 577 | 555 | return apply_filters('hurryt_show_sticky_bar', true, $this->get_id()); |
| 578 | 556 | } |
| 579 | 557 | |
| 580 | 558 | foreach ($this->stickyIncludeUrls as $url) { |
| @@ -585,12 +563,13 @@ | ||
| 585 | 563 | break; |
| 586 | 564 | } |
| 587 | 565 | } |
| 588 | 566 | return apply_filters('hurryt_show_sticky_bar', false, $this->get_id()); |
| 589 | - | |
| 567 | + | |
| 590 | 568 | case 'exclude_pages': |
| 591 | 569 | $pageIds = $this->getStickyExcludePages(); |
| 592 | - if (!empty($pageId) && !empty($pageIds) && in_array($pageId, $pageIds)) { | |
| 570 | + | |
| 571 | + if (!empty($pageId) && !empty($pageIds) && in_array($pageId, $pageIds, true)) { | |
| 593 | 572 | return apply_filters('hurryt_show_sticky_bar', false, $this->get_id()); |
| 594 | 573 | } |
| 595 | 574 | |
| 596 | 575 | foreach ($this->stickyExcludeUrls as $url) { |
| @@ -716,26 +695,12 @@ | ||
| 716 | 695 | * @param $data |
| 717 | 696 | */ |
| 718 | 697 | public function storeSettings($data) |
| 719 | 698 | { |
| 720 | - if (!hurrytimer_allow_unfiltered_html()) { | |
| 721 | - // Exclude fields that have their own sanitization to avoid double-processing | |
| 722 | - // which can strip valid HTML (e.g. <a> tags in headline). | |
| 723 | - $html_fields = ['headline']; | |
| 724 | - $reserved = array_intersect_key($data, array_flip($html_fields)); | |
| 725 | - $data = wp_kses_post_deep(array_diff_key($data, array_flip($html_fields))); | |
| 726 | - $data = array_merge($data, $reserved); | |
| 727 | - } | |
| 728 | - | |
| 729 | 699 | foreach ($data as $prop => $value) { |
| 730 | 700 | $method = Helpers::snakeToCamelCase("set_{$prop}"); |
| 731 | 701 | if (method_exists($this, $method)) { |
| 732 | - if($prop === 'timezone') { | |
| 733 | - $this->setTimezone($value, $data['timezone_type']); | |
| 734 | - } | |
| 735 | - else{ | |
| 736 | - $this->$method($value ?: $this->$prop); | |
| 737 | - } | |
| 702 | + $this->$method($value ?: $this->$prop); | |
| 738 | 703 | } elseif (property_exists(__CLASS__, Helpers::snakeToCamelCase($prop))) { |
| 739 | 704 | $this->set_prop($prop, $value); |
| 740 | 705 | } |
| 741 | 706 | } |
| @@ -744,14 +709,10 @@ | ||
| 744 | 709 | } |
| 745 | 710 | if (!isset($data['sticky_bar_pages'])) { |
| 746 | 711 | $this->setStickyBarPages([]); |
| 747 | 712 | } |
| 748 | - // Only use multiple deadlines if the toggle is active | |
| 749 | - if (isset($data['use_multiple_deadlines']) && $data['use_multiple_deadlines'] === '0') { | |
| 750 | - $this->setDateRanges([]); | |
| 751 | - } | |
| 752 | 713 | |
| 753 | - CSS_Builder::get_instance()->generate_css(); | |
| 714 | + CSS_Builder::get_instance()->build(); | |
| 754 | 715 | } |
| 755 | 716 | |
| 756 | 717 | //removeIf(pro) |
| 757 | 718 | |
| @@ -760,9 +721,9 @@ | ||
| 760 | 721 | * ::PROP |
| 761 | 722 | */ |
| 762 | 723 | public function setMode($mode) |
| 763 | 724 | { |
| 764 | - if ($mode == C::MODE_RECURRING) { | |
| 725 | + if ( $mode == C::MODE_RECURRING ) { | |
| 765 | 726 | return; |
| 766 | 727 | } |
| 767 | 728 | $this->set_prop('mode', $mode); |
| 768 | 729 | } |
| @@ -784,184 +745,28 @@ | ||
| 784 | 745 | } else { |
| 785 | 746 | $this->{$name} = $this->get_prop(Helpers::camelToSnakeCase($name)); |
| 786 | 747 | } |
| 787 | 748 | } |
| 749 | + } | |
| 788 | 750 | |
| 789 | - } | |
| 790 | 751 | |
| 791 | 752 | public function getHeadline() |
| 792 | 753 | { |
| 793 | - $content = $this->get_prop('_hurryt_headline', false); | |
| 754 | + if (empty($this->id)) { | |
| 755 | + return $this->headline; | |
| 756 | + } | |
| 757 | + if (metadata_exists('post', $this->id, '_hurryt_headline')) { | |
| 758 | + return $this->get_prop('_hurryt_headline'); | |
| 759 | + } | |
| 794 | 760 | |
| 795 | - // User has set a custom headline | |
| 796 | - if( !empty( $content ) ){ return $content; } | |
| 797 | - | |
| 798 | - // Backward compat. | |
| 799 | - if (empty($content) && version_compare(get_option('hurrytimer_version'), '2.3.0', '<=')) { | |
| 800 | - return get_the_title($this->id); | |
| 801 | - } | |
| 802 | - | |
| 803 | - // Show default headline. | |
| 804 | - return $this->headline; | |
| 761 | + return get_the_title($this->id); | |
| 805 | 762 | } |
| 806 | 763 | |
| 807 | 764 | public function setHeadline($value) |
| 808 | 765 | { |
| 809 | - $value = $this->sanitize_headline_html( $value ); | |
| 810 | 766 | $this->set_prop('_hurryt_headline', $value); |
| 811 | 767 | } |
| 812 | 768 | |
| 813 | - /** | |
| 814 | - * Custom HTML sanitizer for the headline field. | |
| 815 | - * | |
| 816 | - * Allowed tags: span, div, a, input, br, s, p, strong, em | |
| 817 | - * - style, class, id allowed on visual tags (CSS values are preserved as-is | |
| 818 | - * except javascript:/expression()/vbscript: patterns are removed) | |
| 819 | - * - <a>: href (blocked if javascript:), target, rel | |
| 820 | - * - <input>: type, value, style (no event handlers) | |
| 821 | - * - All on* event handler attributes stripped from every tag | |
| 822 | - * - Dangerous tags (script, iframe, object, embed, form, link, meta) stripped entirely | |
| 823 | - */ | |
| 824 | - private function sanitize_headline_html( $value ) { | |
| 825 | - // Strip dangerous block-level tags and their contents. | |
| 826 | - $value = preg_replace( | |
| 827 | - '#<(script|iframe|object|embed|form|link|meta)[^>]*>.*?</\1>#is', | |
| 828 | - '', | |
| 829 | - $value | |
| 830 | - ); | |
| 831 | - // Also strip self-closing variants. | |
| 832 | - $value = preg_replace( | |
| 833 | - '#<(script|iframe|object|embed|form|link|meta)[^>]*/?\s*>#is', | |
| 834 | - '', | |
| 835 | - $value | |
| 836 | - ); | |
| 837 | - | |
| 838 | - $allowed_tags = [ 'span', 'div', 'a', 'input', 'img', 'i', 'u', 'b', 'small', 'sup', 'sub', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'br', 's', 'p', 'strong', 'em' ]; | |
| 839 | - | |
| 840 | - // Use DOMDocument to walk and filter the fragment. | |
| 841 | - $doc = new \DOMDocument(); | |
| 842 | - // Suppress warnings from malformed HTML; wrap in a root node. | |
| 843 | - @$doc->loadHTML( | |
| 844 | - '<?xml encoding="utf-8"?><div id="__hurrytimer_root__">' . $value . '</div>', | |
| 845 | - LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD | |
| 846 | - ); | |
| 847 | - | |
| 848 | - $root = $doc->getElementById('__hurrytimer_root__'); | |
| 849 | - if ( ! $root ) { | |
| 850 | - return ''; | |
| 851 | - } | |
| 852 | - | |
| 853 | - $this->_sanitize_headline_node( $root, $allowed_tags ); | |
| 854 | - | |
| 855 | - // Serialize only the inner HTML of our wrapper. | |
| 856 | - $html = ''; | |
| 857 | - foreach ( $root->childNodes as $child ) { | |
| 858 | - $html .= $doc->saveHTML( $child ); | |
| 859 | - } | |
| 860 | - | |
| 861 | - return $html; | |
| 862 | - } | |
| 863 | - | |
| 864 | - /** | |
| 865 | - * Recursively sanitize a DOM node for the headline field. | |
| 866 | - */ | |
| 867 | - private function _sanitize_headline_node( \DOMNode $node, array $allowed_tags ) { | |
| 868 | - $remove = []; | |
| 869 | - | |
| 870 | - foreach ( $node->childNodes as $child ) { | |
| 871 | - if ( $child->nodeType === XML_ELEMENT_NODE ) { | |
| 872 | - $tag = strtolower( $child->nodeName ); | |
| 873 | - | |
| 874 | - if ( ! in_array( $tag, $allowed_tags, true ) ) { | |
| 875 | - // Replace disallowed tag with its children (unwrap). | |
| 876 | - $remove[] = [ 'node' => $child, 'unwrap' => true ]; | |
| 877 | - continue; | |
| 878 | - } | |
| 879 | - | |
| 880 | - // Sanitize attributes. | |
| 881 | - $attrs_to_remove = []; | |
| 882 | - foreach ( $child->attributes as $attr ) { | |
| 883 | - $name = strtolower( $attr->name ); | |
| 884 | - $val = $attr->value; | |
| 885 | - | |
| 886 | - // Strip all event handlers. | |
| 887 | - if ( strncmp( $name, 'on', 2 ) === 0 ) { | |
| 888 | - $attrs_to_remove[] = $name; | |
| 889 | - continue; | |
| 890 | - } | |
| 891 | - | |
| 892 | - // Per-tag attribute rules. | |
| 893 | - if ( $tag === 'a' ) { | |
| 894 | - if ( ! in_array( $name, [ 'href', 'target', 'rel', 'style', 'class', 'id' ], true ) ) { | |
| 895 | - $attrs_to_remove[] = $name; | |
| 896 | - continue; | |
| 897 | - } | |
| 898 | - if ( $name === 'href' && preg_match( '#^\s*javascript:#i', $val ) ) { | |
| 899 | - $attrs_to_remove[] = $name; | |
| 900 | - continue; | |
| 901 | - } | |
| 902 | - } elseif ( $tag === 'img' ) { | |
| 903 | - if ( ! in_array( $name, [ 'src', 'alt', 'width', 'height', 'style', 'class', 'id' ], true ) ) { | |
| 904 | - $attrs_to_remove[] = $name; | |
| 905 | - continue; | |
| 906 | - } | |
| 907 | - if ( $name === 'src' ) { | |
| 908 | - // Block javascript: protocol | |
| 909 | - if ( preg_match( '#^\s*javascript\s*:#i', $val ) ) { | |
| 910 | - $attrs_to_remove[] = $name; | |
| 911 | - continue; | |
| 912 | - } | |
| 913 | - // Block data: URIs except safe image types (no SVG — can contain scripts) | |
| 914 | - if ( preg_match( '#^\s*data\s*:#i', $val ) && ! preg_match( '#^\s*data\s*:\s*image/(png|jpe?g|gif|webp)\s*[;,]#i', $val ) ) { | |
| 915 | - $attrs_to_remove[] = $name; | |
| 916 | - continue; | |
| 917 | - } | |
| 918 | - } | |
| 919 | - } elseif ( $tag === 'input' ) { | |
| 920 | - if ( ! in_array( $name, [ 'type', 'value', 'style', 'class', 'id' ], true ) ) { | |
| 921 | - $attrs_to_remove[] = $name; | |
| 922 | - continue; | |
| 923 | - } | |
| 924 | - } else { | |
| 925 | - // Visual tags: allow style, class, id only. | |
| 926 | - if ( ! in_array( $name, [ 'style', 'class', 'id' ], true ) ) { | |
| 927 | - $attrs_to_remove[] = $name; | |
| 928 | - continue; | |
| 929 | - } | |
| 930 | - } | |
| 931 | - | |
| 932 | - // Sanitize style values: remove JS injection patterns. | |
| 933 | - if ( $name === 'style' ) { | |
| 934 | - $val = preg_replace( '#javascript\s*:#i', '', $val ); | |
| 935 | - $val = preg_replace( '#expression\s*\(#i', '', $val ); | |
| 936 | - $val = preg_replace( '#vbscript\s*:#i', '', $val ); | |
| 937 | - $child->setAttribute( 'style', $val ); | |
| 938 | - } | |
| 939 | - } | |
| 940 | - | |
| 941 | - foreach ( $attrs_to_remove as $a ) { | |
| 942 | - $child->removeAttribute( $a ); | |
| 943 | - } | |
| 944 | - | |
| 945 | - // Recurse. | |
| 946 | - $this->_sanitize_headline_node( $child, $allowed_tags ); | |
| 947 | - } | |
| 948 | - } | |
| 949 | - | |
| 950 | - // Unwrap or remove collected nodes. | |
| 951 | - foreach ( $remove as $item ) { | |
| 952 | - $n = $item['node']; | |
| 953 | - if ( $item['unwrap'] ) { | |
| 954 | - while ( $n->firstChild ) { | |
| 955 | - $node->insertBefore( $n->firstChild, $n ); | |
| 956 | - } | |
| 957 | - } | |
| 958 | - if ( $n->parentNode ) { | |
| 959 | - $n->parentNode->removeChild( $n ); | |
| 960 | - } | |
| 961 | - } | |
| 962 | - } | |
| 963 | - | |
| 964 | 769 | public function is_published() |
| 965 | 770 | { |
| 966 | 771 | return get_post_status($this->id) === "publish"; |
| 967 | 772 | } |
| @@ -996,25 +801,8 @@ | ||
| 996 | 801 | { |
| 997 | 802 | return $this->get_prop('mode') == C::MODE_RECURRING; |
| 998 | 803 | } |
| 999 | 804 | |
| 1000 | - public function getTimezone() | |
| 1001 | - { | |
| 1002 | - | |
| 1003 | - if($this->timezoneType === 'site') { | |
| 1004 | - return ''; | |
| 1005 | - } | |
| 1006 | - return ''; | |
| 1007 | - | |
| 1008 | - } | |
| 1009 | - public function setTimezone($timezone, $timezone_type) | |
| 1010 | - { | |
| 1011 | - if($timezone_type === 'site') { | |
| 1012 | - $timezone = ''; | |
| 1013 | - } | |
| 1014 | - | |
| 1015 | - $this->set_prop('timezone', $timezone); | |
| 1016 | - } | |
| 1017 | 805 | /** |
| 1018 | 806 | * Save compaign endtime for regular mode. |
| 1019 | 807 | * |
| 1020 | 808 | * @param $date |
| @@ -1020,10 +808,8 @@ | ||
| 1020 | 808 | * @param $date |
| 1021 | 809 | */ |
| 1022 | 810 | public function setEndDatetime($date) |
| 1023 | 811 | { |
| 1024 | - // Sanitize the date input to prevent XSS | |
| 1025 | - $date = sanitize_text_field($date); | |
| 1026 | 812 | $this->set_prop('end_datetime', $date ?: $this->defaultEndDatetime()); |
| 1027 | 813 | } |
| 1028 | 814 | |
| 1029 | 815 | /** |
| @@ -1216,9 +1002,8 @@ | ||
| 1216 | 1002 | return array_pad(array_map('intval', $duration), 4, 0); |
| 1217 | 1003 | } |
| 1218 | 1004 | |
| 1219 | 1005 | |
| 1220 | - | |
| 1221 | 1006 | public function getRestartDuration($asSeconds = false) |
| 1222 | 1007 | { |
| 1223 | 1008 | $duration = (array)$this->get_prop('hurryt_restart_duration', false); |
| 1224 | 1009 | |
| @@ -1235,27 +1020,8 @@ | ||
| 1235 | 1020 | } |
| 1236 | 1021 | return $duration; |
| 1237 | 1022 | } |
| 1238 | 1023 | |
| 1239 | - | |
| 1240 | - public function getRecurringPauseDuration($asSeconds = false) | |
| 1241 | - { | |
| 1242 | - $duration = (array)$this->get_prop('_hurryt_recurring_pause_duration', false); | |
| 1243 | - | |
| 1244 | - $duration = wp_parse_args($duration, $this->recurringPauseDuration); | |
| 1245 | - foreach ($duration as $unit => $value) { | |
| 1246 | - $duration[$unit] = (int)$value; | |
| 1247 | - } | |
| 1248 | - | |
| 1249 | - if ($asSeconds) { | |
| 1250 | - $duration = $duration['days'] * DAY_IN_SECONDS + | |
| 1251 | - $duration['hours'] * HOUR_IN_SECONDS + | |
| 1252 | - $duration['minutes'] * MINUTE_IN_SECONDS + | |
| 1253 | - $duration['seconds']; | |
| 1254 | - } | |
| 1255 | - return $duration; | |
| 1256 | - } | |
| 1257 | - | |
| 1258 | 1024 | public function setRestartDuration($duration_array) |
| 1259 | 1025 | { |
| 1260 | 1026 | $this->set_prop('hurryt_restart_duration', $duration_array); |
| 1261 | 1027 | } |
| @@ -1267,13 +1033,10 @@ | ||
| 1267 | 1033 | public function setRecurringDuration($value) |
| 1268 | 1034 | { |
| 1269 | 1035 | $this->set_prop('_hurryt_recurring_duration', $value); |
| 1270 | 1036 | } |
| 1271 | - public function setRecurringPauseDuration($value) | |
| 1272 | - { | |
| 1273 | - $this->set_prop('_hurryt_recurring_pause_duration', $value); | |
| 1274 | - } | |
| 1275 | 1037 | |
| 1038 | + | |
| 1276 | 1039 | /** |
| 1277 | 1040 | * Returns evergreen duration. |
| 1278 | 1041 | * |
| 1279 | 1042 | * @return array |
| @@ -1322,36 +1085,20 @@ | ||
| 1322 | 1085 | 'wcStockStatus' => '', |
| 1323 | 1086 | ], |
| 1324 | 1087 | ]; |
| 1325 | 1088 | |
| 1326 | - if (empty($actions) || !is_array($actions)) { | |
| 1089 | + if (count($actions) === 0) { | |
| 1327 | 1090 | return $defaults; |
| 1328 | 1091 | } |
| 1329 | 1092 | |
| 1330 | 1093 | return array_map(function ($action) use ($defaults) { |
| 1331 | - // Ensure we have an array | |
| 1332 | - $action = (array)$action; | |
| 1333 | - | |
| 1334 | - // Parse with defaults to ensure all keys exist | |
| 1335 | - $action = wp_parse_args($action, $defaults[0]); | |
| 1336 | - | |
| 1337 | - // Cast ID to integer | |
| 1338 | 1094 | $action['id'] = (int)$action['id']; |
| 1339 | 1095 | |
| 1340 | - // Clean up message HTML if it exists | |
| 1341 | - if (!empty($action['message'])) { | |
| 1342 | - $action['message'] = preg_replace_callback( | |
| 1343 | - '#<style(\s=?[\S]*)?>([\s\S]*)?<\/style>#', | |
| 1344 | - function ($matches) { | |
| 1345 | - return isset($matches[1], $matches[2]) | |
| 1346 | - ? '<style' . $matches[1] . '>' . preg_replace('/\<br(\s*)?\/?\>/i', '', $matches[2]) . '</style>' | |
| 1347 | - : ''; | |
| 1348 | - }, | |
| 1349 | - $action['message'] | |
| 1350 | - ); | |
| 1351 | - } | |
| 1096 | + $action['message'] = preg_replace_callback('#<style(\s=?[\S]*)?>([\s\S]*)?<\/style>#', function ($matches) { | |
| 1097 | + return '<style' . $matches[1] . '>' . preg_replace('/\<br(\s*)?\/?\>/i', '', $matches[2]) . '</style>'; | |
| 1098 | + }, $action['message']); | |
| 1352 | 1099 | |
| 1353 | - return $action; | |
| 1100 | + return array_merge($defaults[0], $action); | |
| 1354 | 1101 | }, $actions); |
| 1355 | 1102 | } |
| 1356 | 1103 | |
| 1357 | 1104 | |
| @@ -1408,9 +1155,9 @@ | ||
| 1408 | 1155 | if (!($endDate instanceof Carbon)) { |
| 1409 | 1156 | return false; |
| 1410 | 1157 | } |
| 1411 | 1158 | |
| 1412 | - $now = Carbon::now(hurryt_tz($this->timezone)); | |
| 1159 | + $now = Carbon::now(hurryt_tz()); | |
| 1413 | 1160 | |
| 1414 | 1161 | return $now->greaterThan($endDate); |
| 1415 | 1162 | } |
| 1416 | 1163 | |
| @@ -1425,43 +1172,13 @@ | ||
| 1425 | 1172 | $this->loadSettings(); |
| 1426 | 1173 | |
| 1427 | 1174 | if ($this->isMonthlyRecurring()) { |
| 1428 | 1175 | $current = $this->getRecurrenceEndDate(); |
| 1429 | - | |
| 1430 | 1176 | $next = $this->getRecurrenceEndDate(true); |
| 1431 | - | |
| 1432 | - $duration = $this->durationInSeconds($this->getRecurringDuration()); | |
| 1433 | - $use_custom = $this->recurringDurationOption === 'custom' && $duration > 0; | |
| 1434 | - | |
| 1435 | - if ($use_custom) { | |
| 1436 | - $time_remaining = $next->diffInSeconds($current); | |
| 1437 | - } else { | |
| 1438 | - $time_remaining = $this->getRecurringPauseDuration(true); | |
| 1439 | - } | |
| 1440 | - return $time_remaining; | |
| 1177 | + return absint($next->diffInSeconds($current)); | |
| 1441 | 1178 | } |
| 1442 | - | |
| 1443 | 1179 | list($duration, $pause, $period) = $this->getRecurringDurationInSeconds(); |
| 1444 | - | |
| 1445 | - $t = $pause ?: 0; | |
| 1446 | - | |
| 1447 | - $waitBeforeRestart = $this->getRecurringPauseDuration(true); | |
| 1448 | - | |
| 1449 | - $t += $waitBeforeRestart; | |
| 1450 | - | |
| 1451 | - if (!$this->has_skipped_days()) { | |
| 1452 | - return $t; | |
| 1453 | - } | |
| 1454 | - | |
| 1455 | - if ($this->isWeeklyRecurring()) { | |
| 1456 | - return $t; | |
| 1457 | - } | |
| 1458 | - | |
| 1459 | - if ($this->recurringUnselectedDaysAction === 'hide') { | |
| 1460 | - return $t; | |
| 1461 | - } | |
| 1462 | - | |
| 1463 | - return $waitBeforeRestart; | |
| 1180 | + return $pause ?: 0; | |
| 1464 | 1181 | } |
| 1465 | 1182 | |
| 1466 | 1183 | /** |
| 1467 | 1184 | * Return true if the current campaign can recur today. |
| @@ -1471,9 +1188,9 @@ | ||
| 1471 | 1188 | public function can_recur_today() |
| 1472 | 1189 | { |
| 1473 | 1190 | $this->loadSettings(); |
| 1474 | 1191 | |
| 1475 | - $day = absint(Carbon::now(hurryt_tz($this->timezone))->format('w')); | |
| 1192 | + $day = absint(Carbon::now(hurryt_tz())->format('w')); | |
| 1476 | 1193 | |
| 1477 | 1194 | $recur = in_array($day, array_map('absint', $this->recurringDays)); |
| 1478 | 1195 | |
| 1479 | 1196 | return apply_filters('hurryt_recur_today', $recur, $this->get_id()); |
| @@ -1518,10 +1235,10 @@ | ||
| 1518 | 1235 | |
| 1519 | 1236 | public function getRecurringPeriodEndDate() |
| 1520 | 1237 | { |
| 1521 | 1238 | list($d, $h, $m, $s) = $this->getRecurringDuration(); |
| 1522 | - $now = Carbon::now(hurryt_tz($this->timezone)); | |
| 1523 | - $startDate = Carbon::parse($this->recurringStartTime, hurryt_tz($this->timezone)); | |
| 1239 | + $now = Carbon::now(hurryt_tz()); | |
| 1240 | + $startDate = Carbon::parse($this->recurringStartTime, hurryt_tz()); | |
| 1524 | 1241 | $interval = (int)$this->recurringInterval; |
| 1525 | 1242 | $endDate = $now->copy(); |
| 1526 | 1243 | |
| 1527 | 1244 | switch ($this->recurringFrequency) { |
| @@ -1579,32 +1296,22 @@ | ||
| 1579 | 1296 | |
| 1580 | 1297 | /** |
| 1581 | 1298 | * Returns the recurrence end date based on the current date/time. |
| 1582 | 1299 | * |
| 1583 | - * @param bool $next Return the next recurrence end date. | |
| 1584 | - * | |
| 1585 | 1300 | * @return Carbon |
| 1586 | 1301 | */ |
| 1587 | - | |
| 1588 | 1302 | public function getRecurrenceEndDate($next = false) |
| 1589 | 1303 | { |
| 1590 | - | |
| 1591 | - $cached_key = $next ? 'recur_end_date__next' : 'recur_end_date'; | |
| 1592 | - $cached = wp_cache_get($cached_key, 'hurrytimer'); | |
| 1593 | - if ($cached instanceof Carbon) { | |
| 1594 | - return $cached; | |
| 1595 | - } | |
| 1596 | - | |
| 1597 | 1304 | try { |
| 1598 | - | |
| 1599 | 1305 | $this->loadSettings(); |
| 1600 | - $now = Carbon::now(hurryt_tz($this->timezone)); | |
| 1601 | - $startDate = Carbon::parse($this->recurringStartTime, hurryt_tz($this->timezone)); | |
| 1306 | + $now = Carbon::now(hurryt_tz()); | |
| 1307 | + $startDate = Carbon::parse($this->recurringStartTime, hurryt_tz()); | |
| 1602 | 1308 | $interval = (int)$this->recurringInterval; |
| 1603 | 1309 | |
| 1604 | 1310 | |
| 1605 | 1311 | // Handle monthly recurring |
| 1606 | 1312 | if ($this->isMonthlyRecurring()) { |
| 1313 | + | |
| 1607 | 1314 | $start_date_modified = $startDate->copy(); |
| 1608 | 1315 | |
| 1609 | 1316 | if ($startDate->day >= 28) { |
| 1610 | 1317 | $start_date_modified->startOfMonth(); |
| @@ -1616,15 +1323,11 @@ | ||
| 1616 | 1323 | $endDate->addMonths($interval); |
| 1617 | 1324 | } |
| 1618 | 1325 | |
| 1619 | 1326 | if ($this->shouldEndRecurringByDate()) { |
| 1620 | - $endDate = Carbon::parse($this->recurringUntil, hurryt_tz($this->timezone)); | |
| 1327 | + $endDate = Carbon::parse($this->recurringUntil, hurryt_tz()); | |
| 1621 | 1328 | } |
| 1622 | 1329 | |
| 1623 | - if ($this->isDayOfWeekRecurring()) { | |
| 1624 | - $endDate = $endDate->addMonths($interval); | |
| 1625 | - } | |
| 1626 | - | |
| 1627 | 1330 | $period = CarbonPeriod::create($start_date_modified, 'P' . $interval . 'M', $endDate); |
| 1628 | 1331 | |
| 1629 | 1332 | if ($this->shouldEndRecurringByRecurrences()) { |
| 1630 | 1333 | $period->setRecurrences($this->getRecurringRecurrences()); |
| @@ -1633,79 +1336,44 @@ | ||
| 1633 | 1336 | if ($period->count() === 0) { |
| 1634 | 1337 | return $period->getEndDate(); |
| 1635 | 1338 | } |
| 1636 | 1339 | |
| 1637 | - $dates = iterator_to_array($period); | |
| 1340 | + $date = $period->first(); | |
| 1341 | + $i = 0; | |
| 1638 | 1342 | |
| 1639 | - $dates = array_map(function ($date) use ($startDate) { | |
| 1640 | - $is_overflow = $startDate->day >= $date->daysInMonth; | |
| 1641 | - if ($this->isDayOfMonthRecurring() && $is_overflow) { | |
| 1343 | + while ($period->valid()) { | |
| 1344 | + | |
| 1345 | + $date = $period->current(); | |
| 1346 | + | |
| 1347 | + $isOverflow = $startDate->day >= $date->daysInMonth; | |
| 1348 | + | |
| 1349 | + if ($this->isDayOfMonthRecurring() && $isOverflow) { | |
| 1642 | 1350 | $date->endOfMonth(); |
| 1643 | 1351 | } |
| 1352 | + | |
| 1644 | 1353 | if ($this->isDayOfWeekRecurring()) { |
| 1645 | 1354 | $date->modifyWeekOfMonth($startDate); |
| 1646 | 1355 | } |
| 1356 | + | |
| 1647 | 1357 | $date->setTimeFrom($startDate); |
| 1648 | 1358 | |
| 1649 | - return $date; | |
| 1650 | - }, $dates); | |
| 1359 | + if ($date->greaterThan($now)) { | |
| 1651 | 1360 | |
| 1652 | - | |
| 1653 | - $out_date = end($dates) ?: $period->getEndDate(); | |
| 1654 | - | |
| 1655 | - reset($dates); | |
| 1656 | - | |
| 1657 | - foreach ($dates as $i => $date) { | |
| 1658 | - $duration = $this->durationInSeconds($this->getRecurringDuration()); | |
| 1659 | - $custom = $this->recurringDurationOption === 'custom' && $duration > 0; | |
| 1660 | - | |
| 1661 | - if ($custom && !$next) { | |
| 1662 | - $custom_end_date = $date->copy()->addSeconds($duration); | |
| 1663 | - | |
| 1664 | - if ($custom_end_date->greaterThan($now)) { | |
| 1665 | - $out_date = $custom_end_date; | |
| 1666 | - | |
| 1667 | - break; | |
| 1361 | + if (!$next || $i === 1) { | |
| 1362 | + return $date; | |
| 1668 | 1363 | } |
| 1669 | 1364 | |
| 1670 | - $next_date = isset($dates[$i + 1]) ? $dates[$i + 1] : $period->getEndDate(); | |
| 1671 | - | |
| 1672 | - if ($now->lessThan($next_date)) { | |
| 1673 | - $out_date = $custom_end_date; | |
| 1674 | - break; | |
| 1675 | - } | |
| 1676 | - | |
| 1677 | - continue; | |
| 1365 | + $i++; | |
| 1678 | 1366 | } |
| 1679 | 1367 | |
| 1680 | - if ($date->greaterThan($now)) { | |
| 1681 | - $pause_duration = $this->getRecurringPauseDuration(true); | |
| 1368 | + $period->next(); | |
| 1369 | + } | |
| 1682 | 1370 | |
| 1683 | - if ($next && !$custom) { | |
| 1684 | - $out_date = isset($dates[$i + 1]) ? $dates[$i + 1] : $out_date; | |
| 1685 | - | |
| 1686 | - if ($pause_duration > 0) { | |
| 1687 | - $out_date = $date; | |
| 1688 | - } | |
| 1689 | - } else { | |
| 1690 | - $out_date = $date; | |
| 1691 | - $prev_end_date = isset($dates[$i - 1]) ? $dates[$i - 1] : null; | |
| 1692 | - if ($prev_end_date && $prev_end_date->copy()->diffInSeconds($now) < $pause_duration) { | |
| 1693 | - $out_date = $prev_end_date; | |
| 1694 | - } | |
| 1695 | - } | |
| 1696 | - | |
| 1697 | - break; | |
| 1698 | - } | |
| 1371 | + if ($this->shouldEndRecurringByDate() && $date->lessThan($now)) { | |
| 1372 | + return $period->getEndDate(); | |
| 1699 | 1373 | } |
| 1700 | - if ($this->shouldEndRecurringByDate() && $out_date->lessThan($now)) { | |
| 1701 | - // TODO: Use the last recurrence instead of `getEndDate()` | |
| 1702 | - $out_date = $period->getEndDate(); | |
| 1703 | - } | |
| 1704 | 1374 | |
| 1705 | - wp_cache_set($cached_key, $out_date, 'hurrytimer'); | |
| 1706 | - | |
| 1707 | - return $out_date; | |
| 1375 | + return $date; | |
| 1708 | 1376 | } // Monthly recurring |
| 1709 | 1377 | |
| 1710 | 1378 | |
| 1711 | 1379 | // Prevent minutely recurring from affecting performance |
| @@ -1718,9 +1386,9 @@ | ||
| 1718 | 1386 | |
| 1719 | 1387 | |
| 1720 | 1388 | list($duration, $pause) = $this->getRecurringDurationInSeconds(); |
| 1721 | 1389 | |
| 1722 | - $period = CarbonPeriod::start($startDate, true); | |
| 1390 | + $period = CarbonPeriod::start($startDate); | |
| 1723 | 1391 | |
| 1724 | 1392 | $period->seconds($duration + $pause); |
| 1725 | 1393 | |
| 1726 | 1394 | if ($this->shouldEndRecurringByRecurrences()) { |
| @@ -1726,41 +1394,38 @@ | ||
| 1726 | 1394 | if ($this->shouldEndRecurringByRecurrences()) { |
| 1727 | 1395 | $period->setRecurrences($this->getRecurringRecurrences()); |
| 1728 | 1396 | } else { |
| 1729 | 1397 | $endDate = $this->getRecurringPeriodEndDate(); |
| 1730 | - $dateperiod_interval = new DateInterval('PT' .($duration + $pause) . 'S'); | |
| 1731 | - $period = new DatePeriod($startDate->toDateTime(), $dateperiod_interval, $endDate->addDays(7 * $interval)->toDateTime()); | |
| 1732 | - // $period->until($endDate->addDays(7 * $interval)); | |
| 1733 | - | |
| 1398 | + $period->until($endDate->addDays(7 * $interval)); | |
| 1734 | 1399 | } |
| 1735 | 1400 | |
| 1736 | - $date = null; | |
| 1401 | + $date = false; | |
| 1402 | + $skip = false; | |
| 1403 | + while ($period->valid()) { | |
| 1737 | 1404 | |
| 1738 | - $i = 0; | |
| 1405 | + $date = $period->current(); | |
| 1406 | + $skip_day = $this->should_skip_day($date); | |
| 1407 | + if ($date->greaterThan($now)) { | |
| 1739 | 1408 | |
| 1740 | - $pause_duration = $this->getRecurringPauseDuration(true); | |
| 1409 | + if ($skip_day) { | |
| 1741 | 1410 | |
| 1742 | - foreach ($period as $start) { | |
| 1411 | + $skip = true; | |
| 1743 | 1412 | |
| 1744 | - $start = Carbon::instance($start); | |
| 1745 | - | |
| 1746 | - $end = $start->copy()->addSeconds($this->getRecurringFrequencyInSeconds() - 1); | |
| 1413 | + if ($this->recurringUnselectedDaysAction === 'hide' || $this->isWeeklyRecurring()) { | |
| 1414 | + return false; | |
| 1415 | + } | |
| 1747 | 1416 | |
| 1748 | - if ($now->isBetween($start, $end->copy()->addSeconds($pause_duration))) { | |
| 1749 | - $date = $start->copy()->addSeconds($duration - 1); | |
| 1750 | - if (!in_array($date->format('w'), $this->recurringDays)) { | |
| 1417 | + $period->next(); | |
| 1751 | 1418 | continue; |
| 1752 | 1419 | } |
| 1753 | - break; | |
| 1754 | - } | |
| 1755 | 1420 | |
| 1756 | - if ($now->isBefore($end->copy()->addSeconds($pause_duration))) { | |
| 1757 | - $date = $start; | |
| 1758 | - if (!in_array($date->format('w'), $this->recurringDays)) { | |
| 1759 | - continue; | |
| 1421 | + if (!$skip) { | |
| 1422 | + $date = $pause ? $date->subSeconds($pause) : $date; | |
| 1760 | 1423 | } |
| 1761 | 1424 | break; |
| 1762 | 1425 | } |
| 1426 | + | |
| 1427 | + $period->next(); | |
| 1763 | 1428 | } |
| 1764 | 1429 | |
| 1765 | 1430 | if (empty($date)) { |
| 1766 | 1431 | return $period->getEndDate(); |
| @@ -1765,14 +1430,13 @@ | ||
| 1765 | 1430 | if (empty($date)) { |
| 1766 | 1431 | return $period->getEndDate(); |
| 1767 | 1432 | } |
| 1768 | 1433 | |
| 1769 | - $stop_date = Carbon::parse($this->recurringUntil, hurryt_tz($this->timezone)); | |
| 1434 | + $stop_date = Carbon::parse($this->recurringUntil, hurryt_tz()); | |
| 1770 | 1435 | |
| 1771 | 1436 | if ($this->shouldEndRecurringByDate() && $stop_date->lessThan($date)) { |
| 1772 | 1437 | return $stop_date; |
| 1773 | 1438 | } |
| 1774 | - | |
| 1775 | 1439 | return $date; |
| 1776 | 1440 | } catch (\Exception $e) { |
| 1777 | 1441 | return false; |
| 1778 | 1442 | } |
| @@ -1777,37 +1441,14 @@ | ||
| 1777 | 1441 | return false; |
| 1778 | 1442 | } |
| 1779 | 1443 | } |
| 1780 | 1444 | |
| 1781 | - | |
| 1782 | - function should_hide_today($date, $now) | |
| 1445 | + function should_skip_day($date) | |
| 1783 | 1446 | { |
| 1784 | - return ($date->format('w') === $now->format('w')) && ($this->isWeeklyRecurring() || $this->recurringUnselectedDaysAction === 'hide'); | |
| 1785 | - } | |
| 1786 | - function has_skipped_days() | |
| 1787 | - { | |
| 1788 | 1447 | $recur_days = array_map('intval', $this->recurringDays); |
| 1789 | - return count($recur_days) < 7; | |
| 1448 | + return !in_array($date->format('w'), $recur_days); | |
| 1790 | 1449 | } |
| 1791 | - function can_recur_on($date) | |
| 1792 | - { | |
| 1793 | - $recur_days = array_map('intval', $this->recurringDays); | |
| 1794 | 1450 | |
| 1795 | - if (in_array($date->format('w'), $recur_days)) { | |
| 1796 | - return true; | |
| 1797 | - } | |
| 1798 | - | |
| 1799 | - if (($date->isStartOfDay() && in_array($this->get_previous_day($date->format('w')), $recur_days))) { | |
| 1800 | - return true; | |
| 1801 | - } | |
| 1802 | - | |
| 1803 | - return false; | |
| 1804 | - } | |
| 1805 | - private function get_previous_day($current_day) | |
| 1806 | - { | |
| 1807 | - $current_day === 0 ? 6 : ($current_day - 1); | |
| 1808 | - } | |
| 1809 | - | |
| 1810 | 1451 | /** |
| 1811 | 1452 | * Returns compaign publish datetime. |
| 1812 | 1453 | * |
| 1813 | 1454 | * @return mixed |
| @@ -1964,12 +1605,8 @@ | ||
| 1964 | 1605 | * @param $labels |
| 1965 | 1606 | */ |
| 1966 | 1607 | public function setLabels($labels) |
| 1967 | 1608 | { |
| 1968 | - // Sanitize each label to prevent XSS | |
| 1969 | - if (is_array($labels)) { | |
| 1970 | - $labels = array_map('sanitize_text_field', $labels); | |
| 1971 | - } | |
| 1972 | 1609 | $labels = wp_parse_args($labels, $this->labels); |
| 1973 | 1610 | update_post_meta($this->id, 'labels', $labels); |
| 1974 | 1611 | } |
| 1975 | 1612 | |
| @@ -2001,13 +1638,13 @@ | ||
| 2001 | 1638 | return true; |
| 2002 | 1639 | } |
| 2003 | 1640 | |
| 2004 | 1641 | if ($this->is_recurring()) { |
| 2005 | - $start_date = Carbon::parse($this->recurringStartTime, hurryt_tz($this->timezone)); | |
| 2006 | - $now = Carbon::now(hurryt_tz($this->timezone)); | |
| 1642 | + $start_date = Carbon::parse($this->recurringStartTime, hurryt_tz()); | |
| 1643 | + $now = Carbon::now(hurryt_tz()); | |
| 2007 | 1644 | $now->second = $start_date->second; |
| 1645 | + | |
| 2008 | 1646 | if ($now->lessThan($start_date)) { |
| 2009 | - | |
| 2010 | 1647 | return true; |
| 2011 | 1648 | } |
| 2012 | 1649 | } |
| 2013 | 1650 | |
| @@ -2028,160 +1665,8 @@ | ||
| 2028 | 1665 | |
| 2029 | 1666 | return $endDate < $today; |
| 2030 | 1667 | } |
| 2031 | 1668 | |
| 2032 | - /** | |
| 2033 | - * Check if a regular campaign with multiple deadlines has all deadlines expired. | |
| 2034 | - * | |
| 2035 | - * @return bool | |
| 2036 | - */ | |
| 2037 | - public function is_all_date_ranges_expired() | |
| 2038 | - { | |
| 2039 | - $ranges = $this->getDateRanges(); | |
| 2040 | - if (empty($ranges)) { | |
| 2041 | - return false; // No ranges means single-date mode, handled by is_one_time_expired | |
| 2042 | - } | |
| 2043 | - | |
| 2044 | - $now = Carbon::now(hurryt_tz($this->timezone)); | |
| 2045 | - | |
| 2046 | - foreach ($ranges as $range) { | |
| 2047 | - if (empty($range['end'])) { | |
| 2048 | - continue; | |
| 2049 | - } | |
| 2050 | - $end = Carbon::parse($range['end'], hurryt_tz($this->timezone)); | |
| 2051 | - if ($end->greaterThan($now)) { | |
| 2052 | - return false; | |
| 2053 | - } | |
| 2054 | - } | |
| 2055 | - | |
| 2056 | - return true; | |
| 2057 | - } | |
| 2058 | - | |
| 2059 | - /** | |
| 2060 | - * Get the next upcoming deadline from the date ranges list. | |
| 2061 | - * | |
| 2062 | - * @return Carbon|null | |
| 2063 | - */ | |
| 2064 | - public function getActiveDateRange() | |
| 2065 | - { | |
| 2066 | - $this->loadSettings(); | |
| 2067 | - $ranges = $this->getDateRanges(); | |
| 2068 | - | |
| 2069 | - if (empty($ranges)) { | |
| 2070 | - return null; | |
| 2071 | - } | |
| 2072 | - | |
| 2073 | - $now = Carbon::now(hurryt_tz($this->timezone)); | |
| 2074 | - | |
| 2075 | - // Collect and sort end dates chronologically | |
| 2076 | - $endDates = []; | |
| 2077 | - foreach ($ranges as $range) { | |
| 2078 | - if (empty($range['end'])) { | |
| 2079 | - continue; | |
| 2080 | - } | |
| 2081 | - $endDates[] = Carbon::parse($range['end'], hurryt_tz($this->timezone)); | |
| 2082 | - } | |
| 2083 | - | |
| 2084 | - usort($endDates, function ($a, $b) { | |
| 2085 | - return $a->timestamp - $b->timestamp; | |
| 2086 | - }); | |
| 2087 | - | |
| 2088 | - // Return the first deadline that hasn't passed yet | |
| 2089 | - foreach ($endDates as $end) { | |
| 2090 | - if ($end->greaterThan($now)) { | |
| 2091 | - return $end; | |
| 2092 | - } | |
| 2093 | - } | |
| 2094 | - | |
| 2095 | - return null; | |
| 2096 | - } | |
| 2097 | - | |
| 2098 | - /** | |
| 2099 | - * Get all future deadlines (end dates that haven't expired yet), sorted chronologically. | |
| 2100 | - * | |
| 2101 | - * @return array Each entry: ['end' => Carbon, 'headline' => string] | |
| 2102 | - */ | |
| 2103 | - public function getFutureDateRanges() | |
| 2104 | - { | |
| 2105 | - $this->loadSettings(); | |
| 2106 | - $ranges = $this->getDateRanges(); | |
| 2107 | - | |
| 2108 | - if (empty($ranges)) { | |
| 2109 | - return []; | |
| 2110 | - } | |
| 2111 | - | |
| 2112 | - $now = Carbon::now(hurryt_tz($this->timezone)); | |
| 2113 | - $result = []; | |
| 2114 | - | |
| 2115 | - foreach ($ranges as $range) { | |
| 2116 | - if (empty($range['end'])) { | |
| 2117 | - continue; | |
| 2118 | - } | |
| 2119 | - $end = Carbon::parse($range['end'], hurryt_tz($this->timezone)); | |
| 2120 | - | |
| 2121 | - if ($end->greaterThan($now)) { | |
| 2122 | - $result[] = [ | |
| 2123 | - 'end' => $end, | |
| 2124 | - 'headline' => isset($range['headline']) ? $range['headline'] : '', | |
| 2125 | - ]; | |
| 2126 | - } | |
| 2127 | - } | |
| 2128 | - | |
| 2129 | - usort($result, function ($a, $b) { | |
| 2130 | - return $a['end']->timestamp - $b['end']->timestamp; | |
| 2131 | - }); | |
| 2132 | - | |
| 2133 | - return $result; | |
| 2134 | - } | |
| 2135 | - | |
| 2136 | - /** | |
| 2137 | - * Get date ranges array. | |
| 2138 | - * | |
| 2139 | - * @return array | |
| 2140 | - */ | |
| 2141 | - public function getDateRanges() | |
| 2142 | - { | |
| 2143 | - $ranges = $this->get_prop('date_ranges', false); | |
| 2144 | - if (!empty($ranges) && is_array($ranges)) { | |
| 2145 | - return $ranges; | |
| 2146 | - } | |
| 2147 | - return []; | |
| 2148 | - } | |
| 2149 | - | |
| 2150 | - /** | |
| 2151 | - * Set date ranges array. | |
| 2152 | - * | |
| 2153 | - * @param array|string $value | |
| 2154 | - */ | |
| 2155 | - public function setDateRanges($value) | |
| 2156 | - { | |
| 2157 | - if (is_string($value)) { | |
| 2158 | - $value = json_decode(stripslashes($value), true); | |
| 2159 | - } | |
| 2160 | - if (!is_array($value)) { | |
| 2161 | - $value = []; | |
| 2162 | - } | |
| 2163 | - // Filter out entries without an end date | |
| 2164 | - $value = array_filter($value, function ($entry) { | |
| 2165 | - return !empty($entry['end']); | |
| 2166 | - }); | |
| 2167 | - // Re-index | |
| 2168 | - $value = array_values($value); | |
| 2169 | - // Use update_post_meta directly to allow saving an empty array | |
| 2170 | - update_post_meta($this->get_id(), 'date_ranges', $value); | |
| 2171 | - } | |
| 2172 | - | |
| 2173 | - /** | |
| 2174 | - * Check if this regular campaign uses multiple deadlines. | |
| 2175 | - * | |
| 2176 | - * @return bool | |
| 2177 | - */ | |
| 2178 | - public function hasMultipleDateRanges() | |
| 2179 | - { | |
| 2180 | - $ranges = $this->getDateRanges(); | |
| 2181 | - return count($ranges) > 1; | |
| 2182 | - } | |
| 2183 | - | |
| 2184 | 1669 | public function is_sticky_dismissed() |
| 2185 | 1670 | { |
| 2186 | 1671 | return isset($_COOKIE[Cookie_Detection::COOKIE_PREFIX . $this->get_id() . '_dismissed']) |
| 2187 | 1672 | && $this->stickyBarDismissible === C::YES |
| @@ -2267,11 +1752,8 @@ | ||
| 2267 | 1752 | * @return bool |
| 2268 | 1753 | */ |
| 2269 | 1754 | public function is_expired() |
| 2270 | 1755 | { |
| 2271 | - if ($this->is_one_time() && $this->hasMultipleDateRanges()) { | |
| 2272 | - return $this->is_all_date_ranges_expired(); | |
| 2273 | - } | |
| 2274 | 1756 | return ($this->is_one_time() && $this->is_one_time_expired()) |
| 2275 | 1757 | || ($this->is_recurring() && $this->is_recurring_expired()); |
| 2276 | 1758 | } |
| 2277 | 1759 | |
| @@ -2341,115 +1823,5 @@ | ||
| 2341 | 1823 | private function isMinutelyRecurring() |
| 2342 | 1824 | { |
| 2343 | 1825 | return $this->recurringFrequency === C::RECURRING_MINUTELY; |
| 2344 | 1826 | } |
| 2345 | - | |
| 2346 | - /** | |
| 2347 | - * Get the end time for evergreen timers | |
| 2348 | - * | |
| 2349 | - * @return string|null | |
| 2350 | - */ | |
| 2351 | - public function getEndTime() | |
| 2352 | - { | |
| 2353 | - return $this->get_prop('end_time'); | |
| 2354 | - } | |
| 2355 | - | |
| 2356 | - /** | |
| 2357 | - * Set the end time for evergreen timers | |
| 2358 | - * | |
| 2359 | - * @param string $time | |
| 2360 | - */ | |
| 2361 | - public function setEndTime($time) | |
| 2362 | - { | |
| 2363 | - $this->set_prop('end_time', $time); | |
| 2364 | - } | |
| 2365 | - | |
| 2366 | - /** | |
| 2367 | - * Get the cookie name for this campaign | |
| 2368 | - * | |
| 2369 | - * @return string | |
| 2370 | - */ | |
| 2371 | - public function getCookieName() | |
| 2372 | - { | |
| 2373 | - return Cookie_Detection::cookieName($this->id); | |
| 2374 | - } | |
| 2375 | - | |
| 2376 | - /** | |
| 2377 | - * Get the reset token for this campaign | |
| 2378 | - * | |
| 2379 | - * @return string|null | |
| 2380 | - */ | |
| 2381 | - public function getResetToken() | |
| 2382 | - { | |
| 2383 | - $evergreenCampaign = new EvergreenCampaign($this->id); | |
| 2384 | - $evergreenCampaign->loadSettings(); | |
| 2385 | - return $evergreenCampaign->getInitiatedResetToken(); | |
| 2386 | - } | |
| 2387 | - | |
| 2388 | - /** | |
| 2389 | - * Check if the campaign should reset | |
| 2390 | - * | |
| 2391 | - * @return bool | |
| 2392 | - */ | |
| 2393 | - public function shouldReset() | |
| 2394 | - { | |
| 2395 | - $evergreenCampaign = new EvergreenCampaign($this->id); | |
| 2396 | - $evergreenCampaign->loadSettings(); | |
| 2397 | - return $evergreenCampaign->shouldResetTimer(); | |
| 2398 | - } | |
| 2399 | - | |
| 2400 | - /** | |
| 2401 | - * Get whether the campaign runs in background | |
| 2402 | - * | |
| 2403 | - * @return bool | |
| 2404 | - */ | |
| 2405 | - public function getRunInBackground() | |
| 2406 | - { | |
| 2407 | - return $this->get_prop('run_in_background', false); | |
| 2408 | - } | |
| 2409 | - | |
| 2410 | - /** | |
| 2411 | - * Get the end day for evergreen timers | |
| 2412 | - * | |
| 2413 | - * @return int | |
| 2414 | - */ | |
| 2415 | - public function getEvergreenEndDay() | |
| 2416 | - { | |
| 2417 | - return (int)$this->get_prop('evergreen_end_day', false) ?: 0; | |
| 2418 | - } | |
| 2419 | - | |
| 2420 | - /** | |
| 2421 | - * Set the end day for evergreen timers | |
| 2422 | - * | |
| 2423 | - * @param int $day | |
| 2424 | - */ | |
| 2425 | - public function setEvergreenEndDay($day) | |
| 2426 | - { | |
| 2427 | - $this->set_prop('evergreen_end_day', (int)$day); | |
| 2428 | - } | |
| 2429 | - | |
| 2430 | - public function getEvergreenEndTime() | |
| 2431 | - { | |
| 2432 | - return $this->get_prop('evergreen_end_time'); | |
| 2433 | - } | |
| 2434 | - | |
| 2435 | - public function setEvergreenEndTime($time) | |
| 2436 | - { | |
| 2437 | - $this->set_prop('evergreen_end_time', $time); | |
| 2438 | - } | |
| 2439 | - | |
| 2440 | - public function getEvergreenEndType() | |
| 2441 | - { | |
| 2442 | - return $this->get_prop('evergreen_end_type'); | |
| 2443 | - } | |
| 2444 | - | |
| 2445 | - public function setEvergreenEndType($type){ | |
| 2446 | - | |
| 2447 | - // removeIf(pro) | |
| 2448 | - if(! hurrytimer_is_pro() ){ | |
| 2449 | - $type = 'duration'; | |
| 2450 | - } | |
| 2451 | - // endRemoveIf(pro) | |
| 2452 | - $this->set_prop('evergreen_end_type', $type); | |
| 2453 | - } | |
| 2454 | - | |
| 2455 | 1827 | } |