<?php
/**
* Copyright (c) 2011-present Qualiteam software Ltd. All rights reserved.
* See https://www.x-cart.com/license-agreement.html for license details.
*/
namespace QSL\PopupAnywhere\Model;
use Doctrine\ORM\Mapping as ORM;
use QSL\PopupAnywhere\View\FormField\PixelOrPercent;
use QSL\PopupAnywhere\View\FormField\Select\AbsolutePixelOrPercent;
/**
* Popup model.
*
* @ORM\Entity (repositoryClass="\QSL\PopupAnywhere\Model\Repo\Popup")
* @ORM\Table (name="anywhere_popups")
*/
class Popup extends \XLite\Model\Base\I18n
{
public const TYPE_CUSTOM = 'Custom';
public const TYPE_TEMPLATE = 'Template';
public const TYPE_BAR_MESSAGE = 'NotificationBar';
public const TYPE_BAR_CART = 'MinicartBar';
public const TYPE_POPUP_NEWSLETTER = 'Subscription';
public const TYPE_POPUP_FACEBOOK = 'SocialPlugin';
public const DISPLAY_ON_LOAD = 0;
public const DISPLAY_ON_CLICK = 1;
public const DISPLAY_ONCE = 2;
public const DISPLAY_ON_EXIT = 3;
public const LOCATION_CENTER = 'center';
public const LOCATION_TOP = 'top';
public const LOCATION_BOTTOM = 'bottom';
public const LOCATION_LEFT_TOP = 'left_top_corner';
public const LOCATION_LEFT_BOTTOM = 'left_bottom_corner';
public const LOCATION_RIGHT_TOP = 'right_top_corner';
public const LOCATION_RIGHT_BOTTOM = 'right_bottom_corner';
public const ANIMATION_NONE = 0;
public const ANIMATION_FADE = 1;
public const ANIMATION_SLIDE = 2;
public const USERS_ALL = 0;
public const USERS_GUESTS = 1;
public const USERS_REGISTERED = 2;
public const TYPE_PERCENT = '%';
public const TYPE_ABSOLUTE = 'px';
/**
* Entity identifier.
*
* @var integer
*
* @ORM\Id
* @ORM\GeneratedValue (strategy="AUTO")
* @ORM\Column (type="integer", options={ "unsigned": true })
*/
protected $popup_id;
/**
* Whether it is enabled, or not.
*
* @var boolean
*
* @ORM\Column (type="boolean", options={ "default": 0 })
*/
protected $enabled = false;
/**
* Priority. The entity with the highest priority is selected when displaying a popup to the customer.
*
* @var integer
*
* @ORM\Column (type="integer", options={ "default": 0 })
*/
protected $position = 0;
/**
* Class that handles methods specific for the popup type.
*
* @var string
*
* @ORM\Column (type="string", length=255, options={ "default": "" })
*/
protected $popupType = self::TYPE_CUSTOM;
/**
* When to show the popup (on the page load / on a mouse click / ...)
*
* @var integer
*
* @ORM\Column (type="integer", options={ "default": 0 })
*/
protected $displayMode = self::DISPLAY_ON_LOAD;
/**
* Whether the Close button is visible, or not.
*
* @var boolean
*
* @ORM\Column (type="boolean", options={ "default": 1 })
*/
protected $showCloseButton = true;
/**
* Number of days before the popup appears for the same user once again.
*
* @var integer
*
* @ORM\Column (type="integer", options={ "default": 365 })
*/
protected $displayPeriod = 365;
/**
* Delay (in seconds) before the popup appears on the page.
*
* @var integer
*
* @ORM\Column (type="integer", options={ "default": 0 })
*/
protected $delay = 0;
/**
* Whether the overlay background is enabled, or not.
*
* @var boolean
*
* @ORM\Column (type="boolean", options={ "default": 0 })
*/
protected $modal = false;
/**
* Width of the popup
*
* @var string
*
* @ORM\Column (type="string", length=255, options={ "default": "" })
*/
protected $width = '';
/**
* Type Width of the popup ( % or px).
*
* @var string
*
* @ORM\Column (type="string", length=2)
*/
protected $widthType = self::TYPE_PERCENT;
/**
* Position of the popup.
*
* @var string
*
* @ORM\Column (type="string", length=255, options={ "default": "center" })
*/
protected $location = self::LOCATION_CENTER;
/**
* Popup animation.
*
* @var integer
*
* @ORM\Column (type="integer", options={ "default": 0 })
*/
protected $animation = 0;
/**
* URLs where the popup may be displayed.
*
* @var string
*
* @ORM\Column (type="text")
*/
protected $targetPages = '';
/**
* URLs where the popup may not be displayed.
*
* @var string
*
* @ORM\Column (type="text")
*/
protected $blockedPages = '';
/**
* Active from (UNIXSTAMP).
*
* @var integer
*
* @ORM\Column (type="integer", options={ "unsigned": true, "default": 0 })
*/
protected $activeFrom = 0;
/**
* Active till (UNIXSTAMP).
*
* @var integer
*
* @ORM\Column (type="integer", options={ "unsigned": true, "default": 0 })
*/
protected $activeTill = 0;
/**
* Path to the custom template.
*
* @var string
*
* @ORM\Column (type="string", length=255, options={ "default": "" })
*/
protected $customTemplate = '';
/**
* What users will see the popup.
*
* @var integer
*
* @ORM\Column (type="integer", options={ "default": 0 })
*/
protected $targetUsers = self::USERS_ALL;
// {{{ Exit offer-type related attributes
/**
* The offer is valid for customers with this minimum number of items in cart.
*
* @var integer
*
* @ORM\Column (type="integer")
*/
protected $minItemQty = 0;
/**
* The offer is valid for customers with this maximum number of items in cart.
*
* @var integer
*
* @ORM\Column (type="integer")
*/
protected $maxItemQty = 0;
/**
* The offer is valid for customers with this minimum cart subtotal.
*
* @var float
*
* @ORM\Column (type="decimal", precision=14, scale=4)
*/
protected $minCartTotal = 0;
/**
* The offer is valid for customers with this maximum cart subtotal.
*
* @var float
*
* @ORM\Column (type="decimal", precision=14, scale=4)
*/
protected $maxCartTotal = 0;
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\OneToMany (targetEntity="QSL\PopupAnywhere\Model\PopupTranslation", mappedBy="owner", cascade={"all"})
*/
protected $translations;
// }}}
/**
* Get the entity identifier.
*
* @return integer
*/
public function getId()
{
return $this->getPopupId();
}
/**
* Returns name of the popup widget class.
*
* @return string
*/
public function getPopupWidgetClassName()
{
$type = $this->getPopupType();
return $type ? ('\QSL\PopupAnywhere\View\Popup\\' . $type) : '';
}
/**
* Returns the string representation for the popup width.
*
* @return string
*/
public function getDisplayWidth()
{
return $this->getWidthValue() ? $this->getWidthValue() . $this->getWidthType() : 'auto';
}
/**
* Check if the URL matches one of the target URL patterns.
*
* @param string $url URL to match
*
* @return boolean
*/
public function matchesTargetUrlPattern($url)
{
$matches = false;
if ($url && $this->getTargetPages()) {
$urlNorm = $this->normalizeUrlForComparison($url);
foreach ($this->getTargetUrlPatterns() as $pattern) {
if ($pattern && strpos($urlNorm, $this->normalizePatternForComparison($pattern)) !== false) {
$matches = true;
break;
}
}
} else {
$matches = true;
}
return $matches;
}
/**
* Normilizes URL before comparing
*
* @param string $url
*
* @return string
*/
protected function normalizeUrlForComparison($url)
{
$urlParts = parse_url($url);
$path = isset($urlParts['path'])
? str_replace('/index.php', '/', $urlParts['path'])
: '/';
$query = $urlParts['query'] ?? '';
return strtolower(trim("{$path}?{$query}"));
}
/**
* Normalize pattern for comparison.
*
* @param string $pattern URL pattern.
*
* @return string
*/
protected function normalizePatternForComparison(string $pattern): string
{
return strtolower($pattern);
}
/**
* Check if the URL matches one of the blocked URL patterns.
*
* @param string $url URL to match
*
* @return boolean
*/
public function matchesBlockedUrlPattern($url)
{
$matches = false;
$url = strtolower($url);
if ($url) {
foreach ($this->getBlockedUrlPatterns() as $pattern) {
if ($pattern && strpos($url, strtolower(trim($pattern))) !== false) {
$matches = true;
break;
}
}
}
return $matches;
}
/**
* Returns the popoup identifier.
*
* @return integer
*/
public function getPopupId()
{
return $this->popup_id;
}
/**
* Set whether the popup is enabled, or not.
*
* @param boolean $enabled New state
*
* @return Popup
*/
public function setEnabled($enabled)
{
$this->enabled = $enabled;
return $this;
}
/**
* Check if the popup is enabled.
*
* @return boolean
*/
public function getEnabled()
{
return $this->enabled;
}
/**
* Set whether the Close button is visible, or not.
*
* @param boolean $state New state
*
* @return Popup
*/
public function setShowCloseButton($state)
{
$this->showCloseButton = $state;
return $this;
}
/**
* Check if the Close button is visible.
*
* @return boolean
*/
public function getShowCloseButton()
{
return $this->showCloseButton;
}
/**
* Sets the popup position.
*
* @param integer $position New position.
*
* @return Popup
*/
public function setPosition($position)
{
$this->position = $position;
return $this;
}
/**
* Returns the popup position.
*
* @return integer
*/
public function getPosition()
{
return $this->position;
}
/**
* Updates the popup type.
*
* @param string $popupType New popup type
*
* @return Popup
*/
public function setPopupType($popupType)
{
$this->popupType = $popupType;
return $this;
}
/**
* Returns the popup type.
*
* @return string
*/
public function getPopupType()
{
return $this->popupType;
}
/**
* Sets the popup display mode.
*
* @param integer $displayMode New display mode.
*
* @return Popup
*/
public function setDisplayMode($displayMode)
{
$this->displayMode = $displayMode;
return $this;
}
/**
* Get displayMode
*
* @return integer
*/
public function getDisplayMode()
{
return $this->displayMode;
}
/**
* Updates the display period.
*
* @param integer $displayPeriod New period
*
* @return Popup
*/
public function setDisplayPeriod($displayPeriod)
{
$this->displayPeriod = $displayPeriod;
return $this;
}
/**
* Returns the display period.
*
* @return integer
*/
public function getDisplayPeriod()
{
return $this->displayPeriod;
}
/**
* Sets the delay before the popup appears on the page.
*
* @param integer $delay New delay in seconds
*
* @return Popup
*/
public function setDelay($delay)
{
$this->delay = $delay;
return $this;
}
/**
* Returns the delay (in seconds) before the popup appears on the page.
*
* @return integer
*/
public function getDelay()
{
return $this->delay;
}
/**
* Sets whether the popup should be modal, or not.
*
* @param boolean $modal Status
*
* @return Popup
*/
public function setModal($modal)
{
$this->modal = $modal;
return $this;
}
/**
* Checks if the popup is modal.
*
* @return boolean
*/
public function getModal()
{
return $this->modal;
}
/**
* Sets the popup width.
*
* @param string $width New width
*
* @return Popup
*/
public function setWidth($width)
{
$this->setWidthValue(
$width[PixelOrPercent::PRICE_VALUE] ?? 0
);
$this->setWidthType(
isset($width[PixelOrPercent::TYPE_VALUE])
&& $width[PixelOrPercent::TYPE_VALUE] === AbsolutePixelOrPercent::TYPE_PERCENT
? static::TYPE_PERCENT
: static::TYPE_ABSOLUTE
);
return $this;
}
/**
* Returns the popup width.
*
* @return array
*/
public function getWidth()
{
return [
PixelOrPercent::PRICE_VALUE => $this->getWidthValue(),
PixelOrPercent::TYPE_VALUE => $this->getWidthType() === static::TYPE_PERCENT
? AbsolutePixelOrPercent::TYPE_PERCENT
: AbsolutePixelOrPercent::TYPE_ABSOLUTE
];
}
/**
* Set width value
*
* @param float $value
*
* @return Popup
*/
public function setWidthValue($value)
{
$this->width = $value;
return $this;
}
/**
* Get width value
*
* @return float
*/
public function getWidthValue()
{
return $this->width;
}
/**
* Set width type
*
* @param string $type
*
* @return Popup
*/
public function setWidthType($type)
{
$this->widthType = $type;
return $this;
}
/**
* Get width type
*
* @return string
*/
public function getWidthType()
{
return $this->widthType;
}
/**
* Updates the popup location.
*
* @param string $location New location
*
* @return Popup
*/
public function setLocation($location)
{
$this->location = $location;
return $this;
}
/**
* Returns the popup location.
*
* @return string
*/
public function getLocation()
{
return $this->location;
}
/**
* Sets the popup animation mode.
*
* @param integer $animation New animation mode.
*
* @return Popup
*/
public function setAnimation($animation)
{
$this->animation = $animation;
return $this;
}
/**
* Returns the popup animation mode.
*
* @return integer
*/
public function getAnimation()
{
return $this->animation;
}
/**
* Sets the pages where the popup should appear.
*
* @param string $targetPages URL patterns (multiline - one line per page)
*
* @return Popup
*/
public function setTargetPages($targetPages)
{
$this->targetPages = $targetPages;
return $this;
}
/**
* Returns URL patterns for the pages where the popup should appear.
*
* The result is a multiline string having one line per page.
*
* @return string
*/
public function getTargetPages()
{
return $this->targetPages ?: '';
}
/**
* Sets the pages where the popup should never appear.
*
* @param string $blockedPages URL patterns (multiline - one line per page)
*
* @return Popup
*/
public function setBlockedPages($blockedPages)
{
$this->blockedPages = $blockedPages;
return $this;
}
/**
* Returns URL patterns for the pages where the popup should never appear.
*
* The result is a multiline string having one line per page.
*
* @return string
*/
public function getBlockedPages()
{
return $this->blockedPages ?: '';
}
/**
* Set the date from which the popup may appear on the page.
*
* @param integer $activeFrom UNIX timestamp
*
* @return Popup
*/
public function setActiveFrom($activeFrom)
{
$this->activeFrom = (int) $activeFrom;
return $this;
}
/**
* Returns UNIX timestamp for the date from which the popup may appear on the page.
*
* @return integer
*/
public function getActiveFrom()
{
return $this->activeFrom;
}
/**
* Set the date after which the popup may not appear on the page.
*
* @param integer $activeTill UNIX timestamp
*
* @return Popup
*/
public function setActiveTill($activeTill)
{
$this->activeTill = (int) $activeTill;
return $this;
}
/**
* Returns UNIX timestamp for the date after which the popup may not appear on the page.
*
* @return integer
*/
public function getActiveTill()
{
return $this->activeTill;
}
/**
* Specifies a custom template file for the popup.
*
* @param string $customTemplate Path to the template file
*
* @return Popup
*/
public function setCustomTemplate($customTemplate)
{
$this->customTemplate = $customTemplate;
return $this;
}
/**
* Returns the path to the custom template file that should be used for the popup.
*
* @return string
*/
public function getCustomTemplate()
{
return $this->customTemplate;
}
/**
* Configures which users the popup may appear for.
*
* @param integer $targetUsers New mode
*
* @return Popup
*/
public function setTargetUsers($targetUsers)
{
$this->targetUsers = $targetUsers;
return $this;
}
/**
* Determines which users the popup may appear for.
*
* @return integer
*/
public function getTargetUsers()
{
return $this->targetUsers;
}
/**
* Returns URL patterns for pages where the popup may be displayed.
*
* @return array
*/
protected function getTargetUrlPatterns()
{
$patterns = [];
foreach (explode(',', $this->getTargetPages()) as $line) {
$patterns[] = explode("\n", $line);
}
return array_merge(...$patterns);
}
/**
* Returns URL patterns for pages where the popup may not be displayed.
*
* @return array
*/
protected function getBlockedUrlPatterns()
{
$patterns = [];
foreach (explode(',', $this->getBlockedPages()) as $line) {
$patterns[] = explode("\n", $line);
}
return array_merge(...$patterns);
}
// {{{ Exit offer-type related attributes
/**
* Sets the min number of items in the cart for the exit offer to appear.
*
* @param integer $minItemQty Min number of items in cart
*
* @return self
*/
public function setMinItemQty($minItemQty)
{
$this->minItemQty = $minItemQty;
return $this;
}
/**
* Returns the min number of items in the cart for the exit offer to appear.
*
* @return integer
*/
public function getMinItemQty()
{
return $this->minItemQty;
}
/**
* Sets the max number of items in the cart for the exit offer to appear.
*
* @param integer $maxItemQty Max number of items in cart
*
* @return self
*/
public function setMaxItemQty($maxItemQty)
{
$this->maxItemQty = $maxItemQty;
return $this;
}
/**
* Returns the max number of items in the cart for the exit offer to appear.
*
* @return integer
*/
public function getMaxItemQty()
{
return $this->maxItemQty;
}
/**
* Sets the min cart total for the exit offer to appear.
*
* @param float $minCartTotal Min total
*
* @return self
*/
public function setMinCartTotal($minCartTotal)
{
$this->minCartTotal = $minCartTotal;
return $this;
}
/**
* Returns the min cart total for the exit offer to appear.
*
* @return float
*/
public function getMinCartTotal()
{
return $this->minCartTotal;
}
/**
* Sets the max cart total for the exit offer to appear.
*
* @param float $maxCartTotal Max total
*
* @return self
*/
public function setMaxCartTotal($maxCartTotal)
{
$this->maxCartTotal = $maxCartTotal;
return $this;
}
/**
* Returns the max cart total for the exit offer to appear.
*
* @return float
*/
public function getMaxCartTotal()
{
return $this->maxCartTotal;
}
// }}}
// {{{ Translation Getters / setters
/**
* @return string
*/
public function getCustomHeader()
{
return $this->getTranslationField(__FUNCTION__);
}
/**
* @param string $customHeader
*
* @return \XLite\Model\Base\Translation
*/
public function setCustomHeader($customHeader)
{
return $this->setTranslationField(__FUNCTION__, $customHeader);
}
/**
* @return string
*/
public function getBody()
{
return $this->getTranslationField(__FUNCTION__);
}
/**
* @param string $body
*
* @return \XLite\Model\Base\Translation
*/
public function setBody($body)
{
return $this->setTranslationField(__FUNCTION__, $body);
}
// }}}
}