Newer
Older
use QUI\ERP\Products\Handler\Products;
use QUI\Lock\Locker;
use QUI\Memberships\Users\Handler as MembershipUsersHandler;
use QUI\Utils\Security\Orthos;
use QUI\ERP\Products\Search\BackendSearch;
use QUI\ERP\Products\Handler\Products as ProductsHandler;
use QUI\ERP\Products\Handler\Fields as ProductFields;

Patrick Müller
committed
use QUI\ERP\Plans\Handler as ErpPlansHandler;
/**
* Get IDs of all QUIQQER Groups
*
* @return int[]
*/
public function getGroupIds()
{
$groupIds = $this->getAttribute('groupIds');
return explode(",", trim($groupIds, ","));
}
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/**
* 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 '';
}
* Check if this membership is auto-extended
public function isAutoExtend()
return $this->getAttribute('autoExtend') ? true : false;
Permission::checkPermission(Handler::PERMISSION_EDIT);
$attributes = $this->getAttributes();
// check groups
if (empty($attributes['groupIds'])
) {

Patrick Müller
committed
throw new QUI\Memberships\Exception([
'quiqqer/memberships',
'exception.handler.no.groups'

Patrick Müller
committed
]);

Patrick Müller
committed
$attributes['groupIds'] = ','.$attributes['groupIds'].',';
if (empty($attributes['duration'])
|| $attributes['duration'] === 'infinite'
) {
$attributes['duration'] = 'infinite';
} else {
$duration = explode('-', $attributes['duration']);

Patrick Müller
committed
throw new QUI\Memberships\Exception([
'quiqqer/memberships',
'exception.membership.update.duration.invalid'

Patrick Müller
committed
]);
}
// edit user and timestamp
$attributes['editUser'] = QUI::getUserBySession()->getId();
$attributes['editDate'] = Utils::getFormattedTimestamp();
$this->setAttributes($attributes);

Patrick Müller
committed
* Only possible if membership has no users in it!

Patrick Müller
committed
* @throws \QUI\Memberships\Exception
* @throws \QUI\Permissions\Exception
* @throws \QUI\Exception
*/
public function delete()
{
Permission::checkPermission(Handler::PERMISSION_DELETE);
$MembershipUsers = MembershipUsersHandler::getInstance();
if (count($MembershipUsers->getIdsByMembershipId($this->id))) {

Patrick Müller
committed
throw new Exception([
'quiqqer/memberships',
'exception.membership.cannot.delete.with.users.left'

Patrick Müller
committed
]);
if ($this->isDefault()) {
$Conf = QUI::getPackage('quiqqer/memberships')->getConfig();
$Conf->set('memberships', 'defaultMembershipId', '0');
$Conf->save();
}
// remove from products
if (Utils::isQuiqqerProductsInstalled()) {
/** @var QUI\ERP\Products\Product\Product $Product */
foreach ($this->getProducts() as $Product) {

Patrick Müller
committed
$MembershipField = $Product->getField(
Handler::getProductMembershipField()->getId()
);

Patrick Müller
committed
$Product->deactivate();
$Product->save();
}
}
if (Utils::isQuiqqerContractsInstalled()) {
// @todo quiqqer/contracts abhandeln
}

Patrick Müller
committed
QUI::getEvents()->fireEvent('quiqqerMembershipsDelete', [$this->getId()]);
* Get a user of this membership (non-archived)
* @return QUI\Memberships\Users\MembershipUser
* @throws QUI\Memberships\Exception
*/
public function getMembershipUser($userId)
{

Patrick Müller
committed
$result = QUI::getDataBase()->fetch([
'select' => [

Patrick Müller
committed
],
'from' => MembershipUsersHandler::getInstance()->getDataBaseTableName(),

Patrick Müller
committed
'where' => [
'userId' => $userId,
'archived' => 0

Patrick Müller
committed
]
]);

Patrick Müller
committed
throw new Exception([
'quiqqer/memberships',
'exception.membership.user.not.found',

Patrick Müller
committed
[

Patrick Müller
committed
]
], 404);
}
return MembershipUsersHandler::getInstance()->getChild($result[0]['id']);
}
/**
* Get IDs of all QUIQQER Groups that are UNIQUE to this membership
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]);
}
}
}
}
* Checks if this membership has an (active, non-archived) user assigned
*
* @param int $userId
* @return bool
*/
public function hasMembershipUserId($userId)
{

Patrick Müller
committed
$result = QUI::getDataBase()->fetch([

Patrick Müller
committed
'select' => [

Patrick Müller
committed
],
'from' => MembershipUsersHandler::getInstance()->getDataBaseTableName(),

Patrick Müller
committed
'where' => [

Patrick Müller
committed
]
]);
return current(current($result)) > 0;
}
/**
* @param bool $archivedOnly (optional) - search archived users only [default: false]
* @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
committed
$membershipUserIds = [];
$Grid = new QUI\Utils\Grid($searchParams);
$gridParams = $Grid->parseDBParams($searchParams);
$tbl = MembershipUsersHandler::getInstance()->getDataBaseTableName();
$usersTbl = QUI::getDBTableName('users');

Patrick Müller
committed
$binds = [];
$where = [];
$sql = "SELECT COUNT(*)";
} else {
$sql = "SELECT `musers`.id";
}

Patrick Müller
committed
$sql .= " FROM `".$tbl."` musers, `".$usersTbl."` users";
$where[] = '`musers`.userId = `users`.id';

Patrick Müller
committed
$where[] = '`musers`.membershipId = '.$this->id;
if ($archivedOnly === false) {
$where[] = '`musers`.archived = 0';
} else {
$where[] = '`musers`.archived = 1';
}
if (!empty($searchParams['search'])) {

Patrick Müller
committed
$whereOR = [];

Patrick Müller
committed
$searchColumns = [
'`users`.username',
'`users`.firstname',
'`users`.lastname'

Patrick Müller
committed
];
foreach ($searchColumns as $tbl => $column) {

Patrick Müller
committed
$whereOR[] = $column.' LIKE :search';
$binds['search'] = [
'value' => '%'.$searchParams['search'].'%',
'type' => \PDO::PARAM_STR

Patrick Müller
committed
];

Patrick Müller
committed
$where[] = '('.implode(' OR ', $whereOR).')';
if (!empty($searchParams['productId'])) {
$where[] = '`musers`.productId = :productId';

Patrick Müller
committed
$binds['productId'] = [
'value' => (int)$searchParams['productId'],
'type' => \PDO::PARAM_INT

Patrick Müller
committed
];
// build WHERE query string
if (!empty($where)) {

Patrick Müller
committed
$sql .= " WHERE ".implode(" AND ", $where);
}
// ORDER
if (!empty($searchParams['sortOn'])
) {
$sortOn = Orthos::clear($searchParams['sortOn']);
switch ($sortOn) {
case 'username':
case 'firstname':
case 'lastname':

Patrick Müller
committed
$sortOn = '`users`.'.$sortOn;

Patrick Müller
committed
$sortOn = '`musers`.'.$sortOn;

Patrick Müller
committed
$order = "ORDER BY ".$sortOn;
if (isset($searchParams['sortBy']) &&
!empty($searchParams['sortBy'])
) {

Patrick Müller
committed
$order .= " ".Orthos::clear($searchParams['sortBy']);
} else {
$order .= " ASC";
}

Patrick Müller
committed
$sql .= " ".$order;
}
// LIMIT
if (!empty($gridParams['limit'])
&& !$countOnly
) {

Patrick Müller
committed
$sql .= " LIMIT ".$gridParams['limit'];
} else {
if (!$countOnly) {

Patrick Müller
committed
$sql .= " LIMIT ".(int)20;
$Stmt = QUI::getPDO()->prepare($sql);
// bind search values
foreach ($binds as $var => $bind) {

Patrick Müller
committed
$Stmt->bindValue(':'.$var, $bind['value'], $bind['type']);
}
try {
$Stmt->execute();
$result = $Stmt->fetchAll(\PDO::FETCH_ASSOC);
} catch (\Exception $Exception) {
QUI\System\Log::addError(

Patrick Müller
committed
self::class.' :: searchUsers() -> '.$Exception->getMessage()

Patrick Müller
committed
return [];
}
if ($countOnly) {
return (int)current(current($result));
}
foreach ($result as $row) {
$membershipUserIds[] = (int)$row['id'];
}
return $membershipUserIds;
}
/**
* Calculate the end date for this membership based on a given time
*
* @param int $start (optional) - UNIX timestamp; if omitted use time()
*/
public function calcEndDate($start = null)
{
if ($this->isInfinite()) {
return null;
}
if (is_null($start)) {
$start = time();
}
$start = Utils::getFormattedTimestamp($start);
$duration = explode('-', $this->getAttribute('duration'));
$durationCount = $duration[0];
$durationScope = $duration[1];

Patrick Müller
committed
$durationMode = Handler::getSetting('durationMode');
switch ($durationMode) {
case 'day':

Patrick Müller
committed
$endTime = strtotime($start.' +'.$durationCount.' '.$durationScope);

Patrick Müller
committed
$beginOfDay = strtotime("midnight", $endTime);
$end = strtotime("tomorrow", $beginOfDay) - 1;
break;
default:

Patrick Müller
committed
$end = strtotime($start.' +'.$durationCount.' '.$durationScope);

Patrick Müller
committed
}
return Utils::getFormattedTimestamp($end);
}
* Requires: quiqqer/products
*
* Get all products that have this membership assigned
*
* @return QUI\ERP\Products\Product\Product[]
*/
public function getProducts()
{
if (!Utils::isQuiqqerProductsInstalled()) {

Patrick Müller
committed
return [];

Patrick Müller
committed
$Search = new BackendSearch();
$MembershipField = Handler::getProductMembershipField();
if ($MembershipField === false) {
return [];
}
$result = $Search->search([
'fields' => [
$MembershipField->getId() => "$this->id" // has to be string
]
]);
} catch (\Exception $Exception) {
QUI\System\Log::writeException($Exception);
return [];

Patrick Müller
committed
$products = [];

Patrick Müller
committed
try {
$products[] = ProductsHandler::getProduct($id);
} catch (\Exception $Exception) {
QUI\System\Log::writeException($Exception);
}
}
return $products;
}
/**
* Requires: quiqqer/products
*
* Create a Product from this Membership
*
* Hint: Every time this method is called, a new Product is created, regardless
* of previous calls!
*
* @return QUI\ERP\Products\Product\Product|false
*/
public function createProduct()
{
if (!Utils::isQuiqqerProductsInstalled()) {
return false;
}

Patrick Müller
committed
$categories = [];
$fields = [];
$Category = Handler::getProductCategory();
if ($Category) {
$categories[] = $Category;
}
$MembershipField = Handler::getProductMembershipField();
if ($MembershipField !== false) {

Patrick Müller
committed
$MembershipField->setOwnFieldStatus(true);
$MembershipField->setValue($this->id);
$fields[] = $MembershipField;
}
$MembershipFlagField = Handler::getProductMembershipFlagField();
if ($MembershipFlagField !== false) {

Patrick Müller
committed
$MembershipFlagField->setOwnFieldStatus(true);
$MembershipFlagField->setValue(true);
$fields[] = $MembershipFlagField;
}
// set title and description
$TitleField = ProductFields::getField(ProductFields::FIELD_TITLE);
$DescField = ProductFields::getField(ProductFields::FIELD_SHORT_DESC);
$title = json_decode($this->getAttribute('title'), true);
$description = json_decode($this->getAttribute('description'), true);
if (!empty($title)) {
$TitleField->setValue($title);
$fields[] = $TitleField;
}
if (!empty($description)) {
$DescField->setValue($description);
$fields[] = $DescField;
}
$Product = ProductsHandler::createProduct($categories, $fields);
if (!empty($categories)) {
$Product->setMainCategory($categories[0]);
$Product->save();
}
// Add fields for contract product type
if ($this->isAutoExtend() && Utils::isQuiqqerErpPlansInstalled()) {
ErpPlansHandler::turnIntoPlanProduct($Product, [
ErpPlansHandler::FIELD_DURATION => $this->getAttribute('duration'),
ErpPlansHandler::FIELD_AUTO_EXTEND => true
]);
}
QUI::getEvents()->fireEvent('quiqqerMembershipsCreateProduct', [$this, $Product]);
/**
* Locks editing of this membership for the current session user
*
* @return void
* @throws \QUI\Lock\Exception
* @throws \QUI\Exception
*/
public function lock()
{
Locker::lock(QUI::getPackage('quiqqer/memberships'), $this->getLockKey());
}
/**
* Unlock membership (requires permission!)
*
* @return void
* @throws \QUI\Permissions\Exception
* @throws \QUI\Lock\Exception
* @throws \QUI\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
* @throws \QUI\Exception
*/
public function isLocked()
{
return Locker::isLocked(QUI::getPackage('quiqqer/memberships'), $this->getLockKey());
}
/**
* Get membership lock key
*
* @return string
*/
protected function getLockKey()
{

Patrick Müller
committed
return 'membership_'.$this->id;
/**
* Get membership data for backend view/edit purposes
*
* @return array
*/
public function getBackendViewData()
{

Patrick Müller
committed
return [
'id' => $this->getId(),
'title' => $this->getTitle(),
'description' => $this->getDescription(),
'content' => $this->getContent()

Patrick Müller
committed
];
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
/**
* Check if this membership has an infinite duration (never expires)
*
* @return bool
*/
public function isInfinite()
{
return $this->getAttribute('duration') === 'infinite';
}
/**
* Check if this Membership is the default Memberships
*
* @return bool
*/
public function isDefault()
{
$DefaultMembership = Handler::getDefaultMembership();
if ($DefaultMembership === false) {
return false;
}
return $DefaultMembership->getId() === $this->getId();
}
/**
* Add user to the membership
*
* @param QUI\Users\User $User
* @return QUI\Memberships\Users\MembershipUser
* @throws \QUI\Exception
*/
public function addUser(QUI\Users\User $User)
{

Patrick Müller
committed
return MembershipUsersHandler::getInstance()->createChild([
'userId' => $User->getId(),
'membershipId' => $this->id

Patrick Müller
committed
]);