Skip to content
Code-Schnipsel Gruppen Projekte
Membership.php 12,1 KiB
Newer Older
  • Learn to ignore specific revisions
  • <?php
    
    namespace QUI\Memberships;
    
    
    Patrick Müller's avatar
    Patrick Müller committed
    use QUI;
    
    use QUI\CRUD\Child;
    
    Patrick Müller's avatar
    Patrick Müller committed
    use QUI\Locale;
    
    Patrick Müller's avatar
    Patrick Müller committed
    use QUI\Lock\Locker;
    use QUI\Memberships\Users\Handler as MembershipUsersHandler;
    
    use QUI\Permissions\Permission;
    
    use QUI\Utils\Security\Orthos;
    
    
    class Membership extends Child
    {
    
    Patrick Müller's avatar
    Patrick Müller committed
        /**
         * Get IDs of all QUIQQER Groups
         *
         * @return int[]
         */
        public function getGroupIds()
        {
            $groupIds = $this->getAttribute('groupIds');
            return explode(",", trim($groupIds, ","));
        }
    
    Patrick Müller's avatar
    Patrick Müller committed
        /**
         * Get membership title
         *
         * @param Locale $Locale (optional)
         * @return string - localized title
         */
        public function getTitle($Locale = null)
        {
            if (is_null($Locale)) {
                $Locale = QUI::getLocale();
            }
    
            $trans = json_decode($this->getAttribute('title'), true);
    
            if (isset($trans[$Locale->getCurrent()])) {
                return $trans[$Locale->getCurrent()];
            }
    
            return '';
        }
    
        /**
         * Get membership description
         *
         * @param Locale $Locale (optional)
         * @return string - localized description
         */
        public function getDescription($Locale = null)
        {
            if (is_null($Locale)) {
                $Locale = QUI::getLocale();
            }
    
            $trans = json_decode($this->getAttribute('description'), true);
    
            if (isset($trans[$Locale->getCurrent()])) {
                return $trans[$Locale->getCurrent()];
            }
    
            return '';
        }
    
        /**
         * Get membership content
         *
         * @param Locale $Locale (optional)
         * @return string - localized content
         */
        public function getContent($Locale = null)
        {
            if (is_null($Locale)) {
                $Locale = QUI::getLocale();
            }
    
            $trans = json_decode($this->getAttribute('content'), true);
    
            if (isset($trans[$Locale->getCurrent()])) {
                return $trans[$Locale->getCurrent()];
            }
    
            return '';
        }
    
    
    Patrick Müller's avatar
    Patrick Müller committed
        /**
    
         * Check if this membership is auto-extended
    
    Patrick Müller's avatar
    Patrick Müller committed
         *
         * @return bool
         */
    
        public function isAutoExtend()
    
            return $this->getAttribute('autoExtend') ? true : false;
    
    Patrick Müller's avatar
    Patrick Müller committed
        /**
         * @inheritdoc
    
    Patrick Müller's avatar
    Patrick Müller committed
         * @throws QUI\Memberships\Exception
    
    Patrick Müller's avatar
    Patrick Müller committed
         */
        public function update()
        {
    
            Permission::checkPermission(Handler::PERMISSION_EDIT);
    
    
    Patrick Müller's avatar
    Patrick Müller committed
            $attributes = $this->getAttributes();
    
            // check groups
            if (empty($attributes['groupIds'])
            ) {
                throw new QUI\Memberships\Exception(array(
                    'quiqqer/memberships',
                    'exception.handler.no.groups'
                ));
            }
    
    Patrick Müller's avatar
    Patrick Müller committed
            $attributes['groupIds'] = ',' . $attributes['groupIds'] . ',';
    
            // check duration
            $duration = explode('-', $attributes['duration']);
    
            if ($duration[0] < 1) {
                throw new QUI\Memberships\Exception(array(
                    'quiqqer/memberships',
                    'exception.membership.update.duration.invalid'
                ));
            }
    
            // edit user and timestamp
            $attributes['editUser'] = QUI::getUserBySession()->getId();
            $attributes['editDate'] = Utils::getFormattedTimestamp();
    
            $this->setAttributes($attributes);
    
    Patrick Müller's avatar
    Patrick Müller committed
    
            parent::update();
        }
    
    Patrick Müller's avatar
    Patrick Müller committed
         * Delete membership
         *
         * Only possible if membership has no users in it
    
    Patrick Müller's avatar
    Patrick Müller committed
         * @throws QUI\Memberships\Exception
    
         */
        public function delete()
        {
            Permission::checkPermission(Handler::PERMISSION_DELETE);
    
            $MembershipUsers = MembershipUsersHandler::getInstance();
    
    
    Patrick Müller's avatar
    Patrick Müller committed
            if (count($MembershipUsers->getIdsByMembershipId($this->id))) {
                throw new Exception(array(
                    'quiqqer/memberships',
                    'exception.membership.cannot.delete.with.users.left'
                ));
    
    Patrick Müller's avatar
    Patrick Müller committed
        /**
    
         * Get a user of this membership (non-archived)
    
    Patrick Müller's avatar
    Patrick Müller committed
         *
         * @param int $userId - User ID
         * @return QUI\Memberships\Users\MembershipUser
         * @throws QUI\Memberships\Exception
         */
        public function getMembershipUser($userId)
        {
            $result = QUI::getDataBase()->fetch(array(
                'select' => array(
                    'id'
                ),
                'from'   => MembershipUsersHandler::getInstance()->getDataBaseTableName(),
                'where'  => array(
                    'membershipId' => $this->id,
    
                    'userId'       => $userId,
                    'archived'     => 0
    
    Patrick Müller's avatar
    Patrick Müller committed
                )
            ));
    
            if (empty($result)) {
                throw new Exception(array(
                    'quiqqer/memberships',
                    'exception.membership.user.not.found',
                    array(
                        'userId' => $userId
                    )
                ), 404);
            }
    
            return MembershipUsersHandler::getInstance()->getChild($result[0]['id']);
        }
    
        /**
    
         * Get IDs of all QUIQQER Groups that are UNIQUE to this membership
    
         * @return int[]
    
        public function getUniqueGroupIds()
    
            $Memberships    = Handler::getInstance();
            $groupIds       = $this->getGroupIds();
            $uniqueGroupIds = $groupIds;
    
            foreach ($Memberships->getMembershipIdsByGroupIds($groupIds) as $membershipId) {
                if ($membershipId == $this->getId()) {
                    continue;
                }
    
                $Membership = $Memberships->getChild($membershipId);
    
                foreach ($Membership->getGroupIds() as $groupId) {
                    if (in_array($groupId, $groupIds)) {
                        $k = array_search($groupId, $uniqueGroupIds);
    
                        if ($k !== false) {
                            unset($uniqueGroupIds[$k]);
                        }
                    }
                }
            }
    
            return $uniqueGroupIds;
    
    Patrick Müller's avatar
    Patrick Müller committed
        /**
    
    Patrick Müller's avatar
    Patrick Müller committed
         * Checks if this membership has an (active, non-archived) user assigned
    
    Patrick Müller's avatar
    Patrick Müller committed
         *
         * @param int $userId
         * @return bool
         */
        public function hasMembershipUserId($userId)
        {
            $result = QUI::getDataBase()->fetch(array(
                'count'  => 1,
                'select' => array(
                    'id'
                ),
                'from'   => MembershipUsersHandler::getInstance()->getDataBaseTableName(),
                'where'  => array(
                    'membershipId' => $this->id,
    
    Patrick Müller's avatar
    Patrick Müller committed
                    'userId'       => $userId,
                    'archived'     => 0
    
    Patrick Müller's avatar
    Patrick Müller committed
                )
            ));
    
            return current(current($result)) > 0;
        }
    
        /**
    
         * Search membership users
    
    Patrick Müller's avatar
    Patrick Müller committed
         *
         * @param array $searchParams
    
         * @param bool $archivedOnly (optional) - search archived users only [default: false]
    
    Patrick Müller's avatar
    Patrick Müller committed
         * @param bool $countOnly (optional) - get count for search result only [default: false]
    
         * @return int[]|int - membership user IDs or count
    
        public function searchUsers($searchParams, $archivedOnly = false, $countOnly = false)
    
    Patrick Müller's avatar
    Patrick Müller committed
        {
            $membershipUserIds = array();
            $Grid              = new QUI\Utils\Grid($searchParams);
            $gridParams        = $Grid->parseDBParams($searchParams);
            $tbl               = MembershipUsersHandler::getInstance()->getDataBaseTableName();
    
            $usersTbl          = QUI::getDBTableName('users');
            $binds             = array();
            $where             = array();
    
    Patrick Müller's avatar
    Patrick Müller committed
    
            if ($countOnly) {
    
                $sql = "SELECT COUNT(*)";
            } else {
                $sql = "SELECT `musers`.id";
            }
    
            $sql .= " FROM `" . $tbl . "` musers, `" . $usersTbl . "` users";
    
            $where[] = '`musers`.userId = `users`.id';
            $where[] = '`musers`.membershipId = ' . $this->id;
    
    
            if ($archivedOnly === false) {
                $where[] = '`musers`.archived = 0';
            } else {
                $where[] = '`musers`.archived = 1';
            }
    
    
            if (!empty($searchParams['search'])) {
                $whereOR = array();
    
                $searchColumns = array(
                    '`users`.username',
                    '`users`.firstname',
                    '`users`.lastname'
                );
    
                foreach ($searchColumns as $tbl => $column) {
                    $whereOR[]       = $column . ' LIKE :search';
                    $binds['search'] = array(
                        'value' => '%' . $searchParams['search'] . '%',
                        'type'  => \PDO::PARAM_STR
                    );
                }
    
                $where[] = '(' . implode(' OR ', $whereOR) . ')';
    
            // build WHERE query string
            if (!empty($where)) {
                $sql .= " WHERE " . implode(" AND ", $where);
            }
    
            // ORDER
            if (!empty($searchParams['sortOn'])
            ) {
    
                $sortOn = Orthos::clear($searchParams['sortOn']);
    
                switch ($sortOn) {
                    case 'username':
                    case 'firstname':
                    case 'lastname':
                        $sortOn = '`users`.' . $sortOn;
                        break;
    
                    default:
                        $sortOn = '`musers`.' . $sortOn;
    
                $order = "ORDER BY " . $sortOn;
    
    
                if (isset($searchParams['sortBy']) &&
                    !empty($searchParams['sortBy'])
                ) {
                    $order .= " " . Orthos::clear($searchParams['sortBy']);
                } else {
                    $order .= " ASC";
                }
    
                $sql .= " " . $order;
            }
    
            // LIMIT
            if (!empty($gridParams['limit'])
                && !$countOnly
            ) {
                $sql .= " LIMIT " . $gridParams['limit'];
            } else {
                if (!$countOnly) {
                    $sql .= " LIMIT " . (int)20;
                }
    
            $Stmt = QUI::getPDO()->prepare($sql);
    
            // bind search values
            foreach ($binds as $var => $bind) {
                $Stmt->bindValue(':' . $var, $bind['value'], $bind['type']);
            }
    
            try {
                $Stmt->execute();
                $result = $Stmt->fetchAll(\PDO::FETCH_ASSOC);
            } catch (\Exception $Exception) {
                QUI\System\Log::addError(
                    self::class . ' :: searchUsers() -> ' . $Exception->getMessage()
                );
    
                return array();
            }
    
            if ($countOnly) {
                return (int)current(current($result));
            }
    
    
            foreach ($result as $row) {
                $membershipUserIds[] = (int)$row['id'];
            }
    
            return $membershipUserIds;
        }
    
    
    Patrick Müller's avatar
    Patrick Müller committed
        /**
         * Calculate the end date for this membership based on a given time
         *
    
    Patrick Müller's avatar
    Patrick Müller committed
         * @param int $start (optional) - UNIX timestamp; if omitted use time()
    
    Patrick Müller's avatar
    Patrick Müller committed
         * @return string - formatted timestamp
         */
        public function calcEndDate($start = null)
        {
            if (is_null($start)) {
                $start = time();
            }
    
            $start = Utils::getFormattedTimestamp($start);
    
            $duration      = explode('-', $this->getAttribute('duration'));
            $durationCount = $duration[0];
            $durationScope = $duration[1];
    
    
            $durationMode = Handler::getSetting('durationMode');
    
            switch ($durationMode) {
                case 'day':
                    $endTime    = strtotime($start . ' +' . $durationCount . ' ' . $durationScope);
                    $beginOfDay = strtotime("midnight", $endTime);
                    $end        = strtotime("tomorrow", $beginOfDay) - 1;
                    break;
    
                default:
                    $end = strtotime($start . ' +' . $durationCount . ' ' . $durationScope);
            }
    
    Patrick Müller's avatar
    Patrick Müller committed
    
            return Utils::getFormattedTimestamp($end);
        }
    
        /**
         * Locks editing of this membership for the current session user
         *
         * @return void
         */
        public function lock()
        {
            Locker::lock(QUI::getPackage('quiqqer/memberships'), $this->getLockKey());
        }
    
        /**
         * Unlock membership (requires permission!)
         *
         * @return void
         * @throws QUI\Permissions\Exception
         */
        public function unlock()
        {
            Locker::unlockWithPermissions(
                QUI::getPackage('quiqqer/memberships'),
                $this->getLockKey(),
                Handler::PERMISSION_FORCE_EDIT
            );
        }
    
        /**
         * Check if this membership is currently locked
         *
         * @return bool
         */
        public function isLocked()
        {
            return Locker::isLocked(QUI::getPackage('quiqqer/memberships'), $this->getLockKey());
        }
    
        /**
         * Get membership lock key
         *
         * @return string
         */
        protected function getLockKey()
        {
            return 'membership_' . $this->id;
        }