Skip to content
Code-Schnipsel Gruppen Projekte
CouponCode.php 9,4 KiB
Newer Older
  • Learn to ignore specific revisions
  • Patrick Müller's avatar
    Patrick Müller committed
    <?php
    
    namespace QUI\ERP\Coupons;
    
    use QUI;
    use QUI\Permissions\Permission;
    
    /**
    
    Patrick Müller's avatar
    Patrick Müller committed
     * Class CouponCode
    
    Patrick Müller's avatar
    Patrick Müller committed
     */
    class CouponCode
    {
        /**
    
    Patrick Müller's avatar
    Patrick Müller committed
         * CouponCode ID
    
    Patrick Müller's avatar
    Patrick Müller committed
         *
         * @var int
         */
        protected $id;
    
        /**
         * Actual code
         *
         * @var string
         */
        protected $code;
    
        /**
    
    Patrick Müller's avatar
    Patrick Müller committed
         * IDs of users that this CouponCode is restricted to
    
    Patrick Müller's avatar
    Patrick Müller committed
         *
    
    Patrick Müller's avatar
    Patrick Müller committed
         * @var array
    
    Patrick Müller's avatar
    Patrick Müller committed
         */
    
    Patrick Müller's avatar
    Patrick Müller committed
        protected $userIds = [];
    
    Patrick Müller's avatar
    Patrick Müller committed
    
        /**
    
    Patrick Müller's avatar
    Patrick Müller committed
         * IDs of groups that this CouponCode is restricted to
    
    Patrick Müller's avatar
    Patrick Müller committed
         *
    
    Patrick Müller's avatar
    Patrick Müller committed
         * @var array
    
    Patrick Müller's avatar
    Patrick Müller committed
         */
    
    Patrick Müller's avatar
    Patrick Müller committed
        protected $groupIds = [];
    
    Patrick Müller's avatar
    Patrick Müller committed
    
        /**
    
    Patrick Müller's avatar
    Patrick Müller committed
         * List of usages of this CouponCode
    
    Patrick Müller's avatar
    Patrick Müller committed
         *
    
    Patrick Müller's avatar
    Patrick Müller committed
         * @var array
    
    Patrick Müller's avatar
    Patrick Müller committed
         */
    
    Patrick Müller's avatar
    Patrick Müller committed
        protected $usages = [];
    
    Patrick Müller's avatar
    Patrick Müller committed
    
        /**
    
    Patrick Müller's avatar
    Patrick Müller committed
         * Creation Date
    
    Patrick Müller's avatar
    Patrick Müller committed
         *
         * @var \DateTime
         */
    
    Patrick Müller's avatar
    Patrick Müller committed
        protected $CreateDate;
    
    Patrick Müller's avatar
    Patrick Müller committed
    
        /**
    
    Patrick Müller's avatar
    Patrick Müller committed
         * Date until the CouponCode is valid
    
    Patrick Müller's avatar
    Patrick Müller committed
         *
         * @var \DateTime
         */
        protected $ValidUntilDate = null;
    
        /**
    
    Patrick Müller's avatar
    Patrick Müller committed
         * CouponCode title
    
    Patrick Müller's avatar
    Patrick Müller committed
         *
         * @var string
         */
    
    Patrick Müller's avatar
    Patrick Müller committed
        protected $title = null;
    
    Patrick Müller's avatar
    Patrick Müller committed
    
        /**
    
    Patrick Müller's avatar
    Patrick Müller committed
         * Flag - Is the CouponCode valid?
    
    Patrick Müller's avatar
    Patrick Müller committed
         *
         * @var bool
         */
    
    Patrick Müller's avatar
    Patrick Müller committed
        protected $valid = true;
    
    Patrick Müller's avatar
    Patrick Müller committed
    
        /**
    
    Patrick Müller's avatar
    Patrick Müller committed
         * Flag - Is the CouponCode reusable?
         *
    
    Patrick Müller's avatar
    Patrick Müller committed
         * @var bool
         */
    
    Patrick Müller's avatar
    Patrick Müller committed
        protected $reusable;
    
    Patrick Müller's avatar
    Patrick Müller committed
    
        /**
    
    Patrick Müller's avatar
    Patrick Müller committed
         * CouponCode constructor.
    
    Patrick Müller's avatar
    Patrick Müller committed
         *
         * @param int $id - Invite Code ID
    
    Patrick Müller's avatar
    Patrick Müller committed
         * @throws \QUI\ERP\Coupons\CouponCodeException
    
    Patrick Müller's avatar
    Patrick Müller committed
         */
        public function __construct($id)
        {
    
    Patrick Müller's avatar
    Patrick Müller committed
            $result = QUI::getDataBase()->fetch([
    
    Patrick Müller's avatar
    Patrick Müller committed
                'from'  => Handler::getTable(),
    
    Patrick Müller's avatar
    Patrick Müller committed
                'where' => [
    
    Patrick Müller's avatar
    Patrick Müller committed
                    'id' => $id
    
    Patrick Müller's avatar
    Patrick Müller committed
                ]
            ]);
    
    Patrick Müller's avatar
    Patrick Müller committed
    
            if (empty($result)) {
    
    Patrick Müller's avatar
    Patrick Müller committed
                throw new CouponCodeException([
                    'quiqqer/coupons',
                    'exception.CouponCode.not_found',
                    [
    
    Patrick Müller's avatar
    Patrick Müller committed
                        'id' => $id
    
    Patrick Müller's avatar
    Patrick Müller committed
                    ]
                ], 404);
    
    Patrick Müller's avatar
    Patrick Müller committed
            }
    
            $data = current($result);
    
    
    Patrick Müller's avatar
    Patrick Müller committed
            $this->id    = (int)$data['id'];
            $this->code  = $data['code'];
            $this->title = $data['title'];
    
    Patrick Müller's avatar
    Patrick Müller committed
    
    
    Patrick Müller's avatar
    Patrick Müller committed
            if (!empty($data['usages'])) {
                $this->usages = json_decode($data['usages'], true);
    
    Patrick Müller's avatar
    Patrick Müller committed
            }
    
    
    Patrick Müller's avatar
    Patrick Müller committed
            if (!empty($data['userIds'])) {
                $this->userIds = json_decode($data['userIds'], true);
            }
    
    Patrick Müller's avatar
    Patrick Müller committed
    
    
    Patrick Müller's avatar
    Patrick Müller committed
            if (!empty($data['groupIds'])) {
                $this->groupIds = json_decode($data['groupIds'], true);
    
    Patrick Müller's avatar
    Patrick Müller committed
            }
    
    
    Patrick Müller's avatar
    Patrick Müller committed
            if (!empty($data['isReusable'])) {
                $this->reusable = true;
            }
    
    
    Patrick Müller's avatar
    Patrick Müller committed
            $this->CreateDate = new \DateTime($data['createDate']);
    
    
    Patrick Müller's avatar
    Patrick Müller committed
            if (!empty($data['validUntilDate'])) {
                $this->ValidUntilDate = new \DateTime($data['validUntilDate']);
            }
    
    Patrick Müller's avatar
    Patrick Müller committed
    
            $this->checkValidity();
    
    Patrick Müller's avatar
    Patrick Müller committed
        }
    
        /**
         * @return int
         */
        public function getId()
        {
            return $this->id;
        }
    
        /**
         * @return string
         */
        public function getCode()
        {
            return $this->code;
        }
    
        /**
         * @return \DateTime
         */
        public function getCreateDate()
        {
            return $this->CreateDate;
        }
    
        /**
    
    Patrick Müller's avatar
    Patrick Müller committed
         * Get usage data
         *
         * @return []
    
    Patrick Müller's avatar
    Patrick Müller committed
         */
    
    Patrick Müller's avatar
    Patrick Müller committed
        public function getUsages()
    
    Patrick Müller's avatar
    Patrick Müller committed
        {
    
    Patrick Müller's avatar
    Patrick Müller committed
            return $this->usages;
    
    Patrick Müller's avatar
    Patrick Müller committed
        }
    
        /**
         * @return \DateTime|null
         */
        public function getValidUntilDate()
        {
            return $this->ValidUntilDate;
        }
    
        /**
         * @return string
         */
        public function getTitle()
        {
            return $this->title;
        }
    
        /**
    
    Patrick Müller's avatar
    Patrick Müller committed
         * Redeems this CouponCode
         *
         * Hint: This may invalidate the code for future use
         *
         * @param QUI\Users\User $User - The user that redeems the CouponCode [if omitted use Session User]
         * @return void
         * @throws CouponCodeException
    
    Patrick Müller's avatar
    Patrick Müller committed
         * @throws QUI\Exception
    
    Patrick Müller's avatar
    Patrick Müller committed
         */
    
    Patrick Müller's avatar
    Patrick Müller committed
        public function redeem($User = null)
    
    Patrick Müller's avatar
    Patrick Müller committed
        {
    
    Patrick Müller's avatar
    Patrick Müller committed
            if (is_null($User)) {
                $User = QUI::getUserBySession();
            }
    
            $this->checkRedemption($User);
    
            $Now            = new \DateTime();
            $this->usages[] = [
                'userId' => $User->getId(),
                'date'   => $Now->format('Y-m-d H:i:s')
            ];
    
            QUI::getDataBase()->update(
                Handler::getTable(),
                [
                    'usages' => json_encode($this->usages)
                ],
                [
                    'id' => $this->id
                ]
            );
    
            $this->checkValidity();
    
    Patrick Müller's avatar
    Patrick Müller committed
    
            QUI::getEvents()->fireEvent(
                'quiqqerCouponsRedeem',
                [
                    'User'       => $User,
                    'CouponCode' => $this
                ]
            );
    
    Patrick Müller's avatar
    Patrick Müller committed
        }
    
        /**
    
    Patrick Müller's avatar
    Patrick Müller committed
         * Check if the given User can redeem this CouponCode
    
    Patrick Müller's avatar
    Patrick Müller committed
         *
    
    Patrick Müller's avatar
    Patrick Müller committed
         * @param QUI\Users\User $User - If omitted, use session user
    
    Patrick Müller's avatar
    Patrick Müller committed
         * @return void
    
    Patrick Müller's avatar
    Patrick Müller committed
         * @throws CouponCodeException - Thrown if not redeemable by the given User
    
    Patrick Müller's avatar
    Patrick Müller committed
         */
    
    Patrick Müller's avatar
    Patrick Müller committed
        protected function checkRedemption($User)
    
    Patrick Müller's avatar
    Patrick Müller committed
        {
    
    Patrick Müller's avatar
    Patrick Müller committed
            if (!$this->isValid()) {
                throw new CouponCodeException([
                    'quiqqer/coupons',
                    'exception.CouponCode.no_longer_valid'
                ]);
    
    Patrick Müller's avatar
    Patrick Müller committed
            }
    
    
    Patrick Müller's avatar
    Patrick Müller committed
            if (!empty($this->userIds)) {
                if (in_array($User->getId(), $this->userIds)) {
                    if (!$this->reusable && $this->hasUserRedeemed($User)) {
                        throw new CouponCodeException([
                            'quiqqer/coupons',
                            'exception.CouponCode.already_used'
                        ]);
                    }
                } else {
                    throw new CouponCodeException([
                        'quiqqer/coupons',
                        'exception.CouponCode.user_not_allowed'
                    ]);
                }
    
    Patrick Müller's avatar
    Patrick Müller committed
            }
    
    
    Patrick Müller's avatar
    Patrick Müller committed
            if (!empty($this->groupIds)) {
                $userInGroup = false;
    
    Patrick Müller's avatar
    Patrick Müller committed
    
    
    Patrick Müller's avatar
    Patrick Müller committed
                foreach ($this->groupIds as $groupId) {
                    if ($User->isInGroup($groupId)) {
                        $userInGroup = true;
                        break;
                    }
                }
    
    Patrick Müller's avatar
    Patrick Müller committed
    
    
    Patrick Müller's avatar
    Patrick Müller committed
                if ($userInGroup) {
                    if (!$this->reusable && $this->hasUserRedeemed($User)) {
                        throw new CouponCodeException([
                            'quiqqer/coupons',
                            'exception.CouponCode.already_used'
                        ]);
                    }
                } else {
                    throw new CouponCodeException([
                        'quiqqer/coupons',
                        'exception.CouponCode.user_not_allowed_group'
                    ]);
                }
            }
    
    Patrick Müller's avatar
    Patrick Müller committed
        }
    
        /**
    
    Patrick Müller's avatar
    Patrick Müller committed
         * Check if the given User can redeem this CouponCode
    
    Patrick Müller's avatar
    Patrick Müller committed
         *
    
    Patrick Müller's avatar
    Patrick Müller committed
         * @param QUI\Users\User $User - If omitted, use session user
    
    Patrick Müller's avatar
    Patrick Müller committed
         * @return bool
         */
    
    Patrick Müller's avatar
    Patrick Müller committed
        public function isRedeemable($User = null)
    
    Patrick Müller's avatar
    Patrick Müller committed
        {
    
    Patrick Müller's avatar
    Patrick Müller committed
            try {
                $this->checkRedemption($User);
            } catch (CouponCodeException $Exception) {
                return false;
            }
    
            return true;
    
    Patrick Müller's avatar
    Patrick Müller committed
        }
    
        /**
    
    Patrick Müller's avatar
    Patrick Müller committed
         * Check if this CouponCode is still valid
    
    Patrick Müller's avatar
    Patrick Müller committed
         *
         * @return bool
         */
    
    Patrick Müller's avatar
    Patrick Müller committed
        public function isValid()
    
    Patrick Müller's avatar
    Patrick Müller committed
        {
    
    Patrick Müller's avatar
    Patrick Müller committed
            return $this->valid;
    
    Patrick Müller's avatar
    Patrick Müller committed
        }
    
        /**
    
    Patrick Müller's avatar
    Patrick Müller committed
         * Checks if an CouponCode has been redeemed by a user
    
    Patrick Müller's avatar
    Patrick Müller committed
         *
    
    Patrick Müller's avatar
    Patrick Müller committed
         * @param QUI\Users\User $User
         * @return bool
    
    Patrick Müller's avatar
    Patrick Müller committed
         */
    
    Patrick Müller's avatar
    Patrick Müller committed
        public function hasUserRedeemed($User)
    
    Patrick Müller's avatar
    Patrick Müller committed
        {
    
    Patrick Müller's avatar
    Patrick Müller committed
            $userId = $User->getId();
    
    Patrick Müller's avatar
    Patrick Müller committed
    
    
    Patrick Müller's avatar
    Patrick Müller committed
            foreach ($this->usages as $usage) {
                if ($usage['userId'] === $userId) {
                    return true;
                }
    
    Patrick Müller's avatar
    Patrick Müller committed
            }
    
    
    Patrick Müller's avatar
    Patrick Müller committed
            return false;
    
    Patrick Müller's avatar
    Patrick Müller committed
        }
    
        /**
    
    Patrick Müller's avatar
    Patrick Müller committed
         * Permanently delete this CouponCode
    
    Patrick Müller's avatar
    Patrick Müller committed
         *
         * @return void
         */
        public function delete()
        {
            Permission::checkPermission(Handler::PERMISSION_DELETE);
    
            QUI::getDataBase()->delete(
                Handler::getTable(),
    
    Patrick Müller's avatar
    Patrick Müller committed
                [
    
    Patrick Müller's avatar
    Patrick Müller committed
                    'id' => $this->id
    
    Patrick Müller's avatar
    Patrick Müller committed
                ]
    
    Patrick Müller's avatar
    Patrick Müller committed
         * Get CouponCode attributes as array
    
    Patrick Müller's avatar
    Patrick Müller committed
         *
         * @return array
         */
        public function toArray()
        {
    
    Patrick Müller's avatar
    Patrick Müller committed
            $data = [
    
    Patrick Müller's avatar
    Patrick Müller committed
                'id'             => $this->getId(),
                'code'           => $this->getCode(),
    
    Patrick Müller's avatar
    Patrick Müller committed
                'userIds'        => $this->userIds,
                'groupIds'       => $this->groupIds,
    
    Patrick Müller's avatar
    Patrick Müller committed
                'createDate'     => $this->getCreateDate()->format('Y-m-d H:i:s'),
    
    Patrick Müller's avatar
    Patrick Müller committed
                'usages'         => $this->usages,
    
    Patrick Müller's avatar
    Patrick Müller committed
                'validUntilDate' => false,
                'title'          => $this->getTitle() ?: false,
    
    Patrick Müller's avatar
    Patrick Müller committed
                'isValid'        => $this->isValid(),
                'isReusable'     => $this->reusable
            ];
    
    Patrick Müller's avatar
    Patrick Müller committed
    
    
    Patrick Müller's avatar
    Patrick Müller committed
            $ValidUntilDate = $this->getValidUntilDate();
    
    Patrick Müller's avatar
    Patrick Müller committed
    
    
    Patrick Müller's avatar
    Patrick Müller committed
            if ($ValidUntilDate) {
                $data['validUntilDate'] = $ValidUntilDate->format('Y-m-d H:i:s');
    
    Patrick Müller's avatar
    Patrick Müller committed
            }
    
    
    Patrick Müller's avatar
    Patrick Müller committed
            return $data;
        }
    
    Patrick Müller's avatar
    Patrick Müller committed
    
    
    Patrick Müller's avatar
    Patrick Müller committed
        /**
         * Checks if this CouponCode is still valid
         *
         * @return void
         */
        protected function checkValidity()
        {
            // Check if the expiration date has been reached
            if (!empty($this->ValidUntilDate)) {
                $Now = new \DateTime();
    
    Patrick Müller's avatar
    Patrick Müller committed
    
    
    Patrick Müller's avatar
    Patrick Müller committed
                if ($Now > $this->ValidUntilDate) {
                    $this->valid = false;
                    return;
                }
            }
    
    Patrick Müller's avatar
    Patrick Müller committed
    
    
    Patrick Müller's avatar
    Patrick Müller committed
            if ($this->reusable) {
                return;
    
    Patrick Müller's avatar
    Patrick Müller committed
            }
    
    
    Patrick Müller's avatar
    Patrick Müller committed
            // If the CouponCode is restricted to certain users -> Check if all those
            // users have already redeemed the code
            if (!empty($this->userIds)) {
                $usedByAllUsers = true;
    
                foreach ($this->userIds as $userId) {
                    foreach ($this->usages as $usage) {
                        if ($userId == $usage['userId']) {
                            continue 2;
                        }
                    }
    
                    $usedByAllUsers = false;
                    break;
                }
    
                if ($usedByAllUsers) {
                    $this->valid = false;
                    return;
                }
            }
    
    Patrick Müller's avatar
    Patrick Müller committed
        }
    }