Files
Cloud-CMS/lib/Entity/Notification.php
Matt Batchelder 05ce0da296 Initial Upload
2025-12-02 10:32:59 -05:00

534 lines
14 KiB
PHP

<?php
/*
* Copyright (C) 2024 Xibo Signage Ltd
*
* Xibo - Digital Signage - https://xibosignage.com
*
* This file is part of Xibo.
*
* Xibo is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* Xibo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Xibo. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Xibo\Entity;
use Xibo\Factory\DisplayGroupFactory;
use Xibo\Factory\UserGroupFactory;
use Xibo\Service\LogServiceInterface;
use Xibo\Storage\StorageServiceInterface;
use Xibo\Support\Exception\InvalidArgumentException;
/**
* Class Notification
* @package Xibo\Entity
*
* @SWG\Definition()
*/
class Notification implements \JsonSerializable
{
use EntityTrait;
/**
* @SWG\Property(
* description="The Notifcation ID"
* )
* @var int
*/
public $notificationId;
/**
* @SWG\Property(
* description="Create Date as Unix Timestamp"
* )
* @var int
*/
public $createDt;
/**
* @SWG\Property(
* description="Release Date as Unix Timestamp"
* )
* @var int
*/
public $releaseDt;
/**
* @SWG\Property(
* description="The subject line"
* )
* @var string
*/
public $subject;
/**
* @SWG\Property(
* description="The Notification type"
* )
* @var string
*/
public $type;
/**
* @SWG\Property(
* description="The HTML body of the notification"
* )
* @var string
*/
public $body;
/**
* @SWG\Property(
* description="Should the notification interrupt the CMS UI on navigate/login"
* )
* @var int
*/
public $isInterrupt = 0;
/**
* @SWG\Property(
* description="Flag for system notification"
* )
* @var int
*/
public $isSystem = 0;
/**
* @SWG\Property(
* description="The Owner User Id"
* )
* @var int
*/
public $userId;
/**
* @SWG\Property(
* description="Attachment filename"
* )
* @var string
*/
public $filename;
/**
* @SWG\Property(
* description="Attachment originalFileName"
* )
* @var string
*/
public $originalFileName;
/**
* @SWG\Property(
* description="Additional email addresses to which a saved report will be sent"
* )
* @var string
*/
public $nonusers;
/**
* @SWG\Property(
* description="User Group Notifications associated with this notification"
* )
* @var UserGroup[]
*/
public $userGroups = [];
/**
* @SWG\Property(
* description="Display Groups associated with this notification"
* )
* @var DisplayGroup[]
*/
public $displayGroups = [];
/** @var UserGroupFactory */
private $userGroupFactory;
/** @var DisplayGroupFactory */
private $displayGroupFactory;
/**
* Command constructor.
* @param StorageServiceInterface $store
* @param LogServiceInterface $log
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher
* @param UserGroupFactory $userGroupFactory
* @param DisplayGroupFactory $displayGroupFactory
*/
public function __construct($store, $log, $dispatcher, $userGroupFactory, $displayGroupFactory)
{
$this->setCommonDependencies($store, $log, $dispatcher);
$this->userGroupFactory = $userGroupFactory;
$this->displayGroupFactory = $displayGroupFactory;
}
/**
* Get Id
* @return int
*/
public function getId()
{
return $this->notificationId;
}
/**
* Get Owner
*/
public function getOwnerId()
{
return $this->userId;
}
/**
* Add User Group Notification
* @param UserGroup $userGroup
* @throws \Xibo\Support\Exception\NotFoundException
*/
public function assignUserGroup($userGroup)
{
$this->load();
if (!in_array($userGroup, $this->userGroups)) {
$this->userGroups[] = $userGroup;
}
}
/**
* Add Display Group
* @param DisplayGroup $displayGroup
* @throws \Xibo\Support\Exception\NotFoundException
*/
public function assignDisplayGroup($displayGroup)
{
$this->load();
if (!in_array($displayGroup, $this->displayGroups)) {
$this->displayGroups[] = $displayGroup;
}
}
/**
* Validate
* @throws InvalidArgumentException
*/
public function validate()
{
if (empty($this->subject)) {
throw new InvalidArgumentException(__('Please provide a subject'), 'subject');
}
if (empty($this->body)) {
throw new InvalidArgumentException(__('Please provide a body'), 'body');
}
}
/**
* Load
* @param array $options
* @throws \Xibo\Support\Exception\NotFoundException
*/
public function load($options = [])
{
$options = array_merge([
'loadUserGroups' => true,
'loadDisplayGroups' => true,
], $options);
if ($this->loaded || $this->notificationId == null) {
return;
}
// Load the Display Groups and User Group Notifications
if ($options['loadUserGroups']) {
$this->userGroups = $this->userGroupFactory->getByNotificationId($this->notificationId);
}
if ($options['loadDisplayGroups']) {
$this->displayGroups = $this->displayGroupFactory->getByNotificationId($this->notificationId);
}
$this->loaded = true;
}
/**
* Save Notification
* @throws InvalidArgumentException
*/
public function save(): void
{
$this->validate();
$isNewRecord = false;
if ($this->notificationId == null) {
$isNewRecord = true;
$this->add();
} else {
$this->edit();
}
$this->manageAssignments($isNewRecord);
}
/**
* Delete Notification
*/
public function delete()
{
// Remove all links
$this->getStore()->update(
'DELETE FROM `lknotificationuser` WHERE `notificationId` = :notificationId',
['notificationId' => $this->notificationId]
);
$this->getStore()->update(
'DELETE FROM `lknotificationgroup` WHERE `notificationId` = :notificationId',
['notificationId' => $this->notificationId]
);
$this->getStore()->update(
'DELETE FROM `lknotificationdg` WHERE `notificationId` = :notificationId',
['notificationId' => $this->notificationId]
);
// Remove the notification
$this->getStore()->update(
'DELETE FROM `notification` WHERE `notificationId` = :notificationId',
['notificationId' => $this->notificationId]
);
}
/**
* Add to DB
*/
private function add()
{
$this->notificationId = $this->getStore()->insert('
INSERT INTO `notification` (
`subject`,
`body`,
`createDt`,
`releaseDt`,
`isInterrupt`,
`isSystem`,
`userId`,
`filename`,
`originalFileName`,
`nonusers`,
`type`
)
VALUES (
:subject,
:body,
:createDt,
:releaseDt,
:isInterrupt,
:isSystem,
:userId,
:filename,
:originalFileName,
:nonusers,
:type
)
', [
'subject' => $this->subject,
'body' => $this->body,
'createDt' => $this->createDt,
'releaseDt' => $this->releaseDt,
'isInterrupt' => $this->isInterrupt,
'isSystem' => $this->isSystem,
'userId' => $this->userId,
'filename' => $this->filename,
'originalFileName' => $this->originalFileName,
'nonusers' => $this->nonusers,
'type' => $this->type ?? 'custom'
]);
}
/**
* Update in DB
*/
private function edit()
{
$this->getStore()->update('
UPDATE `notification` SET `subject` = :subject,
`body` = :body,
`createDt` = :createDt,
`releaseDt` = :releaseDt,
`isInterrupt` = :isInterrupt,
`isSystem` = :isSystem,
`userId` = :userId,
`filename` = :filename,
`originalFileName` = :originalFileName,
`nonusers` = :nonusers,
`type` = :type
WHERE `notificationId` = :notificationId
', [
'subject' => $this->subject,
'body' => $this->body,
'createDt' => $this->createDt,
'releaseDt' => $this->releaseDt,
'isInterrupt' => $this->isInterrupt,
'isSystem' => $this->isSystem,
'userId' => $this->userId,
'filename' => $this->filename,
'originalFileName' => $this->originalFileName,
'nonusers' => $this->nonusers,
'type' => $this->type ?? 'custom',
'notificationId' => $this->notificationId
]);
}
/**
* Manage assignements in DB
*/
private function manageAssignments(bool $isNewRecord): void
{
$this->linkUserGroups();
// Only unlink if we're not new (otherwise there is no point as we can't have any links yet)
if (!$isNewRecord) {
$this->unlinkUserGroups();
}
$this->linkDisplayGroups();
if (!$isNewRecord) {
$this->unlinkDisplayGroups();
}
$this->manageRealisedUserLinks();
}
/**
* Manage the links in the User notification table
*/
private function manageRealisedUserLinks(bool $isNewRecord = false): void
{
if (!$isNewRecord) {
// Delete links that no longer exist
$this->getStore()->update('
DELETE FROM `lknotificationuser`
WHERE `notificationId` = :notificationId AND `userId` NOT IN (
SELECT `userId`
FROM `lkusergroup`
INNER JOIN `lknotificationgroup`
ON `lknotificationgroup`.groupId = `lkusergroup`.groupId
WHERE `lknotificationgroup`.notificationId = :notificationId2
) AND userId <> 0
', [
'notificationId' => $this->notificationId,
'notificationId2' => $this->notificationId
]);
}
// Pop in new links following from this adjustment
$this->getStore()->update('
INSERT INTO `lknotificationuser` (`notificationId`, `userId`, `read`, `readDt`, `emailDt`)
SELECT DISTINCT :notificationId, `userId`, 0, 0, 0
FROM `lkusergroup`
INNER JOIN `lknotificationgroup`
ON `lknotificationgroup`.groupId = `lkusergroup`.groupId
WHERE `lknotificationgroup`.notificationId = :notificationId2
ON DUPLICATE KEY UPDATE userId = `lknotificationuser`.userId
', [
'notificationId' => $this->notificationId,
'notificationId2' => $this->notificationId
]);
if ($this->isSystem) {
$this->getStore()->insert('
INSERT INTO `lknotificationuser` (`notificationId`, `userId`, `read`, `readDt`, `emailDt`)
VALUES (:notificationId, :userId, 0, 0, 0)
ON DUPLICATE KEY UPDATE userId = `lknotificationuser`.userId
', [
'notificationId' => $this->notificationId,
'userId' => $this->userId
]);
}
}
/**
* Link User Groups
*/
private function linkUserGroups()
{
foreach ($this->userGroups as $userGroup) {
/* @var UserGroup $userGroup */
$this->getStore()->update('INSERT INTO `lknotificationgroup` (notificationId, groupId) VALUES (:notificationId, :userGroupId) ON DUPLICATE KEY UPDATE groupId = groupId', [
'notificationId' => $this->notificationId,
'userGroupId' => $userGroup->groupId
]);
}
}
/**
* Unlink User Groups
*/
private function unlinkUserGroups()
{
// Unlink any userGroup that is NOT in the collection
$params = ['notificationId' => $this->notificationId];
$sql = 'DELETE FROM `lknotificationgroup` WHERE notificationId = :notificationId AND groupId NOT IN (0';
$i = 0;
foreach ($this->userGroups as $userGroup) {
/* @var UserGroup $userGroup */
$i++;
$sql .= ',:userGroupId' . $i;
$params['userGroupId' . $i] = $userGroup->groupId;
}
$sql .= ')';
$this->getStore()->update($sql, $params);
}
/**
* Link Display Groups
*/
private function linkDisplayGroups()
{
foreach ($this->displayGroups as $displayGroup) {
/* @var DisplayGroup $displayGroup */
$this->getStore()->update('INSERT INTO `lknotificationdg` (notificationId, displayGroupId) VALUES (:notificationId, :displayGroupId) ON DUPLICATE KEY UPDATE displayGroupId = displayGroupId', [
'notificationId' => $this->notificationId,
'displayGroupId' => $displayGroup->displayGroupId
]);
}
}
/**
* Unlink Display Groups
*/
private function unlinkDisplayGroups()
{
// Unlink any displayGroup that is NOT in the collection
$params = ['notificationId' => $this->notificationId];
$sql = 'DELETE FROM `lknotificationdg` WHERE notificationId = :notificationId AND displayGroupId NOT IN (0';
$i = 0;
foreach ($this->displayGroups as $displayGroup) {
/* @var DisplayGroup $displayGroup */
$i++;
$sql .= ',:displayGroupId' . $i;
$params['displayGroupId' . $i] = $displayGroup->displayGroupId;
}
$sql .= ')';
$this->getStore()->update($sql, $params);
}
}