'days', 'hours' => 'hrs', 'minutes' => 'mins', 'seconds' => 'secs', ]; /** * Digit color. * * @var string */ public $digitColor = "#000"; /** * Digit size. * * @var int */ public $digitSize = 35; /** * Redirect action url. * * @var string */ public $redirectUrl; /** * Label size. * * @var int */ public $labelSize = 12; /** * Label color. * * @var string */ public $labelColor = "#000"; /** * End action. * * @var array */ public $actions = []; /** * WooCommerce compaign position in product page. * * @var int */ public $wcPosition = C::WC_POSITION_ABOVE_TITLE; /** * Enable/disable woocommerce integration. * * @var string */ public $wcEnable = C::NO; /** * WooCommerce products selection. * * @var array */ public $wcProductsSelection; /** * WooCommerce products selection type. * * @var int */ public $wcProductsSelectionType; /** * Timer block border color. * * @var string */ public $blockBorderColor = ""; /** * Timer Block border width. * * @var int */ public $blockBorderWidth = 0; /** * Timer block radius. * * @var int */ public $blockBorderRadius = 0; /** * Block size. * * @var int */ public $blockSize = 50; /** * Block background color. * * @var string */ public $blockBgColor = ''; /** * Block spacing. * * @var int */ public $blockSpacing = 5; /** * Block padding. * * @var int */ public $blockPadding = 0; /** * Block spearator visibility. * * @var boolean */ public $blockSeparatorVisibility = C::YES; /** * Label case * * @var string */ public $labelCase = C::TRANSFORM_UPPERCASE; /** * Custom CSS * * @var string */ public $customCss = ''; /** * Block elements display * Values: block, inline * * @var string */ public $blockDisplay = 'block'; /** * Enable sticky bar. */ public $enableSticky = C::NO; /** * Sticky bar background color. * * @var string */ public $stickyBarBgColor = '#eee'; /** * Sticky bar close button color. * * @var string */ public $stickyBarCloseBtnColor = '#fff'; /** * Sticky bar position. * Values: top, bottom * * @var string */ public $stickyBarPosition = 'top'; /** * Sticky bar padding. * * @var integer */ public $stickyBarPadding = 5; /** * Sticky bar display pages. * * @var array */ public $stickyBarPages = []; /** * Where to display the sticky bar option * * @var string */ public $stickyBarDisplayOn = 'all_pages'; /** * Show sticky bar close button? * * @var string */ public $stickyBarDismissible = C::YES; /** * CTA settings. * * @var array */ public $callToAction = [ 'enabled' => C::NO, 'new_tab' => C::NO, 'url' => '', 'text' => 'Learn More', 'text_size' => 15, 'text_color' => '#fff', 'bg_color' => '#000', 'y_padding' => 10, 'x_padding' => 15, 'border_radius' => 3, 'spacing' => 5, ]; /** * Campaign elements display * values: block,inline * * @var string */ public $campaignDisplay = 'block'; /** * Campaign aligments * values: center,left,right * * @var string */ public $campaignAlign = 'center'; /** * Campaign spacing. * * @var integer */ public $campaignSpacing = 10; /** * Campaign horizontal padding. * * @var integer */ public $campaignXPadding = 10; /** * Campaign vertical padding. * * @var integer */ public $campaignYPadding = 10; public function __construct($id) { // Default recurring timezone. $this->recurringTimezone = Utils\Helpers::getSiteTimezone(); $this->recurringStartTime = current_time('Y-m-d h:i A'); $this->id = $id; } /** * Returns compaign post iD. * * @return int */ public function getId() { return $this->id; } public function showStickyBarOn($pageId) { if ($this->enableSticky === C::NO) { return true; } switch ($this->getStickyBarDisplayOn()) { case 'all_pages': return true; case 'wc_products_pages': if (function_exists('is_product') && is_product()) { $wc_campaign = new WCCampaign(); return ($wc_campaign->hasActiveCampaign($this, $pageId)); } return false; case 'specific_pages': $pages = $this->getStickyBarPages(); foreach ($pages as $page) { if ($page == $pageId) { return true; } } return false; } return true; } public function getStickyBarPages() { return $this->getRawSetting('sticky_bar_pages'); } public function getStickyBarDisplayOn() { // backward compat. $all_pages = $this->getRawSetting('sticky_bar_show_on_all_pages', false); if ($all_pages === C::YES) { $this->setStickyBarDisplayOn('all_pages'); } $this->deleteRawSetting('sticky_bar_show_on_all_pages'); $value = $this->getRawSetting('_hurryt_sticky_bar_display_on', false); return ! empty($value) ? $value : $this->stickyBarDisplayOn; } public function setStickyBarDisplayOn($value) { $this->storeRawSetting('_hurryt_sticky_bar_display_on', $value); } /** * Get raw setting. * * @param string $name * @param boolean * * @return mixed */ public function getRawSetting($name, $useDefault = true) { $value = get_post_meta($this->id, $name, true); if ( ! empty($value)) { return $value; } if ($useDefault) { return $this->{Helpers::snakeToCamelCase($name)}; } return $value; } public function storeRawSetting($name, $value) { $value = ! empty($value) ? $value : $this->{Helpers::snakeToCamelCase($name)}; update_post_meta($this->id, $name, $value); } /** * Bulk save for compaign settings. * * @param $data */ public function storeSettings($data) { foreach ($data as $prop => $value) { $method = Helpers::snakeToCamelCase("set_{$prop}"); if (method_exists($this, $method)) { $this->$method($value ?: $this->$prop); } elseif (property_exists(__CLASS__, Helpers::snakeToCamelCase($prop))) { $this->storeRawSetting($prop, $value); } } self::buildCss(); } //removeIf(pro) /** * @param int $mode */ public function setMode($mode) { if($mode == C::MODE_RECURRING){ return; } $this->storeRawSetting('mode',$mode); } //endRemoveIf(pro) /** * Build User CSS, * Then merge it with base one. * * @return void */ public static function buildCss() { // Build and return CSS ob_start(); include HURRYT_DIR . 'includes/css.php'; $css = ob_get_clean(); $base = file_get_contents(HURRYT_DIR . '/assets/css/base.css'); // Merge built and base css. $base .= $css; // Save to public file. file_put_contents(HURRYT_DIR . '/assets/css/hurrytimer.css', $base); } private function setRecurringDates($dates) { foreach ($dates as $d) { add_post_meta($this->getId(), '_hurryt_recurring_dates', $d); } } public function loadSettings() { $reflection = new \ReflectionObject($this); foreach ($reflection->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) { $name = $prop->getName(); $method = 'get' . ucfirst($name); if (method_exists($this, $method)) { $this->{$name} = $this->$method(); } else { $this->{$name} = $this->getRawSetting(Helpers::camelToSnakeCase($name)); } } } /** * Returns compaign headline. * * @return mixed */ public function getHeadline() { return $this->id ? get_the_title($this->id) : $this->headline; } public function isPublished() { return get_post_status($this->id) === "publish"; } public function isWcEnabled() { return $this->getWcEnable() === C::YES; } /** * Check current countdown timer mode * * @return bool */ public function isEvergreen() { return $this->getRawSetting('mode') == C::MODE_EVERGREEN; } public function isRegular() { return $this->getRawSetting('mode') == C::MODE_REGULAR; } public function isRecurring() { return $this->getRawSetting('mode') == C::MODE_RECURRING; } /** * Save compaign endtime for regular mode. * * @param $date */ public function setEndDatetime($date) { $this->storeRawSetting('end_datetime', $date ?: $this->defaultEndDatetime()); } /** * Returns default end datetime for regular mode. * * @return false|string */ private function defaultEndDatetime() { return date('Y-m-d h:i A', strtotime('+1 week')); } /** * Save digit color. * * @param $color */ public function setDigitColor($color) { $this->storeRawSetting('digit_color', $color); } /** * Returns headline visibility. * * @return mixed */ public function getHeadlineVisibility() { $meta = 'headline_visibility'; $value = $this->getRawSetting($meta, false); if ($value === C::NO || $value === C::YES) { return $value; } $legacyMeta = 'display_headline'; $legacyValue = filter_var($this->getLegacySetting($legacyMeta), FILTER_VALIDATE_BOOLEAN); $legacyValue = $legacyValue ? C::YES : C::NO; $this->storeRawSetting($meta, $legacyValue); $this->deleteRawSetting($legacyMeta); return $this->getRawSetting($meta); } /** * Returns digit color. * Backward compat with older versions. * * @return mixed */ public function getDigitColor() { $value = $this->getRawSetting('digit_color', false); if ($value) { return $value; } $legacy = $this->getLegacySetting('text_color'); if ( ! $legacy) { return $this->digitColor; } $this->setDigitColor($legacy); if ( ! $this->getRawSetting('label_color', false)) { $this->setLabelColor($legacy); } $this->deleteRawSetting('text_color'); return $this->getRawSetting('digit_color'); } public function setLabelColor($color) { $this->storeRawSetting('label_color', $color); } /** * Get label color * * @return mixed */ public function getLabelColor() { $value = $this->getRawSetting('label_color', false); if ($value) { return $value; } $legacy = $this->getLegacySetting('text_color'); if ( ! $legacy) { return $this->labelColor; } $this->setLabelColor($legacy); if ( ! $this->getRawSetting('digit_color', false)) { $this->setDigitColor($legacy); } $this->deleteRawSetting('text_color'); return $this->getRawSetting('label_color'); } /** * * Return timer digit size. * Backward comapt. with older versions. * * @return int * @since 1.2.4 */ public function getDigitSize() { $meta = 'digit_size'; $value = $this->getRawSetting($meta, false); if ( ! empty($value)) { return $value; } $legacy = $this->getLegacySetting('text_size'); if (empty($legacy)) { return $this->digitSize; } $this->setDigitSize($legacy); $this->deleteRawSetting('text_size'); return $this->getRawSetting('digit_size'); } /** * Save timer digit size. * * @param $size */ public function setDigitSize($size) { $this->storeRawSetting('digit_size', $size); } /** * Save timer label size. * * @param $size */ public function setLabelSize($size) { $this->storeRawSetting('label_size', $size); } public function setHeadlineSize($size) { $this->storeRawSetting('headline_size', $size); } /** * Returns evergreen duration. * * @return array */ public function getDuration() { $default = [0, 0, 0, 0]; $duration = $this->getRawSetting('duration'); if (is_array($duration)) { $duration = array_merge($duration, $default); return array_map('intval', $duration); } return $default; } public function setRecurringDuration($value) { $this->storeRawSetting('_hurryt_recurring_duration', $value); } public function setRecurringPauseDuration($value) { $this->storeRawSetting('_hurryt_recurring_pause_duration', $value); } /** * Returns evergreen duration. * * @return array */ public function getRecurringDuration() { $default = [0, 0, 0, 0]; $duration = $this->getRawSetting('_hurryt_recurring_duration', false); if (is_array($duration)) { return array_map('intval', array_merge($duration, $default)); } return $default; } public function getRecurringPauseDuration() { $default = [0, 0, 0, 0]; $duration = $this->getRawSetting('_hurryt_recurring_pause_duration', false); if (is_array($duration)) { $duration = array_merge($duration, $default); return array_map('intval', $duration); } return $default; } /** * Returns actions array. * * @return array */ public function getActions() { $legacy = $this->getLegacySetting('end_action'); if ($legacy) { $redirectUrl = $this->getLegacySetting('redirect_url'); $actions = [ [ 'id' => intval($legacy), 'redirectUrl' => $redirectUrl, ], ]; $this->storeRawSetting('actions', $actions); $this->deleteRawSetting('end_action'); $this->deleteRawSetting('redirect_url'); return $this->mergeActions($actions); } return $this->mergeActions($this->getRawSetting('actions')); } private function mergeActions($actions) { $defaults = [ [ 'id' => C::ACTION_NONE, 'redirectUrl' => '', 'message' => '', 'wcStockStatus' => '', ], ]; if (count($actions) === 0) { return $defaults; } return array_map(function ($action) use ($defaults) { $action['id'] = (int)$action['id']; return array_merge($defaults[0], $action); }, $actions); } /** * Returns evergreen duration in seconds. * * @param array $duration * * @return int */ public function durationArrayToSeconds($duration = []) { list($d, $h, $m, $s) = empty($duration) ? $this->getDuration() : $duration; return $d * DAY_IN_SECONDS + $h * HOUR_IN_SECONDS + $m * MINUTE_IN_SECONDS + $s; } /** * Returns end datetime. * * @return string */ public function getEndDatetime() { return $this->getRawSetting('end_datetime') ?: $this->defaultEndDatetime(); } private function getRecurringOccurencesCount() { return $this->getRawSetting('hurryt_recurring_occurences_count', false); } private function incrementRecurringOccurencesCount() { $count = absint($this->getRecurringOccurencesCount()); $this->storeRawSetting('_hurryt_recurring_occurences_count', ++$count); } public function isRecurringExpired() { $deadline = $this->getRecurringDeadline(); if($deadline === null) return false; $now = current_time('mysql'); return $now > strtotime($deadline); } public function getRecurringCurrentDate() { $dates = $this->getRecurringDates(); $now = current_time('timestamp'); foreach ($dates as $d) { // Scheduled if (strtotime($d) > $now) { continue; // Running } else { return $d; } } return null; } public function getRecurringDeadline($date = null) { $currentDate = $date === null ? $this->getRecurringCurrentDate() : $date; if ($currentDate === null) { return null; } $duration = $this->durationArrayToSeconds($this->getRecurringDuration()); return date('Y-m-d H:i:s', strtotime("+ $duration seconds", strtotime($currentDate))); } public function getRecurringDates() { $dates = get_post_meta($this->getId(), '_hurryt_recurring_dates'); return array_reverse($dates, true); } /** * Returns compaign publish datetime. * * @return mixed */ public function getStartTimestamp() { return get_the_date($this->id); } /** * Returns position in WooCommerce product page. * * @return mixed */ public function getWcPosition() { $legacy = $this->getLegacySetting('position'); if ( ! $legacy) { return $this->getRawSetting('wc_position'); } $this->storeRawSetting('wc_position', $legacy); $this->deleteRawSetting('position'); return $legacy; } private function getLegacySetting($name) { return get_post_meta($this->id, $name, true); } /** * Returns true if WooCommerce integration is enabled. * * @return mixed */ public function getWcEnable() { $value = $this->getRawSetting('wc_enable', false); if ($value === C::YES || $value === C::NO) { return $value; } $legacy = filter_var($value, FILTER_VALIDATE_BOOLEAN); if ($legacy) { $this->storeRawSetting('wc_enable', C::YES); } else { $this->storeRawSetting('wc_enable', C::NO); } return $this->getRawSetting('wc_enable'); } /** * Returns true if label should be displayed. * * @return mixed */ public function getLabelVisibility() { $meta = 'label_visibility'; $value = $this->getRawSetting($meta, false); if ($value === C::NO || $value === C::YES) { return $value; } $legacy = filter_var($this->getLegacySetting('display_labels'), FILTER_VALIDATE_BOOLEAN); $legacy = $legacy ? C::YES : C::NO; $this->storeRawSetting($meta, $legacy); $this->deleteRawSetting('display_labels'); return $this->getRawSetting($meta); } /** * * Returns restart type. * * @return int */ public function getRestart() { return $this->getRawSetting('restart') ?: C::RESTART_NONE; } /** * Returns WooCommerce products selection type. * * @return string */ public function getWcProductsSelectionType() { $legacy = $this->getLegacySetting('products_type'); if ( ! $legacy) { return $this->getRawSetting('wc_products_selection_type'); } $this->storeRawSetting('wc_products_selection_type', $legacy); $this->deleteRawSetting('products_type'); return $legacy; } /** * Delete setting item. * * @param $name */ public function deleteRawSetting($name) { delete_post_meta($this->id, $name); } /** * Returns products selection IDs. * * @return array */ public function getWcProductsSelection() { $legacy = $this->getLegacySetting('products'); if ( ! $legacy) { return $this->getRawSetting('wc_products_selection'); } $this->storeRawSetting('wc_products_selection', $legacy); $this->deleteRawSetting('products'); return $legacy; } /** * Store custom labels. * * @param $labels */ public function setLabels($labels) { $labels = array_merge($this->labels, array_filter($labels)); update_post_meta($this->id, 'labels', $labels); } /** * Returns true if compaign can be published. * * @return bool */ public function isActive() { return get_post_status($this->id) === "publish" || get_post_status($this->id) === "future"; } /** * Returns trus if the compaign is scheduled. * * @return bool */ public function isScheduled() { return get_post_status($this->getId()) === "future"; } /** * Returns true if fixed campaign datetime is expired. * * @param string|null $date * * @return bool */ public function isExpired($date = null) { $endDate = $date === null ? date_create($this->endDatetime) : $date; $today = date_create(current_time("mysql")); return $endDate < $today; } public function isStickyDismissed() { return isset($_COOKIE[CookieDetection::COOKIE_PREFIX . $this->getId() . '_dismissed']) && $this->stickyBarDismissible === C::YES && $this->enableSticky === C::YES; } /** * Returns compaign template wrapper. * * @param string * * @return string */ public function wrapTemplate($content) { $campaignBuilder = new CampaignBuilder($this); return $campaignBuilder->build($content); } /* * Returns campaign template content. */ public function buildTemplate() { $campaignBuilder = new CampaignBuilder($this); return $campaignBuilder->template(); } public function getRecurringDeadlinesWithGaps() { $dates = $this->getRecurringDates(); if (empty($dates)) { return []; } $currentDate = $this->getRecurringCurrentDate(); $currentDateIndex = array_search($currentDate, $dates, true); $nextDates = array_reverse(array_slice($dates, 0, -$currentDateIndex - 1)); $datesWithGap = []; for ($i = 0; $i < count($nextDates); $i++) { array_push($datesWithGap, [ 'date' => $this->getRecurringDeadline($nextDates[$i]), 'wait' => strtotime($nextDates[$i]) - strtotime($this->getRecurringDeadline()), ]); } return $datesWithGap; } }