Initial Upload
This commit is contained in:
171
lib/Listener/CampaignListener.php
Normal file
171
lib/Listener/CampaignListener.php
Normal file
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2022 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Event\DayPartDeleteEvent;
|
||||
use Xibo\Event\FolderMovingEvent;
|
||||
use Xibo\Event\ParsePermissionEntityEvent;
|
||||
use Xibo\Event\TagDeleteEvent;
|
||||
use Xibo\Event\UserDeleteEvent;
|
||||
use Xibo\Factory\CampaignFactory;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
use Xibo\Support\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Campaign events
|
||||
*/
|
||||
class CampaignListener
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/** @var \Xibo\Factory\CampaignFactory */
|
||||
private $campaignFactory;
|
||||
|
||||
/** @var \Xibo\Storage\StorageServiceInterface */
|
||||
private $storageService;
|
||||
|
||||
public function __construct(
|
||||
CampaignFactory $campaignFactory,
|
||||
StorageServiceInterface $storageService
|
||||
) {
|
||||
$this->campaignFactory = $campaignFactory;
|
||||
$this->storageService = $storageService;
|
||||
}
|
||||
|
||||
public function registerWithDispatcher(EventDispatcherInterface $dispatcher): CampaignListener
|
||||
{
|
||||
$dispatcher->addListener(ParsePermissionEntityEvent::$NAME . 'campaign', [$this, 'onParsePermissions']);
|
||||
$dispatcher->addListener(FolderMovingEvent::$NAME, [$this, 'onFolderMoving']);
|
||||
$dispatcher->addListener(UserDeleteEvent::$NAME, [$this, 'onUserDelete']);
|
||||
$dispatcher->addListener(DayPartDeleteEvent::$NAME, [$this, 'onDayPartDelete']);
|
||||
$dispatcher->addListener(TagDeleteEvent::$NAME, [$this, 'onTagDelete']);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse permissions
|
||||
* @param \Xibo\Event\ParsePermissionEntityEvent $event
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function onParsePermissions(ParsePermissionEntityEvent $event)
|
||||
{
|
||||
$this->getLogger()->debug('onParsePermissions');
|
||||
$event->setObject($this->campaignFactory->getById($event->getObjectId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* When we're moving a folder, update our folderId/permissions folder id
|
||||
* @param \Xibo\Event\FolderMovingEvent $event
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function onFolderMoving(FolderMovingEvent $event)
|
||||
{
|
||||
$folder = $event->getFolder();
|
||||
$newFolder = $event->getNewFolder();
|
||||
|
||||
foreach ($this->campaignFactory->getByFolderId($folder->getId()) as $campaign) {
|
||||
// update campaign record
|
||||
$campaign->folderId = $newFolder->id;
|
||||
$campaign->permissionsFolderId = $newFolder->getPermissionFolderIdOrThis();
|
||||
$campaign->updateFolders('campaign');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* User is being deleted, tidy up their campaigns
|
||||
* @param \Xibo\Event\UserDeleteEvent $event
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\DuplicateEntityException
|
||||
* @throws \Xibo\Support\Exception\InvalidArgumentException
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function onUserDelete(UserDeleteEvent $event)
|
||||
{
|
||||
$user = $event->getUser();
|
||||
$function = $event->getFunction();
|
||||
$newUser = $event->getNewUser();
|
||||
|
||||
if ($function === 'delete') {
|
||||
// Delete any Campaigns
|
||||
foreach ($this->campaignFactory->getByOwnerId($user->userId) as $campaign) {
|
||||
$campaign->delete();
|
||||
}
|
||||
} else if ($function === 'reassignAll') {
|
||||
// Reassign campaigns
|
||||
$this->storageService->update('UPDATE `campaign` SET userId = :userId WHERE userId = :oldUserId', [
|
||||
'userId' => $newUser->userId,
|
||||
'oldUserId' => $user->userId
|
||||
]);
|
||||
} else if ($function === 'countChildren') {
|
||||
$campaigns = $this->campaignFactory->getByOwnerId($user->userId);
|
||||
|
||||
$count = count($campaigns);
|
||||
$this->getLogger()->debug(
|
||||
sprintf(
|
||||
'Counted Children Campaign on User ID %d, there are %d',
|
||||
$user->userId,
|
||||
$count
|
||||
)
|
||||
);
|
||||
|
||||
$event->setReturnValue($event->getReturnValue() + $count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Days parts might be assigned to lkcampaignlayout records.
|
||||
* @param \Xibo\Event\DayPartDeleteEvent $event
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\InvalidArgumentException
|
||||
*/
|
||||
public function onDayPartDelete(DayPartDeleteEvent $event)
|
||||
{
|
||||
// We can't delete dayparts that are in-use on advertising campaigns.
|
||||
if ($this->storageService->exists('
|
||||
SELECT lkCampaignLayoutId
|
||||
FROM `lkcampaignlayout`
|
||||
WHERE dayPartId = :dayPartId
|
||||
LIMIT 1
|
||||
', [
|
||||
'dayPartId' => $event->getDayPart()->dayPartId,
|
||||
])) {
|
||||
throw new InvalidArgumentException(__('This is inuse and cannot be deleted.'), 'dayPartId');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When Tag gets deleted, remove any campaign links from it.
|
||||
* @param TagDeleteEvent $event
|
||||
* @return void
|
||||
*/
|
||||
public function onTagDelete(TagDeleteEvent $event)
|
||||
{
|
||||
$this->storageService->update(
|
||||
'DELETE FROM `lktagcampaign` WHERE `lktagcampaign`.tagId = :tagId',
|
||||
['tagId' => $event->getTagId()]
|
||||
);
|
||||
}
|
||||
}
|
||||
372
lib/Listener/DataSetDataProviderListener.php
Normal file
372
lib/Listener/DataSetDataProviderListener.php
Normal file
@@ -0,0 +1,372 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2025 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\Listener;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Entity\DataSet;
|
||||
use Xibo\Event\DataSetDataRequestEvent;
|
||||
use Xibo\Event\DataSetDataTypeRequestEvent;
|
||||
use Xibo\Event\DataSetModifiedDtRequestEvent;
|
||||
use Xibo\Factory\DataSetFactory;
|
||||
use Xibo\Factory\DisplayFactory;
|
||||
use Xibo\Service\ConfigServiceInterface;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
use Xibo\Support\Exception\NotFoundException;
|
||||
use Xibo\Widget\Definition\DataType;
|
||||
use Xibo\Widget\Provider\DataProviderInterface;
|
||||
|
||||
/**
|
||||
* Listens to requests for data from DataSets.
|
||||
*/
|
||||
class DataSetDataProviderListener
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/** @var \Xibo\Storage\StorageServiceInterface */
|
||||
private $store;
|
||||
|
||||
/** @var \Xibo\Service\ConfigServiceInterface */
|
||||
private $config;
|
||||
|
||||
/** @var \Xibo\Factory\DataSetFactory */
|
||||
private $dataSetFactory;
|
||||
|
||||
/** @var \Xibo\Factory\DisplayFactory */
|
||||
private $displayFactory;
|
||||
|
||||
public function __construct(
|
||||
StorageServiceInterface $store,
|
||||
ConfigServiceInterface $config,
|
||||
DataSetFactory $dataSetFactory,
|
||||
DisplayFactory $displayFactory
|
||||
) {
|
||||
$this->store = $store;
|
||||
$this->config = $config;
|
||||
$this->dataSetFactory = $dataSetFactory;
|
||||
$this->displayFactory = $displayFactory;
|
||||
}
|
||||
|
||||
public function registerWithDispatcher(EventDispatcherInterface $dispatcher): DataSetDataProviderListener
|
||||
{
|
||||
$dispatcher->addListener(DataSetDataRequestEvent::$NAME, [$this, 'onDataRequest']);
|
||||
$dispatcher->addListener(DataSetDataTypeRequestEvent::$NAME, [$this, 'onDataTypeRequest']);
|
||||
$dispatcher->addListener(DataSetModifiedDtRequestEvent::$NAME, [$this, 'onModifiedDtRequest']);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function onDataRequest(DataSetDataRequestEvent $event)
|
||||
{
|
||||
$this->getLogger()->debug('onDataRequest: data source is ' . $event->getDataProvider()->getDataSource());
|
||||
|
||||
$dataProvider = $event->getDataProvider();
|
||||
|
||||
// We must have a dataSetId configured.
|
||||
$dataSetId = $dataProvider->getProperty('dataSetId', 0);
|
||||
if (empty($dataSetId)) {
|
||||
$this->getLogger()->debug('onDataRequest: no dataSetId.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Get this dataset
|
||||
try {
|
||||
$dataSet = $this->dataSetFactory->getById($dataSetId);
|
||||
} catch (NotFoundException $notFoundException) {
|
||||
$this->getLogger()->error('onDataRequest: dataSetId ' . $dataSetId . ' not found.');
|
||||
return;
|
||||
}
|
||||
|
||||
$this->getData($dataSet, $dataProvider);
|
||||
|
||||
// Cache timeout
|
||||
$dataProvider->setCacheTtl($dataProvider->getProperty('updateInterval', 60) * 60);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Xibo\Event\DataSetDataTypeRequestEvent $event
|
||||
* @return void
|
||||
*/
|
||||
public function onDataTypeRequest(DataSetDataTypeRequestEvent $event)
|
||||
{
|
||||
// We must have a dataSetId configured.
|
||||
$dataSetId = $event->getDataSetId();
|
||||
if (empty($dataSetId)) {
|
||||
$this->getLogger()->debug('onDataTypeRequest: no dataSetId.');
|
||||
return;
|
||||
}
|
||||
|
||||
$this->getLogger()->debug('onDataTypeRequest: with dataSetId: ' . $dataSetId);
|
||||
|
||||
// Get this dataset
|
||||
try {
|
||||
$dataSet = $this->dataSetFactory->getById($dataSetId);
|
||||
|
||||
// Create a new DataType for this DataSet
|
||||
$dataType = new DataType();
|
||||
$dataType->id = 'dataset';
|
||||
$dataType->name = $dataSet->dataSet;
|
||||
|
||||
// Get the columns for this dataset and return a list of them
|
||||
foreach ($dataSet->getColumn() as $column) {
|
||||
$dataType->addField(
|
||||
$column->heading . '|' . $column->dataSetColumnId,
|
||||
$column->heading,
|
||||
$column->dataType
|
||||
);
|
||||
}
|
||||
|
||||
$event->setDataType($dataType);
|
||||
} catch (NotFoundException $notFoundException) {
|
||||
$this->getLogger()->error('onDataTypeRequest: dataSetId ' . $dataSetId . ' not found.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public function onModifiedDtRequest(DataSetModifiedDtRequestEvent $event)
|
||||
{
|
||||
$this->getLogger()->debug('onModifiedDtRequest: get modifiedDt with dataSetId: ' . $event->getDataSetId());
|
||||
|
||||
try {
|
||||
$dataSet = $this->dataSetFactory->getById($event->getDataSetId());
|
||||
$event->setModifiedDt(Carbon::createFromTimestamp($dataSet->lastDataEdit));
|
||||
|
||||
// Remote dataSets are kept "active" by required files
|
||||
$dataSet->setActive();
|
||||
} catch (NotFoundException $notFoundException) {
|
||||
$this->getLogger()->error('onModifiedDtRequest: dataSetId ' . $event->getDataSetId() . ' not found.');
|
||||
}
|
||||
}
|
||||
|
||||
private function getData(DataSet $dataSet, DataProviderInterface $dataProvider): void
|
||||
{
|
||||
// Load the dataSet
|
||||
$dataSet->load();
|
||||
|
||||
// Columns
|
||||
// Build a list of column mappings we will make available as metadata
|
||||
$mappings = [];
|
||||
$columnIds = $dataProvider->getProperty('columns');
|
||||
$columnIds = empty($columnIds) ? null : explode(',', $columnIds);
|
||||
|
||||
$this->getLogger()->debug('getData: loaded dataSetId ' . $dataSet->dataSetId . ', there are '
|
||||
. count($dataSet->columns) . '. We have selected ' . ($columnIds !== null ? count($columnIds) : 'all')
|
||||
. ' of them');
|
||||
|
||||
foreach ($dataSet->columns as $column) {
|
||||
if ($columnIds === null || in_array($column->dataSetColumnId, $columnIds)) {
|
||||
$mappings[] = [
|
||||
'dataSetColumnId' => $column->dataSetColumnId,
|
||||
'heading' => $column->heading,
|
||||
'dataTypeId' => $column->dataTypeId
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$this->getLogger()->debug('getData: resolved ' . count($mappings) . ' column mappings');
|
||||
|
||||
// Build filter, order and limit parameters to pass to the DataSet entity
|
||||
// Ordering
|
||||
$ordering = '';
|
||||
if ($dataProvider->getProperty('useOrderingClause', 1) == 1) {
|
||||
$ordering = $dataProvider->getProperty('ordering');
|
||||
} else {
|
||||
// Build an order string
|
||||
foreach (json_decode($dataProvider->getProperty('orderClauses', '[]'), true) as $clause) {
|
||||
$ordering .= $clause['orderClause'] . ' ' . $clause['orderClauseDirection'] . ',';
|
||||
}
|
||||
|
||||
$ordering = rtrim($ordering, ',');
|
||||
}
|
||||
|
||||
// Build a filter to pass to the dataset
|
||||
$filter = [
|
||||
'filter' => $this->buildFilterClause($dataProvider),
|
||||
'order' => $ordering,
|
||||
'displayId' => $dataProvider->getDisplayId(),
|
||||
];
|
||||
|
||||
// limits?
|
||||
$upperLimit = $dataProvider->getProperty('upperLimit', 0);
|
||||
$lowerLimit = $dataProvider->getProperty('lowerLimit', 0);
|
||||
if ($lowerLimit !== 0 || $upperLimit !== 0) {
|
||||
// Start should be the lower limit
|
||||
// Size should be the distance between upper and lower
|
||||
$filter['start'] = $lowerLimit;
|
||||
$filter['size'] = $upperLimit - $lowerLimit;
|
||||
|
||||
$this->getLogger()->debug('getData: applied limits, start: '
|
||||
. $filter['start'] . ', size: ' . $filter['size']);
|
||||
}
|
||||
|
||||
// Expiry time for any images
|
||||
$expires = Carbon::now()
|
||||
->addSeconds($dataProvider->getProperty('updateInterval', 3600) * 60)
|
||||
->format('U');
|
||||
|
||||
try {
|
||||
$this->setTimezone($dataProvider);
|
||||
|
||||
$dataSetResults = $dataSet->getData($filter);
|
||||
|
||||
$this->getLogger()->debug('getData: finished getting data. There are '
|
||||
. count($dataSetResults) . ' records returned');
|
||||
|
||||
foreach ($dataSetResults as $row) {
|
||||
// Add an item containing the columns we have selected
|
||||
$item = [];
|
||||
foreach ($mappings as $mapping) {
|
||||
// This column is selected
|
||||
$cellValue = $row[$mapping['heading']] ?? null;
|
||||
if ($mapping['dataTypeId'] === 4) {
|
||||
// Grab the external image
|
||||
$item[$mapping['heading']] = $dataProvider->addImage(
|
||||
'dataset_' . md5($dataSet->dataSetId . $mapping['dataSetColumnId'] . $cellValue),
|
||||
str_replace(' ', '%20', htmlspecialchars_decode($cellValue)),
|
||||
$expires
|
||||
);
|
||||
} else if ($mapping['dataTypeId'] === 5) {
|
||||
// Library Image
|
||||
$this->getLogger()->debug('getData: Library media reference found: ' . $cellValue);
|
||||
|
||||
// The content is the ID of the image
|
||||
try {
|
||||
$item[$mapping['heading']] = $dataProvider->addLibraryFile(intval($cellValue));
|
||||
} catch (NotFoundException $notFoundException) {
|
||||
$this->getLogger()->error('getData: Invalid library media reference: ' . $cellValue);
|
||||
$item[$mapping['heading']] = '';
|
||||
}
|
||||
} else {
|
||||
// Just a normal column
|
||||
$item[$mapping['heading']] = $cellValue;
|
||||
}
|
||||
}
|
||||
$dataProvider->addItem($item);
|
||||
}
|
||||
|
||||
// Add the mapping we've generated to the metadata
|
||||
$dataProvider->addOrUpdateMeta('mapping', $mappings);
|
||||
$dataProvider->setIsHandled();
|
||||
} catch (\Exception $exception) {
|
||||
$this->getLogger()->debug('onDataRequest: ' . $exception->getTraceAsString());
|
||||
$this->getLogger()->error('onDataRequest: unable to get data for dataSetId ' . $dataSet->dataSetId
|
||||
. ' e: ' . $exception->getMessage());
|
||||
|
||||
$dataProvider->addError(__('DataSet Invalid'));
|
||||
}
|
||||
}
|
||||
|
||||
private function buildFilterClause(DataProviderInterface $dataProvider): ?string
|
||||
{
|
||||
$filter = '';
|
||||
|
||||
if ($dataProvider->getProperty('useFilteringClause', 1) == 1) {
|
||||
$filter = $dataProvider->getProperty('filter');
|
||||
} else {
|
||||
// Build
|
||||
$i = 0;
|
||||
foreach (json_decode($dataProvider->getProperty('filterClauses', '[]'), true) as $clause) {
|
||||
$i++;
|
||||
|
||||
switch ($clause['filterClauseCriteria']) {
|
||||
case 'starts-with':
|
||||
$criteria = 'LIKE \'' . $clause['filterClauseValue'] . '%\'';
|
||||
break;
|
||||
|
||||
case 'ends-with':
|
||||
$criteria = 'LIKE \'%' . $clause['filterClauseValue'] . '\'';
|
||||
break;
|
||||
|
||||
case 'contains':
|
||||
$criteria = 'LIKE \'%' . $clause['filterClauseValue'] . '%\'';
|
||||
break;
|
||||
|
||||
case 'equals':
|
||||
$criteria = '= \'' . $clause['filterClauseValue'] . '\'';
|
||||
break;
|
||||
|
||||
case 'not-contains':
|
||||
$criteria = 'NOT LIKE \'%' . $clause['filterClauseValue'] . '%\'';
|
||||
break;
|
||||
|
||||
case 'not-starts-with':
|
||||
$criteria = 'NOT LIKE \'' . $clause['filterClauseValue'] . '%\'';
|
||||
break;
|
||||
|
||||
case 'not-ends-with':
|
||||
$criteria = 'NOT LIKE \'%' . $clause['filterClauseValue'] . '\'';
|
||||
break;
|
||||
|
||||
case 'not-equals':
|
||||
$criteria = '<> \'' . $clause['filterClauseValue'] . '\'';
|
||||
break;
|
||||
|
||||
case 'greater-than':
|
||||
$criteria = '> \'' . $clause['filterClauseValue'] . '\'';
|
||||
break;
|
||||
|
||||
case 'less-than':
|
||||
$criteria = '< \'' . $clause['filterClauseValue'] . '\'';
|
||||
break;
|
||||
|
||||
default:
|
||||
continue 2;
|
||||
}
|
||||
|
||||
if ($i > 1) {
|
||||
$filter .= ' ' . $clause['filterClauseOperator'] . ' ';
|
||||
}
|
||||
|
||||
$filter .= $clause['filterClause'] . ' ' . $criteria;
|
||||
}
|
||||
}
|
||||
|
||||
return $filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Xibo\Widget\Provider\DataProviderInterface $dataProvider
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
private function setTimezone(DataProviderInterface $dataProvider)
|
||||
{
|
||||
// Set the timezone for SQL
|
||||
$dateNow = Carbon::now();
|
||||
if ($dataProvider->getDisplayId() != 0) {
|
||||
$display = $this->displayFactory->getById($dataProvider->getDisplayId());
|
||||
$timeZone = $display->getSetting('displayTimeZone', '');
|
||||
$timeZone = ($timeZone == '') ? $this->config->getSetting('defaultTimezone') : $timeZone;
|
||||
$dateNow->timezone($timeZone);
|
||||
$this->logger->debug(sprintf(
|
||||
'Display Timezone Resolved: %s. Time: %s.',
|
||||
$timeZone,
|
||||
$dateNow->toDateTimeString()
|
||||
));
|
||||
}
|
||||
|
||||
// Run this command on a new connection so that we do not interfere with any other queries on this connection.
|
||||
$this->store->setTimeZone($dateNow->format('P'), 'dataset');
|
||||
|
||||
$this->getLogger()->debug('setTimezone: finished setting timezone');
|
||||
}
|
||||
}
|
||||
277
lib/Listener/DisplayGroupListener.php
Normal file
277
lib/Listener/DisplayGroupListener.php
Normal file
@@ -0,0 +1,277 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2022 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Event\DisplayGroupLoadEvent;
|
||||
use Xibo\Event\FolderMovingEvent;
|
||||
use Xibo\Event\MediaDeleteEvent;
|
||||
use Xibo\Event\MediaFullLoadEvent;
|
||||
use Xibo\Event\ParsePermissionEntityEvent;
|
||||
use Xibo\Event\TagDeleteEvent;
|
||||
use Xibo\Event\TagEditEvent;
|
||||
use Xibo\Event\TriggerTaskEvent;
|
||||
use Xibo\Event\UserDeleteEvent;
|
||||
use Xibo\Factory\DisplayFactory;
|
||||
use Xibo\Factory\DisplayGroupFactory;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
use Xibo\Support\Exception\GeneralException;
|
||||
use Xibo\Support\Exception\NotFoundException;
|
||||
|
||||
/**
|
||||
* DisplayGroup events
|
||||
*/
|
||||
class DisplayGroupListener
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/**
|
||||
* @var DisplayGroupFactory
|
||||
*/
|
||||
private $displayGroupFactory;
|
||||
|
||||
/**
|
||||
* @var DisplayFactory
|
||||
*/
|
||||
private $displayFactory;
|
||||
|
||||
/**
|
||||
* @var StorageServiceInterface
|
||||
*/
|
||||
private $storageService;
|
||||
|
||||
/**
|
||||
* @param DisplayGroupFactory $displayGroupFactory
|
||||
* @param DisplayFactory $displayFactory
|
||||
* @param StorageServiceInterface $storageService
|
||||
*/
|
||||
public function __construct(
|
||||
DisplayGroupFactory $displayGroupFactory,
|
||||
DisplayFactory $displayFactory,
|
||||
StorageServiceInterface $storageService
|
||||
) {
|
||||
$this->displayGroupFactory = $displayGroupFactory;
|
||||
$this->displayFactory = $displayFactory;
|
||||
$this->storageService = $storageService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return $this
|
||||
*/
|
||||
public function registerWithDispatcher(EventDispatcherInterface $dispatcher): DisplayGroupListener
|
||||
{
|
||||
$dispatcher->addListener(MediaDeleteEvent::$NAME, [$this, 'onMediaDelete']);
|
||||
$dispatcher->addListener(UserDeleteEvent::$NAME, [$this, 'onUserDelete']);
|
||||
$dispatcher->addListener(MediaFullLoadEvent::$NAME, [$this, 'onMediaLoad']);
|
||||
$dispatcher->addListener(ParsePermissionEntityEvent::$NAME . 'displayGroup', [$this, 'onParsePermissions']);
|
||||
$dispatcher->addListener(FolderMovingEvent::$NAME, [$this, 'onFolderMoving']);
|
||||
$dispatcher->addListener(TagDeleteEvent::$NAME, [$this, 'onTagDelete']);
|
||||
$dispatcher->addListener(TagEditEvent::$NAME, [$this, 'onTagEdit']);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MediaDeleteEvent $event
|
||||
* @param string $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\GeneralException
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function onMediaDelete(MediaDeleteEvent $event, string $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$media = $event->getMedia();
|
||||
$parentMedia = $event->getParentMedia();
|
||||
|
||||
foreach ($this->displayGroupFactory->getByMediaId($media->mediaId) as $displayGroup) {
|
||||
$dispatcher->dispatch(new DisplayGroupLoadEvent($displayGroup), DisplayGroupLoadEvent::$NAME);
|
||||
$displayGroup->load();
|
||||
$displayGroup->unassignMedia($media);
|
||||
if ($parentMedia != null) {
|
||||
$displayGroup->assignMedia($parentMedia);
|
||||
}
|
||||
|
||||
$displayGroup->save(['validate' => false]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserDeleteEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\GeneralException
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function onUserDelete(UserDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$user = $event->getUser();
|
||||
$function = $event->getFunction();
|
||||
$newUser = $event->getNewUser();
|
||||
$systemUser = $event->getSystemUser();
|
||||
|
||||
if ($function === 'delete') {
|
||||
// we do not want to delete Display specific Display Groups, reassign to systemUser instead.
|
||||
foreach ($this->displayGroupFactory->getByOwnerId($user->userId, -1) as $displayGroup) {
|
||||
if ($displayGroup->isDisplaySpecific === 1) {
|
||||
$displayGroup->setOwner($systemUser->userId);
|
||||
$displayGroup->save(['saveTags' => false, 'manageDynamicDisplayLinks' => false]);
|
||||
} else {
|
||||
$displayGroup->load();
|
||||
$dispatcher->dispatch(new DisplayGroupLoadEvent($displayGroup), DisplayGroupLoadEvent::$NAME);
|
||||
$displayGroup->delete();
|
||||
}
|
||||
}
|
||||
} else if ($function === 'reassignAll') {
|
||||
foreach ($this->displayGroupFactory->getByOwnerId($user->userId, -1) as $displayGroup) {
|
||||
($displayGroup->isDisplaySpecific === 1) ? $displayGroup->setOwner($systemUser->userId) : $displayGroup->setOwner($newUser->getOwnerId());
|
||||
$displayGroup->save(['saveTags' => false, 'manageDynamicDisplayLinks' => false]);
|
||||
}
|
||||
} else if ($function === 'countChildren') {
|
||||
$displayGroups = $this->displayGroupFactory->getByOwnerId($user->userId, -1);
|
||||
|
||||
$count = count($displayGroups);
|
||||
$this->getLogger()->debug(
|
||||
sprintf(
|
||||
'Counted Children Display Groups on User ID %d, there are %d',
|
||||
$user->userId,
|
||||
$count
|
||||
)
|
||||
);
|
||||
|
||||
$event->setReturnValue($event->getReturnValue() + $count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MediaFullLoadEvent $event
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function onMediaLoad(MediaFullLoadEvent $event)
|
||||
{
|
||||
$media = $event->getMedia();
|
||||
|
||||
$media->displayGroups = $this->displayGroupFactory->getByMediaId($media->mediaId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ParsePermissionEntityEvent $event
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function onParsePermissions(ParsePermissionEntityEvent $event)
|
||||
{
|
||||
$this->getLogger()->debug('onParsePermissions');
|
||||
$event->setObject($this->displayGroupFactory->getById($event->getObjectId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FolderMovingEvent $event
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function onFolderMoving(FolderMovingEvent $event)
|
||||
{
|
||||
$folder = $event->getFolder();
|
||||
$newFolder = $event->getNewFolder();
|
||||
|
||||
foreach ($this->displayGroupFactory->getbyFolderId($folder->getId()) as $displayGroup) {
|
||||
$displayGroup->folderId = $newFolder->getId();
|
||||
$displayGroup->permissionsFolderId = $newFolder->getPermissionFolderIdOrThis();
|
||||
$displayGroup->updateFolders('displaygroup');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TagDeleteEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return void
|
||||
*/
|
||||
public function onTagDelete(TagDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher): void
|
||||
{
|
||||
$displays = $this->storageService->select('
|
||||
SELECT lktagdisplaygroup.displayGroupId
|
||||
FROM `lktagdisplaygroup`
|
||||
INNER JOIN `displaygroup`
|
||||
ON `lktagdisplaygroup`.displayGroupId = `displaygroup`.displayGroupId
|
||||
AND `displaygroup`.isDisplaySpecific = 1
|
||||
WHERE `lktagdisplaygroup`.tagId = :tagId', [
|
||||
'tagId' => $event->getTagId()
|
||||
]);
|
||||
|
||||
$this->storageService->update(
|
||||
'DELETE FROM `lktagdisplaygroup` WHERE `lktagdisplaygroup`.tagId = :tagId',
|
||||
['tagId' => $event->getTagId()]
|
||||
);
|
||||
|
||||
if (count($displays) > 0) {
|
||||
$dispatcher->dispatch(
|
||||
new TriggerTaskEvent('\Xibo\XTR\MaintenanceRegularTask', 'DYNAMIC_DISPLAY_GROUP_ASSESSED'),
|
||||
TriggerTaskEvent::$NAME
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update dynamic display groups' dynamicCriteriaTags when a tag is edited from the tag administration.
|
||||
*
|
||||
* @param TagEditEvent $event
|
||||
* @return void
|
||||
* @throws NotFoundException
|
||||
* @throws GeneralException
|
||||
*/
|
||||
public function onTagEdit(TagEditEvent $event): void
|
||||
{
|
||||
// Retrieve all dynamic display groups
|
||||
$displayGroups = $this->displayGroupFactory->getByIsDynamic(1);
|
||||
|
||||
foreach ($displayGroups as $displayGroup) {
|
||||
// Convert the tag string into an array for easier processing
|
||||
$tags = explode(',', $displayGroup->dynamicCriteriaTags);
|
||||
|
||||
$displayGroup->setDisplayFactory($this->displayFactory);
|
||||
|
||||
foreach ($tags as &$tag) {
|
||||
$tag = trim($tag);
|
||||
|
||||
// Split tag into name and value (e.g. "tagName|tagValue")
|
||||
$parts = explode('|', $tag, 2);
|
||||
$tagName = $parts[0];
|
||||
$tagValue = $parts[1] ?? null;
|
||||
|
||||
// If tag name matches the old tag, update the name while keeping the value (if any)
|
||||
if ($tagName == $event->getOldTag()) {
|
||||
$tagName = $event->getNewTag();
|
||||
$tag = $tagValue !== null ? $tagName . '|' . $tagValue : $tagName;
|
||||
|
||||
$displayGroup->dynamicCriteriaTags = implode(',', $tags);
|
||||
$displayGroup->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
271
lib/Listener/LayoutListener.php
Normal file
271
lib/Listener/LayoutListener.php
Normal file
@@ -0,0 +1,271 @@
|
||||
<?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\Listener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Entity\Layout;
|
||||
use Xibo\Entity\Region;
|
||||
use Xibo\Event\DisplayGroupLoadEvent;
|
||||
use Xibo\Event\LayoutOwnerChangeEvent;
|
||||
use Xibo\Event\LayoutSharingChangeEvent;
|
||||
use Xibo\Event\MediaDeleteEvent;
|
||||
use Xibo\Event\MediaFullLoadEvent;
|
||||
use Xibo\Event\PlaylistDeleteEvent;
|
||||
use Xibo\Event\RegionAddedEvent;
|
||||
use Xibo\Event\TagDeleteEvent;
|
||||
use Xibo\Event\UserDeleteEvent;
|
||||
use Xibo\Factory\LayoutFactory;
|
||||
use Xibo\Factory\PermissionFactory;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
|
||||
/**
|
||||
* Layout events
|
||||
*/
|
||||
class LayoutListener
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/**
|
||||
* @param LayoutFactory $layoutFactory
|
||||
* @param StorageServiceInterface $storageService
|
||||
* @param \Xibo\Factory\PermissionFactory $permissionFactory
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly LayoutFactory $layoutFactory,
|
||||
private readonly StorageServiceInterface $storageService,
|
||||
private readonly PermissionFactory $permissionFactory
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return $this
|
||||
*/
|
||||
public function registerWithDispatcher(EventDispatcherInterface $dispatcher) : LayoutListener
|
||||
{
|
||||
$dispatcher->addListener(MediaDeleteEvent::$NAME, [$this, 'onMediaDelete']);
|
||||
$dispatcher->addListener(UserDeleteEvent::$NAME, [$this, 'onUserDelete']);
|
||||
$dispatcher->addListener(DisplayGroupLoadEvent::$NAME, [$this, 'onDisplayGroupLoad']);
|
||||
$dispatcher->addListener(MediaFullLoadEvent::$NAME, [$this, 'onMediaLoad']);
|
||||
$dispatcher->addListener(LayoutOwnerChangeEvent::$NAME, [$this, 'onOwnerChange']);
|
||||
$dispatcher->addListener(TagDeleteEvent::$NAME, [$this, 'onTagDelete']);
|
||||
$dispatcher->addListener(PlaylistDeleteEvent::$NAME, [$this, 'onPlaylistDelete']);
|
||||
$dispatcher->addListener(LayoutSharingChangeEvent::$NAME, [$this, 'onLayoutSharingChange']);
|
||||
$dispatcher->addListener(RegionAddedEvent::$NAME, [$this, 'onRegionAdded']);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MediaDeleteEvent $event
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\GeneralException
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function onMediaDelete(MediaDeleteEvent $event)
|
||||
{
|
||||
$media = $event->getMedia();
|
||||
$parentMedia = $event->getParentMedia();
|
||||
|
||||
foreach ($this->layoutFactory->getByBackgroundImageId($media->mediaId) as $layout) {
|
||||
if ($media->mediaType == 'image' && $parentMedia != null) {
|
||||
$this->getLogger()->debug(sprintf(
|
||||
'Updating layouts with the old media %d as the background image.',
|
||||
$media->mediaId
|
||||
));
|
||||
$this->getLogger()->debug(sprintf(
|
||||
'Found layout that needs updating. ID = %d. Setting background image id to %d',
|
||||
$layout->layoutId,
|
||||
$parentMedia->mediaId
|
||||
));
|
||||
|
||||
$layout->backgroundImageId = $parentMedia->mediaId;
|
||||
} else {
|
||||
$layout->backgroundImageId = null;
|
||||
}
|
||||
|
||||
$layout->save(Layout::$saveOptionsMinimum);
|
||||
}
|
||||
|
||||
// do we have any full screen Layout linked to this Media item?
|
||||
$linkedLayout = $this->layoutFactory->getLinkedFullScreenLayout('media', $media->mediaId);
|
||||
|
||||
if (!empty($linkedLayout)) {
|
||||
$linkedLayout->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserDeleteEvent $event
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\GeneralException
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function onUserDelete(UserDeleteEvent $event)
|
||||
{
|
||||
$user = $event->getUser();
|
||||
$function = $event->getFunction();
|
||||
$newUser = $event->getNewUser();
|
||||
|
||||
if ($function === 'delete') {
|
||||
// Delete any Layouts
|
||||
foreach ($this->layoutFactory->getByOwnerId($user->userId) as $layout) {
|
||||
$layout->delete();
|
||||
}
|
||||
} else if ($function === 'reassignAll') {
|
||||
// Reassign layouts, regions, region Playlists and Widgets.
|
||||
foreach ($this->layoutFactory->getByOwnerId($user->userId) as $layout) {
|
||||
$layout->setOwner($newUser->userId, true);
|
||||
$layout->save(['notify' => false, 'saveTags' => false, 'setBuildRequired' => false]);
|
||||
}
|
||||
} else if ($function === 'countChildren') {
|
||||
$layouts = $this->layoutFactory->getByOwnerId($user->userId);
|
||||
|
||||
$count = count($layouts);
|
||||
$this->getLogger()->debug(
|
||||
sprintf(
|
||||
'Counted Children Layouts on User ID %d, there are %d',
|
||||
$user->userId,
|
||||
$count
|
||||
)
|
||||
);
|
||||
|
||||
$event->setReturnValue($event->getReturnValue() + $count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DisplayGroupLoadEvent $event
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function onDisplayGroupLoad(DisplayGroupLoadEvent $event)
|
||||
{
|
||||
$displayGroup = $event->getDisplayGroup();
|
||||
|
||||
$displayGroup->layouts = ($displayGroup->displayGroupId != null)
|
||||
? $this->layoutFactory->getByDisplayGroupId($displayGroup->displayGroupId)
|
||||
: [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MediaFullLoadEvent $event
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function onMediaLoad(MediaFullLoadEvent $event)
|
||||
{
|
||||
$media = $event->getMedia();
|
||||
|
||||
$media->layoutBackgroundImages = $this->layoutFactory->getByBackgroundImageId($media->mediaId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param LayoutOwnerChangeEvent $event
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\GeneralException
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function onOwnerChange(LayoutOwnerChangeEvent $event)
|
||||
{
|
||||
$campaignId = $event->getCampaignId();
|
||||
$ownerId = $event->getOwnerId();
|
||||
|
||||
foreach ($this->layoutFactory->getByCampaignId($campaignId, true, true) as $layout) {
|
||||
$layout->setOwner($ownerId, true);
|
||||
$layout->save(['notify' => false]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TagDeleteEvent $event
|
||||
* @return void
|
||||
*/
|
||||
public function onTagDelete(TagDeleteEvent $event)
|
||||
{
|
||||
$this->storageService->update(
|
||||
'DELETE FROM `lktaglayout` WHERE `lktaglayout`.tagId = :tagId',
|
||||
['tagId' => $event->getTagId()]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PlaylistDeleteEvent $event
|
||||
* @return void
|
||||
*/
|
||||
public function onPlaylistDelete(PlaylistDeleteEvent $event)
|
||||
{
|
||||
$playlist = $event->getPlaylist();
|
||||
|
||||
// do we have any full screen Layout linked to this playlist?
|
||||
$layout = $this->layoutFactory->getLinkedFullScreenLayout('playlist', $playlist->playlistId);
|
||||
|
||||
if (!empty($layout)) {
|
||||
$layout->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Xibo\Event\LayoutSharingChangeEvent $event
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\GeneralException
|
||||
*/
|
||||
public function onLayoutSharingChange(LayoutSharingChangeEvent $event): void
|
||||
{
|
||||
// Check to see if this Campaign has any Canvas regions
|
||||
$layouts = $this->layoutFactory->getByCampaignId($event->getCampaignId(), false, true);
|
||||
foreach ($layouts as $layout) {
|
||||
$layout->load([
|
||||
'loadPlaylists' => false,
|
||||
'loadPermissions' => false,
|
||||
'loadCampaigns' => false,
|
||||
'loadActions' => false,
|
||||
]);
|
||||
|
||||
foreach ($layout->regions as $region) {
|
||||
if ($region->type === 'canvas') {
|
||||
$event->addCanvasRegionId($region->getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Xibo\Event\RegionAddedEvent $event
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\InvalidArgumentException
|
||||
*/
|
||||
public function onRegionAdded(RegionAddedEvent $event): void
|
||||
{
|
||||
if ($event->getRegion()->type === 'canvas') {
|
||||
// Set this layout's permissions on the canvas region
|
||||
$entityId = $this->permissionFactory->getEntityId(Region::class);
|
||||
foreach ($event->getLayout()->permissions as $permission) {
|
||||
$new = clone $permission;
|
||||
$new->entityId = $entityId;
|
||||
$new->objectId = $event->getRegion()->getId();
|
||||
$new->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
49
lib/Listener/ListenerConfigTrait.php
Normal file
49
lib/Listener/ListenerConfigTrait.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2023 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\Listener;
|
||||
|
||||
use Xibo\Service\ConfigServiceInterface;
|
||||
|
||||
trait ListenerConfigTrait
|
||||
{
|
||||
/** @var ConfigServiceInterface */
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* @param ConfigServiceInterface $config
|
||||
* @return $this
|
||||
*/
|
||||
public function useConfig(ConfigServiceInterface $config)
|
||||
{
|
||||
$this->config = $config;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ConfigServiceInterface
|
||||
*/
|
||||
protected function getConfig()
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
}
|
||||
53
lib/Listener/ListenerLoggerTrait.php
Normal file
53
lib/Listener/ListenerLoggerTrait.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener;
|
||||
|
||||
use Psr\Log\NullLogger;
|
||||
|
||||
trait ListenerLoggerTrait
|
||||
{
|
||||
/** @var \Psr\Log\LoggerInterface */
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* @param \Psr\Log\LoggerInterface $logger
|
||||
* @return $this
|
||||
*/
|
||||
public function useLogger($logger)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Psr\Log\LoggerInterface
|
||||
*/
|
||||
protected function getLogger()
|
||||
{
|
||||
if ($this->logger === null) {
|
||||
$this->logger = new NullLogger();
|
||||
}
|
||||
|
||||
return $this->logger;
|
||||
}
|
||||
}
|
||||
194
lib/Listener/MediaListener.php
Normal file
194
lib/Listener/MediaListener.php
Normal file
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2022 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Event\DisplayGroupLoadEvent;
|
||||
use Xibo\Event\FolderMovingEvent;
|
||||
use Xibo\Event\MediaDeleteEvent;
|
||||
use Xibo\Event\ParsePermissionEntityEvent;
|
||||
use Xibo\Event\TagDeleteEvent;
|
||||
use Xibo\Event\UserDeleteEvent;
|
||||
use Xibo\Factory\MediaFactory;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
use Xibo\Support\Exception\NotFoundException;
|
||||
|
||||
/**
|
||||
* Media events
|
||||
*/
|
||||
class MediaListener
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/**
|
||||
* @var MediaFactory
|
||||
*/
|
||||
private $mediaFactory;
|
||||
/**
|
||||
* @var StorageServiceInterface
|
||||
*/
|
||||
private $storageService;
|
||||
|
||||
/**
|
||||
* @param MediaFactory $mediaFactory
|
||||
* @param StorageServiceInterface $storageService
|
||||
*/
|
||||
public function __construct(
|
||||
MediaFactory $mediaFactory,
|
||||
StorageServiceInterface $storageService
|
||||
) {
|
||||
$this->mediaFactory = $mediaFactory;
|
||||
$this->storageService = $storageService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return $this
|
||||
*/
|
||||
public function registerWithDispatcher(EventDispatcherInterface $dispatcher) : MediaListener
|
||||
{
|
||||
$dispatcher->addListener(UserDeleteEvent::$NAME, [$this, 'onUserDelete']);
|
||||
$dispatcher->addListener(DisplayGroupLoadEvent::$NAME, [$this, 'onDisplayGroupLoad']);
|
||||
$dispatcher->addListener(ParsePermissionEntityEvent::$NAME . 'media', [$this, 'onParsePermissions']);
|
||||
$dispatcher->addListener(FolderMovingEvent::$NAME, [$this, 'onFolderMoving']);
|
||||
$dispatcher->addListener(TagDeleteEvent::$NAME, [$this, 'onTagDelete']);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserDeleteEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return void
|
||||
* @throws NotFoundException
|
||||
* @throws \Xibo\Support\Exception\ConfigurationException
|
||||
* @throws \Xibo\Support\Exception\DuplicateEntityException
|
||||
* @throws \Xibo\Support\Exception\GeneralException
|
||||
* @throws \Xibo\Support\Exception\InvalidArgumentException
|
||||
*/
|
||||
public function onUserDelete(UserDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$user = $event->getUser();
|
||||
$function = $event->getFunction();
|
||||
$newUser = $event->getNewUser();
|
||||
$systemUser = $event->getSystemUser();
|
||||
|
||||
if ($function === 'delete') {
|
||||
// Delete any media
|
||||
foreach ($this->mediaFactory->getByOwnerId($user->userId, 1) as $media) {
|
||||
// If there is a parent, bring it back
|
||||
try {
|
||||
$parentMedia = $this->mediaFactory->getParentById($media->mediaId);
|
||||
$parentMedia->isEdited = 0;
|
||||
$parentMedia->parentId = null;
|
||||
$parentMedia->save(['validate' => false]);
|
||||
} catch (NotFoundException $e) {
|
||||
// This is fine, no parent
|
||||
$parentMedia = null;
|
||||
}
|
||||
|
||||
// if this User owns any module files, reassign to systemUser instead of deleting.
|
||||
if ($media->mediaType === 'module') {
|
||||
$media->setOwner($systemUser->userId);
|
||||
$media->save();
|
||||
} else {
|
||||
$dispatcher->dispatch(new MediaDeleteEvent($media, $parentMedia, true), MediaDeleteEvent::$NAME);
|
||||
$media->delete();
|
||||
}
|
||||
}
|
||||
} else if ($function === 'reassignAll') {
|
||||
foreach ($this->mediaFactory->getByOwnerId($user->userId, 1) as $media) {
|
||||
($media->mediaType === 'module') ? $media->setOwner($systemUser->userId) : $media->setOwner($newUser->getOwnerId());
|
||||
$media->save();
|
||||
}
|
||||
} else if ($function === 'countChildren') {
|
||||
$media = $this->mediaFactory->getByOwnerId($user->userId, 1);
|
||||
|
||||
$count = count($media);
|
||||
$this->getLogger()->debug(
|
||||
sprintf(
|
||||
'Counted Children Media on User ID %d, there are %d',
|
||||
$user->userId,
|
||||
$count
|
||||
)
|
||||
);
|
||||
|
||||
$event->setReturnValue($event->getReturnValue() + $count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DisplayGroupLoadEvent $event
|
||||
* @return void
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
public function onDisplayGroupLoad(DisplayGroupLoadEvent $event)
|
||||
{
|
||||
$displayGroup = $event->getDisplayGroup();
|
||||
|
||||
$displayGroup->media = ($displayGroup->displayGroupId != null)
|
||||
? $this->mediaFactory->getByDisplayGroupId($displayGroup->displayGroupId)
|
||||
: [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ParsePermissionEntityEvent $event
|
||||
* @return void
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
public function onParsePermissions(ParsePermissionEntityEvent $event)
|
||||
{
|
||||
$this->getLogger()->debug('onParsePermissions');
|
||||
$event->setObject($this->mediaFactory->getById($event->getObjectId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FolderMovingEvent $event
|
||||
* @return void
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
public function onFolderMoving(FolderMovingEvent $event)
|
||||
{
|
||||
$folder = $event->getFolder();
|
||||
$newFolder = $event->getNewFolder();
|
||||
|
||||
foreach ($this->mediaFactory->getByFolderId($folder->getId()) as $media) {
|
||||
$media->folderId = $newFolder->getId();
|
||||
$media->permissionsFolderId = $newFolder->getPermissionFolderIdOrThis();
|
||||
$media->updateFolders('media');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TagDeleteEvent $event
|
||||
* @return void
|
||||
*/
|
||||
public function onTagDelete(TagDeleteEvent $event)
|
||||
{
|
||||
$this->storageService->update(
|
||||
'DELETE FROM `lktagmedia` WHERE `lktagmedia`.tagId = :tagId',
|
||||
['tagId' => $event->getTagId()]
|
||||
);
|
||||
}
|
||||
}
|
||||
167
lib/Listener/MenuBoardProviderListener.php
Normal file
167
lib/Listener/MenuBoardProviderListener.php
Normal file
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2023 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\Listener;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Event\MenuBoardCategoryRequest;
|
||||
use Xibo\Event\MenuBoardModifiedDtRequest;
|
||||
use Xibo\Event\MenuBoardProductRequest;
|
||||
use Xibo\Factory\MenuBoardCategoryFactory;
|
||||
use Xibo\Factory\MenuBoardFactory;
|
||||
use Xibo\Support\Exception\NotFoundException;
|
||||
|
||||
/**
|
||||
* Listener for dealing with a menu board provider
|
||||
*/
|
||||
class MenuBoardProviderListener
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
private MenuBoardFactory $menuBoardFactory;
|
||||
|
||||
private MenuBoardCategoryFactory $menuBoardCategoryFactory;
|
||||
|
||||
public function __construct(MenuBoardFactory $menuBoardFactory, MenuBoardCategoryFactory $menuBoardCategoryFactory)
|
||||
{
|
||||
$this->menuBoardFactory = $menuBoardFactory;
|
||||
$this->menuBoardCategoryFactory = $menuBoardCategoryFactory;
|
||||
}
|
||||
|
||||
public function registerWithDispatcher(EventDispatcherInterface $dispatcher): MenuBoardProviderListener
|
||||
{
|
||||
$dispatcher->addListener(MenuBoardProductRequest::$NAME, [$this, 'onProductRequest']);
|
||||
$dispatcher->addListener(MenuBoardCategoryRequest::$NAME, [$this, 'onCategoryRequest']);
|
||||
$dispatcher->addListener(MenuBoardModifiedDtRequest::$NAME, [$this, 'onModifiedDtRequest']);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function onProductRequest(MenuBoardProductRequest $event): void
|
||||
{
|
||||
$this->getLogger()->debug('onProductRequest: data source is ' . $event->getDataProvider()->getDataSource());
|
||||
|
||||
$dataProvider = $event->getDataProvider();
|
||||
$menuId = $dataProvider->getProperty('menuId', 0);
|
||||
if (empty($menuId)) {
|
||||
$this->getLogger()->debug('onProductRequest: no menuId.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Sorting
|
||||
$desc = $dataProvider->getProperty('sortDescending') == 1 ? ' DESC' : '';
|
||||
$sort = match ($dataProvider->getProperty('sortField')) {
|
||||
'name' => '`name`' . $desc,
|
||||
'price' => '`price`' . $desc,
|
||||
'id' => '`menuProductId`' . $desc,
|
||||
default => '`displayOrder`' . $desc,
|
||||
};
|
||||
|
||||
// Build a filter
|
||||
$filter = [
|
||||
'menuId' => $menuId,
|
||||
];
|
||||
|
||||
$categoryId = $dataProvider->getProperty('categoryId');
|
||||
$this->getLogger()->debug('onProductRequest: $categoryId: ' . $categoryId);
|
||||
if ($categoryId !== null && $categoryId !== '') {
|
||||
$filter['menuCategoryId'] = intval($categoryId);
|
||||
}
|
||||
|
||||
// Show Unavailable?
|
||||
if ($dataProvider->getProperty('showUnavailable', 0) === 0) {
|
||||
$filter['availability'] = 1;
|
||||
}
|
||||
|
||||
// limits?
|
||||
$lowerLimit = $dataProvider->getProperty('lowerLimit', 0);
|
||||
$upperLimit = $dataProvider->getProperty('upperLimit', 0);
|
||||
if ($lowerLimit !== 0 || $upperLimit !== 0) {
|
||||
// Start should be the lower limit
|
||||
// Size should be the distance between upper and lower
|
||||
$filter['start'] = $lowerLimit;
|
||||
$filter['length'] = $upperLimit - $lowerLimit;
|
||||
|
||||
$this->getLogger()->debug('onProductRequest: applied limits, start: '
|
||||
. $filter['start'] . ', length: ' . $filter['length']);
|
||||
}
|
||||
|
||||
$products = $this->menuBoardCategoryFactory->getProductData([$sort], $filter);
|
||||
|
||||
foreach ($products as $menuBoardProduct) {
|
||||
$menuBoardProduct->productOptions = $menuBoardProduct->getOptions();
|
||||
$product = $menuBoardProduct->toProduct();
|
||||
|
||||
// Convert the image to a library image?
|
||||
if ($product->image !== null) {
|
||||
// The content is the ID of the image
|
||||
try {
|
||||
$product->image = $dataProvider->addLibraryFile(intval($product->image));
|
||||
} catch (NotFoundException $notFoundException) {
|
||||
$this->getLogger()->error('onProductRequest: Invalid library media reference: ' . $product->image);
|
||||
$product->image = null;
|
||||
}
|
||||
}
|
||||
$dataProvider->addItem($product);
|
||||
}
|
||||
|
||||
$dataProvider->setIsHandled();
|
||||
}
|
||||
|
||||
public function onCategoryRequest(MenuBoardCategoryRequest $event): void
|
||||
{
|
||||
$this->getLogger()->debug('onCategoryRequest: data source is ' . $event->getDataProvider()->getDataSource());
|
||||
|
||||
$dataProvider = $event->getDataProvider();
|
||||
$menuId = $dataProvider->getProperty('menuId', 0);
|
||||
if (empty($menuId)) {
|
||||
$this->getLogger()->debug('onCategoryRequest: no menuId.');
|
||||
return;
|
||||
}
|
||||
$categoryId = $dataProvider->getProperty('categoryId', 0);
|
||||
if (empty($categoryId)) {
|
||||
$this->getLogger()->debug('onCategoryRequest: no categoryId.');
|
||||
return;
|
||||
}
|
||||
|
||||
$category = $this->menuBoardCategoryFactory->getById($categoryId)->toProductCategory();
|
||||
// Convert the image to a library image?
|
||||
if ($category->image !== null) {
|
||||
// The content is the ID of the image
|
||||
try {
|
||||
$category->image = $dataProvider->addLibraryFile(intval($category->image));
|
||||
} catch (NotFoundException $notFoundException) {
|
||||
$this->getLogger()->error('onCategoryRequest: Invalid library media reference: ' . $category->image);
|
||||
$category->image = null;
|
||||
}
|
||||
}
|
||||
$dataProvider->addItem($category);
|
||||
|
||||
$dataProvider->setIsHandled();
|
||||
}
|
||||
|
||||
public function onModifiedDtRequest(MenuBoardModifiedDtRequest $event): void
|
||||
{
|
||||
$menu = $this->menuBoardFactory->getById($event->getDataSetId());
|
||||
$event->setModifiedDt(Carbon::createFromTimestamp($menu->modifiedDt));
|
||||
}
|
||||
}
|
||||
58
lib/Listener/ModuleTemplateListener.php
Normal file
58
lib/Listener/ModuleTemplateListener.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?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\Listener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Event\ParsePermissionEntityEvent;
|
||||
use Xibo\Factory\ModuleTemplateFactory;
|
||||
|
||||
class ModuleTemplateListener
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/** @var ModuleTemplateFactory */
|
||||
private ModuleTemplateFactory $moduleTemplateFactory;
|
||||
|
||||
public function __construct(ModuleTemplateFactory $moduleTemplateFactory)
|
||||
{
|
||||
$this->moduleTemplateFactory = $moduleTemplateFactory;
|
||||
}
|
||||
|
||||
public function registerWithDispatcher(EventDispatcherInterface $dispatcher): ModuleTemplateListener
|
||||
{
|
||||
$dispatcher->addListener(ParsePermissionEntityEvent::$NAME . 'moduleTemplate', [$this, 'onParsePermissions']);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ParsePermissionEntityEvent $event
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function onParsePermissions(ParsePermissionEntityEvent $event)
|
||||
{
|
||||
$this->getLogger()->debug('onParsePermissions');
|
||||
$event->setObject($this->moduleTemplateFactory->getUserTemplateById($event->getObjectId()));
|
||||
}
|
||||
}
|
||||
131
lib/Listener/NotificationDataProviderListener.php
Normal file
131
lib/Listener/NotificationDataProviderListener.php
Normal file
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2023 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\Listener;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Entity\User;
|
||||
use Xibo\Event\NotificationCacheKeyRequestEvent;
|
||||
use Xibo\Event\NotificationDataRequestEvent;
|
||||
use Xibo\Event\NotificationModifiedDtRequestEvent;
|
||||
use Xibo\Factory\NotificationFactory;
|
||||
use Xibo\Service\ConfigServiceInterface;
|
||||
use Xibo\Widget\Provider\DataProviderInterface;
|
||||
|
||||
/**
|
||||
* Listens to request for data from Notification.
|
||||
*/
|
||||
class NotificationDataProviderListener
|
||||
{
|
||||
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/** @var \Xibo\Service\ConfigServiceInterface */
|
||||
private $config;
|
||||
|
||||
/** @var \Xibo\Factory\NotificationFactory */
|
||||
private $notificationFactory;
|
||||
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
private $user;
|
||||
|
||||
public function __construct(
|
||||
ConfigServiceInterface $config,
|
||||
NotificationFactory $notificationFactory,
|
||||
User $user
|
||||
) {
|
||||
$this->config = $config;
|
||||
$this->notificationFactory = $notificationFactory;
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
public function registerWithDispatcher(EventDispatcherInterface $dispatcher): NotificationDataProviderListener
|
||||
{
|
||||
$dispatcher->addListener(NotificationDataRequestEvent::$NAME, [$this, 'onDataRequest']);
|
||||
$dispatcher->addListener(NotificationModifiedDtRequestEvent::$NAME, [$this, 'onModifiedDtRequest']);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function onDataRequest(NotificationDataRequestEvent $event)
|
||||
{
|
||||
$this->getData($event->getDataProvider());
|
||||
}
|
||||
|
||||
public function getData(DataProviderInterface $dataProvider)
|
||||
{
|
||||
$age = $dataProvider->getProperty('age', 0);
|
||||
|
||||
$filter = [
|
||||
'releaseDt' => ($age === 0) ? null : Carbon::now()->subMinutes($age)->unix(),
|
||||
'onlyReleased' => 1,
|
||||
];
|
||||
|
||||
if ($dataProvider->isPreview()) {
|
||||
$filter['userId'] = $this->user->getId();
|
||||
} else {
|
||||
$filter['displayId'] = $dataProvider->getDisplayId();
|
||||
}
|
||||
|
||||
$sort = ['releaseDt DESC', 'createDt DESC', 'subject'];
|
||||
|
||||
$notifications = $this->notificationFactory->query($sort, $filter);
|
||||
|
||||
foreach ($notifications as $notification) {
|
||||
$item = [];
|
||||
$item['subject'] = $notification->subject;
|
||||
$item['body'] = strip_tags($notification->body);
|
||||
$item['date'] = Carbon::createFromTimestamp($notification->releaseDt)->format('c');
|
||||
$item['createdAt'] = Carbon::createFromTimestamp($notification->createDt)->format('c');
|
||||
|
||||
$dataProvider->addItem($item);
|
||||
}
|
||||
|
||||
$dataProvider->setIsHandled();
|
||||
}
|
||||
|
||||
public function onModifiedDtRequest(NotificationModifiedDtRequestEvent $event)
|
||||
{
|
||||
$this->getLogger()->debug('onModifiedDtRequest');
|
||||
|
||||
// Get the latest notification according to the filter provided.
|
||||
$displayId = $event->getDisplayId();
|
||||
|
||||
// If we're a user, we should always refresh
|
||||
if ($displayId === 0) {
|
||||
$event->setModifiedDt(Carbon::maxValue());
|
||||
return;
|
||||
}
|
||||
|
||||
$notifications = $this->notificationFactory->query(['releaseDt DESC'], [
|
||||
'onlyReleased' => 1,
|
||||
'displayId' => $displayId,
|
||||
'length' => 1,
|
||||
]);
|
||||
|
||||
if (count($notifications) > 0) {
|
||||
$event->setModifiedDt(Carbon::createFromTimestamp($notifications[0]->releaseDt));
|
||||
}
|
||||
}
|
||||
}
|
||||
53
lib/Listener/OnCommandDelete.php
Normal file
53
lib/Listener/OnCommandDelete.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener;
|
||||
|
||||
use Xibo\Event\CommandDeleteEvent;
|
||||
use Xibo\Factory\DisplayProfileFactory;
|
||||
|
||||
class OnCommandDelete
|
||||
{
|
||||
/**
|
||||
* @var DisplayProfileFactory
|
||||
*/
|
||||
private $displayProfileFactory;
|
||||
|
||||
public function __construct(DisplayProfileFactory $displayProfileFactory)
|
||||
{
|
||||
$this->displayProfileFactory = $displayProfileFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
* @throws \Xibo\Support\Exception\InvalidArgumentException
|
||||
*/
|
||||
public function __invoke(CommandDeleteEvent $event)
|
||||
{
|
||||
$command = $event->getCommand();
|
||||
|
||||
foreach ($this->displayProfileFactory->getByCommandId($command->commandId) as $displayProfile) {
|
||||
$displayProfile->unassignCommand($command);
|
||||
$displayProfile->save(['validate' => false]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnDisplayGroupLoad;
|
||||
|
||||
use Xibo\Event\DisplayGroupLoadEvent;
|
||||
use Xibo\Factory\DisplayFactory;
|
||||
|
||||
class DisplayGroupDisplayListener
|
||||
{
|
||||
/**
|
||||
* @var DisplayFactory
|
||||
*/
|
||||
private $displayFactory;
|
||||
|
||||
public function __construct(DisplayFactory $displayFactory)
|
||||
{
|
||||
$this->displayFactory = $displayFactory;
|
||||
}
|
||||
|
||||
public function __invoke(DisplayGroupLoadEvent $event)
|
||||
{
|
||||
$displayGroup = $event->getDisplayGroup();
|
||||
$displayGroup->setDisplayFactory($this->displayFactory);
|
||||
|
||||
$displayGroup->displays = $this->displayFactory->getByDisplayGroupId($displayGroup->displayGroupId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnDisplayGroupLoad;
|
||||
|
||||
use Xibo\Event\DisplayGroupLoadEvent;
|
||||
use Xibo\Factory\ScheduleFactory;
|
||||
|
||||
class DisplayGroupScheduleListener
|
||||
{
|
||||
/**
|
||||
* @var ScheduleFactory
|
||||
*/
|
||||
private $scheduleFactory;
|
||||
|
||||
public function __construct(ScheduleFactory $scheduleFactory)
|
||||
{
|
||||
$this->scheduleFactory = $scheduleFactory;
|
||||
}
|
||||
|
||||
public function __invoke(DisplayGroupLoadEvent $event)
|
||||
{
|
||||
$displayGroup = $event->getDisplayGroup();
|
||||
|
||||
$displayGroup->events = ($displayGroup->displayGroupId != null)
|
||||
? $this->scheduleFactory->getByDisplayGroupId($displayGroup->displayGroupId)
|
||||
: [];
|
||||
}
|
||||
}
|
||||
50
lib/Listener/OnFolderMoving/DataSetListener.php
Normal file
50
lib/Listener/OnFolderMoving/DataSetListener.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2022 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnFolderMoving;
|
||||
|
||||
use Xibo\Event\FolderMovingEvent;
|
||||
use Xibo\Factory\DataSetFactory;
|
||||
|
||||
class DataSetListener
|
||||
{
|
||||
/**
|
||||
* @var DataSetFactory
|
||||
*/
|
||||
private $dataSetFactory;
|
||||
|
||||
public function __construct(DataSetFactory $dataSetFactory)
|
||||
{
|
||||
$this->dataSetFactory = $dataSetFactory;
|
||||
}
|
||||
|
||||
public function __invoke(FolderMovingEvent $event)
|
||||
{
|
||||
$folder = $event->getFolder();
|
||||
$newFolder = $event->getNewFolder();
|
||||
|
||||
foreach ($this->dataSetFactory->getByFolderId($folder->getId()) as $dataSet) {
|
||||
$dataSet->folderId = $newFolder->getId();
|
||||
$dataSet->permissionsFolderId = $newFolder->getPermissionFolderIdOrThis();
|
||||
$dataSet->updateFolders('dataset');
|
||||
}
|
||||
}
|
||||
}
|
||||
55
lib/Listener/OnFolderMoving/FolderListener.php
Normal file
55
lib/Listener/OnFolderMoving/FolderListener.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2022 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnFolderMoving;
|
||||
|
||||
use Xibo\Event\FolderMovingEvent;
|
||||
use Xibo\Factory\FolderFactory;
|
||||
|
||||
class FolderListener
|
||||
{
|
||||
/**
|
||||
* @var FolderFactory
|
||||
*/
|
||||
private $folderFactory;
|
||||
|
||||
public function __construct(FolderFactory $folderFactory)
|
||||
{
|
||||
$this->folderFactory = $folderFactory;
|
||||
}
|
||||
|
||||
public function __invoke(FolderMovingEvent $event)
|
||||
{
|
||||
$merge = $event->getIsMerge();
|
||||
|
||||
if ($merge) {
|
||||
$folder = $event->getFolder();
|
||||
$newFolder = $event->getNewFolder();
|
||||
|
||||
// on merge we delete the original Folder and move its content to the new selected folder
|
||||
// sub-folders are moved to their new parent as well
|
||||
foreach (array_filter(explode(',', $folder->children)) as $childFolderId) {
|
||||
$childFolder = $this->folderFactory->getById($childFolderId, 0);
|
||||
$childFolder->updateFoldersAfterMove($folder->getId(), $newFolder->getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
50
lib/Listener/OnFolderMoving/MenuBoardListener.php
Normal file
50
lib/Listener/OnFolderMoving/MenuBoardListener.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2022 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnFolderMoving;
|
||||
|
||||
use Xibo\Event\FolderMovingEvent;
|
||||
use Xibo\Factory\MenuBoardFactory;
|
||||
|
||||
class MenuBoardListener
|
||||
{
|
||||
/**
|
||||
* @var MenuBoardFactory
|
||||
*/
|
||||
private $menuBoardFactory;
|
||||
|
||||
public function __construct(MenuBoardFactory $menuBoardFactory)
|
||||
{
|
||||
$this->menuBoardFactory = $menuBoardFactory;
|
||||
}
|
||||
|
||||
public function __invoke(FolderMovingEvent $event)
|
||||
{
|
||||
$folder = $event->getFolder();
|
||||
$newFolder = $event->getNewFolder();
|
||||
|
||||
foreach ($this->menuBoardFactory->getbyFolderId($folder->getId()) as $menuBoard) {
|
||||
$menuBoard->folderId = $newFolder->getId();
|
||||
$menuBoard->permissionsFolderId = $newFolder->getPermissionFolderIdOrThis();
|
||||
$menuBoard->updateFolders('menu_board');
|
||||
}
|
||||
}
|
||||
}
|
||||
58
lib/Listener/OnFolderMoving/UserListener.php
Normal file
58
lib/Listener/OnFolderMoving/UserListener.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2022 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnFolderMoving;
|
||||
|
||||
use Xibo\Event\FolderMovingEvent;
|
||||
use Xibo\Factory\UserFactory;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
|
||||
class UserListener
|
||||
{
|
||||
/**
|
||||
* @var UserFactory
|
||||
*/
|
||||
private $userFactory;
|
||||
/**
|
||||
* @var StorageServiceInterface
|
||||
*/
|
||||
private $store;
|
||||
|
||||
public function __construct(UserFactory $userFactory, StorageServiceInterface $store)
|
||||
{
|
||||
$this->userFactory = $userFactory;
|
||||
$this->store = $store;
|
||||
}
|
||||
|
||||
public function __invoke(FolderMovingEvent $event)
|
||||
{
|
||||
$folder = $event->getFolder();
|
||||
$newFolder = $event->getNewFolder();
|
||||
|
||||
foreach ($this->userFactory->getByHomeFolderId($folder->getId()) as $user) {
|
||||
$this->store->update('UPDATE `user` SET homeFolderId = :newFolderId WHERE homeFolderId = :oldFolderId AND userId = :userId', [
|
||||
'newFolderId' => $newFolder->getId(),
|
||||
'oldFolderId' => $folder->getId(),
|
||||
'userId' => $user->getId()
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
29
lib/Listener/OnGettingDependencyFileSize/FontsListener.php
Normal file
29
lib/Listener/OnGettingDependencyFileSize/FontsListener.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Xibo\Listener\OnGettingDependencyFileSize;
|
||||
|
||||
use Xibo\Event\DependencyFileSizeEvent;
|
||||
use Xibo\Factory\FontFactory;
|
||||
|
||||
class FontsListener
|
||||
{
|
||||
/**
|
||||
* @var FontFactory
|
||||
*/
|
||||
private $fontFactory;
|
||||
|
||||
public function __construct(FontFactory $fontFactory)
|
||||
{
|
||||
$this->fontFactory = $fontFactory;
|
||||
}
|
||||
|
||||
public function __invoke(DependencyFileSizeEvent $event)
|
||||
{
|
||||
$fontsSize = $this->fontFactory->getFontsSizeAndCount();
|
||||
$event->addResult([
|
||||
'SumSize' => $fontsSize['SumSize'],
|
||||
'type' => 'font',
|
||||
'count' => $fontsSize['totalCount']
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Xibo\Listener\OnGettingDependencyFileSize;
|
||||
|
||||
use Xibo\Event\DependencyFileSizeEvent;
|
||||
use Xibo\Factory\PlayerVersionFactory;
|
||||
|
||||
class PlayerVersionListener
|
||||
{
|
||||
/**
|
||||
* @var PlayerVersionFactory
|
||||
*/
|
||||
private $playerVersionFactory;
|
||||
|
||||
public function __construct(PlayerVersionFactory $playerVersionFactory)
|
||||
{
|
||||
$this->playerVersionFactory = $playerVersionFactory;
|
||||
}
|
||||
|
||||
public function __invoke(DependencyFileSizeEvent $event)
|
||||
{
|
||||
$versionSize = $this->playerVersionFactory->getSizeAndCount();
|
||||
$event->addResult([
|
||||
'SumSize' => $versionSize['SumSize'],
|
||||
'type' => 'playersoftware',
|
||||
'count' => $versionSize['totalCount']
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2023 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnGettingDependencyFileSize;
|
||||
|
||||
use Xibo\Event\DependencyFileSizeEvent;
|
||||
use Xibo\Factory\SavedReportFactory;
|
||||
|
||||
class SavedReportListener
|
||||
{
|
||||
/**
|
||||
* @var SavedReportFactory
|
||||
*/
|
||||
private $savedReportFactory;
|
||||
|
||||
public function __construct(SavedReportFactory $savedReportFactory)
|
||||
{
|
||||
$this->savedReportFactory = $savedReportFactory;
|
||||
}
|
||||
|
||||
public function __invoke(DependencyFileSizeEvent $event)
|
||||
{
|
||||
$versionSize = $this->savedReportFactory->getSizeAndCount();
|
||||
$event->addResult([
|
||||
'SumSize' => $versionSize['SumSize'],
|
||||
'type' => 'savedreport',
|
||||
'count' => $versionSize['totalCount']
|
||||
]);
|
||||
}
|
||||
}
|
||||
60
lib/Listener/OnMediaDelete/MenuBoardListener.php
Normal file
60
lib/Listener/OnMediaDelete/MenuBoardListener.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnMediaDelete;
|
||||
|
||||
use Xibo\Event\MediaDeleteEvent;
|
||||
use Xibo\Factory\MenuBoardCategoryFactory;
|
||||
use Xibo\Listener\ListenerLoggerTrait;
|
||||
use Xibo\Support\Exception\InvalidArgumentException;
|
||||
|
||||
class MenuBoardListener
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/** @var MenuBoardCategoryFactory */
|
||||
private $menuBoardCategoryFactory;
|
||||
|
||||
public function __construct($menuBoardCategoryFactory)
|
||||
{
|
||||
$this->menuBoardCategoryFactory = $menuBoardCategoryFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MediaDeleteEvent $event
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function __invoke(MediaDeleteEvent $event)
|
||||
{
|
||||
$media = $event->getMedia();
|
||||
|
||||
foreach ($this->menuBoardCategoryFactory->query(null, ['mediaId' => $media->mediaId]) as $category) {
|
||||
$category->mediaId = null;
|
||||
$category->save();
|
||||
}
|
||||
|
||||
foreach ($this->menuBoardCategoryFactory->getProductData(null, ['mediaId' => $media->mediaId]) as $product) {
|
||||
$product->mediaId = null;
|
||||
$product->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
62
lib/Listener/OnMediaDelete/PurgeListListener.php
Normal file
62
lib/Listener/OnMediaDelete/PurgeListListener.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnMediaDelete;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Xibo\Event\MediaDeleteEvent;
|
||||
use Xibo\Helper\DateFormatHelper;
|
||||
use Xibo\Listener\ListenerLoggerTrait;
|
||||
use Xibo\Service\ConfigServiceInterface;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
|
||||
class PurgeListListener
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/**
|
||||
* @var StorageServiceInterface
|
||||
*/
|
||||
private $store;
|
||||
/**
|
||||
* @var ConfigServiceInterface
|
||||
*/
|
||||
private $configService;
|
||||
|
||||
public function __construct(StorageServiceInterface $store, ConfigServiceInterface $configService)
|
||||
{
|
||||
$this->store = $store;
|
||||
$this->configService = $configService;
|
||||
}
|
||||
|
||||
public function __invoke(MediaDeleteEvent $event)
|
||||
{
|
||||
// storedAs
|
||||
if ($event->isSetToPurge()) {
|
||||
$this->store->insert('INSERT INTO `purge_list` (mediaId, storedAs, expiryDate) VALUES (:mediaId, :storedAs, :expiryDate)', [
|
||||
'mediaId' => $event->getMedia()->mediaId,
|
||||
'storedAs' => $event->getMedia()->storedAs,
|
||||
'expiryDate' => Carbon::now()->addDays($this->configService->getSetting('DEFAULT_PURGE_LIST_TTL'))->format(DateFormatHelper::getSystemFormat())
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
97
lib/Listener/OnMediaDelete/WidgetListener.php
Normal file
97
lib/Listener/OnMediaDelete/WidgetListener.php
Normal file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2023 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnMediaDelete;
|
||||
|
||||
use Xibo\Event\MediaDeleteEvent;
|
||||
use Xibo\Factory\ModuleFactory;
|
||||
use Xibo\Factory\WidgetFactory;
|
||||
use Xibo\Listener\ListenerLoggerTrait;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
|
||||
class WidgetListener
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/** @var WidgetFactory */
|
||||
private $widgetFactory;
|
||||
|
||||
/** @var \Xibo\Factory\ModuleFactory */
|
||||
private $moduleFactory;
|
||||
|
||||
/** @var StorageServiceInterface */
|
||||
private $storageService;
|
||||
|
||||
public function __construct(
|
||||
StorageServiceInterface $storageService,
|
||||
WidgetFactory $widgetFactory,
|
||||
ModuleFactory $moduleFactory
|
||||
) {
|
||||
$this->storageService = $storageService;
|
||||
$this->widgetFactory = $widgetFactory;
|
||||
$this->moduleFactory = $moduleFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MediaDeleteEvent $event
|
||||
* @throws \Xibo\Support\Exception\GeneralException
|
||||
*/
|
||||
public function __invoke(MediaDeleteEvent $event)
|
||||
{
|
||||
$media = $event->getMedia();
|
||||
$parentMedia = $event->getParentMedia();
|
||||
|
||||
foreach ($this->widgetFactory->getByMediaId($media->mediaId) as $widget) {
|
||||
$widget->unassignMedia($media->mediaId);
|
||||
|
||||
if ($parentMedia != null) {
|
||||
// Assign the parent media to the widget instead
|
||||
$widget->assignMedia($parentMedia->mediaId);
|
||||
|
||||
// Swap any audio nodes over to this new widget media assignment.
|
||||
$this->storageService->update('
|
||||
UPDATE `lkwidgetaudio` SET mediaId = :mediaId WHERE widgetId = :widgetId AND mediaId = :oldMediaId
|
||||
', [
|
||||
'mediaId' => $parentMedia->mediaId,
|
||||
'widgetId' => $widget->widgetId,
|
||||
'oldMediaId' => $media->mediaId
|
||||
]);
|
||||
} else {
|
||||
// Also delete the `lkwidgetaudio`
|
||||
foreach ($widget->audio as $audio) {
|
||||
$widget->unassignAudioById($audio->mediaId);
|
||||
$audio->delete();
|
||||
}
|
||||
}
|
||||
|
||||
// This action might result in us deleting a widget (unless we are a temporary file with an expiry date)
|
||||
if ($media->mediaType != 'module'
|
||||
&& $this->moduleFactory->getByType($widget->type)->regionSpecific === 0
|
||||
&& count($widget->mediaIds) <= 0
|
||||
) {
|
||||
$widget->delete();
|
||||
} else {
|
||||
$widget->save(['saveWidgetOptions' => false]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
27
lib/Listener/OnMediaLoad/WidgetListener.php
Normal file
27
lib/Listener/OnMediaLoad/WidgetListener.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Xibo\Listener\OnMediaLoad;
|
||||
|
||||
use Xibo\Event\MediaFullLoadEvent;
|
||||
use Xibo\Factory\WidgetFactory;
|
||||
|
||||
class WidgetListener
|
||||
{
|
||||
/**
|
||||
* @var WidgetFactory
|
||||
*/
|
||||
private $widgetFactory;
|
||||
|
||||
public function __construct(WidgetFactory $widgetFactory)
|
||||
{
|
||||
$this->widgetFactory = $widgetFactory;
|
||||
}
|
||||
|
||||
public function __invoke(MediaFullLoadEvent $event)
|
||||
{
|
||||
$media = $event->getMedia();
|
||||
|
||||
$media->widgets = $this->widgetFactory->getByMediaId($media->mediaId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnParsePermissions;
|
||||
|
||||
use Xibo\Event\ParsePermissionEntityEvent;
|
||||
use Xibo\Factory\CommandFactory;
|
||||
|
||||
class PermissionsCommandListener
|
||||
{
|
||||
/**
|
||||
* @var CommandFactory
|
||||
*/
|
||||
private $commandFactory;
|
||||
|
||||
public function __construct(CommandFactory $commandFactory)
|
||||
{
|
||||
$this->commandFactory = $commandFactory;
|
||||
}
|
||||
|
||||
public function __invoke(ParsePermissionEntityEvent $event)
|
||||
{
|
||||
$event->setObject($this->commandFactory->getById($event->getObjectId()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnParsePermissions;
|
||||
|
||||
use Xibo\Event\ParsePermissionEntityEvent;
|
||||
use Xibo\Factory\DataSetFactory;
|
||||
|
||||
class PermissionsDataSetListener
|
||||
{
|
||||
/**
|
||||
* @var DataSetFactory
|
||||
*/
|
||||
private $dataSetFactory;
|
||||
|
||||
public function __construct(DataSetFactory $dataSetFactory)
|
||||
{
|
||||
$this->dataSetFactory = $dataSetFactory;
|
||||
}
|
||||
|
||||
public function __invoke(ParsePermissionEntityEvent $event)
|
||||
{
|
||||
$event->setObject($this->dataSetFactory->getById($event->getObjectId()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnParsePermissions;
|
||||
|
||||
use Xibo\Event\ParsePermissionEntityEvent;
|
||||
use Xibo\Factory\DayPartFactory;
|
||||
|
||||
class PermissionsDayPartListener
|
||||
{
|
||||
/**
|
||||
* @var DayPartFactory
|
||||
*/
|
||||
private $dayPartFactory;
|
||||
|
||||
public function __construct(DayPartFactory $dayPartFactory)
|
||||
{
|
||||
$this->dayPartFactory = $dayPartFactory;
|
||||
}
|
||||
|
||||
public function __invoke(ParsePermissionEntityEvent $event)
|
||||
{
|
||||
$event->setObject($this->dayPartFactory->getById($event->getObjectId()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnParsePermissions;
|
||||
|
||||
use Xibo\Event\ParsePermissionEntityEvent;
|
||||
use Xibo\Factory\FolderFactory;
|
||||
|
||||
class PermissionsFolderListener
|
||||
{
|
||||
/**
|
||||
* @var FolderFactory
|
||||
*/
|
||||
private $folderFactory;
|
||||
|
||||
public function __construct(FolderFactory $folderFactory)
|
||||
{
|
||||
$this->folderFactory = $folderFactory;
|
||||
}
|
||||
|
||||
public function __invoke(ParsePermissionEntityEvent $event)
|
||||
{
|
||||
$event->setObject($this->folderFactory->getById($event->getObjectId()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnParsePermissions;
|
||||
|
||||
use Xibo\Event\ParsePermissionEntityEvent;
|
||||
use Xibo\Factory\MenuBoardFactory;
|
||||
|
||||
class PermissionsMenuBoardListener
|
||||
{
|
||||
/**
|
||||
* @var MenuBoardFactory
|
||||
*/
|
||||
private $menuBoardFactory;
|
||||
|
||||
public function __construct(MenuBoardFactory $menuBoardFactory)
|
||||
{
|
||||
$this->menuBoardFactory = $menuBoardFactory;
|
||||
}
|
||||
|
||||
public function __invoke(ParsePermissionEntityEvent $event)
|
||||
{
|
||||
$event->setObject($this->menuBoardFactory->getById($event->getObjectId()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnParsePermissions;
|
||||
|
||||
use Xibo\Event\ParsePermissionEntityEvent;
|
||||
use Xibo\Factory\NotificationFactory;
|
||||
|
||||
class PermissionsNotificationListener
|
||||
{
|
||||
/**
|
||||
* @var NotificationFactory
|
||||
*/
|
||||
private $notificationFactory;
|
||||
|
||||
public function __construct(NotificationFactory $notificationFactory)
|
||||
{
|
||||
$this->notificationFactory = $notificationFactory;
|
||||
}
|
||||
|
||||
public function __invoke(ParsePermissionEntityEvent $event)
|
||||
{
|
||||
$event->setObject($this->notificationFactory->getById($event->getObjectId()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnParsePermissions;
|
||||
|
||||
use Xibo\Event\ParsePermissionEntityEvent;
|
||||
use Xibo\Factory\RegionFactory;
|
||||
|
||||
class PermissionsRegionListener
|
||||
{
|
||||
/**
|
||||
* @var RegionFactory
|
||||
*/
|
||||
private $regionFactory;
|
||||
|
||||
public function __construct(RegionFactory $regionFactory)
|
||||
{
|
||||
$this->regionFactory = $regionFactory;
|
||||
}
|
||||
|
||||
public function __invoke(ParsePermissionEntityEvent $event)
|
||||
{
|
||||
$event->setObject($this->regionFactory->getById($event->getObjectId()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnParsePermissions;
|
||||
|
||||
use Xibo\Event\ParsePermissionEntityEvent;
|
||||
use Xibo\Factory\WidgetFactory;
|
||||
|
||||
class PermissionsWidgetListener
|
||||
{
|
||||
/**
|
||||
* @var WidgetFactory
|
||||
*/
|
||||
private $widgetFactory;
|
||||
|
||||
public function __construct(WidgetFactory $widgetFactory)
|
||||
{
|
||||
$this->widgetFactory = $widgetFactory;
|
||||
}
|
||||
|
||||
public function __invoke(ParsePermissionEntityEvent $event)
|
||||
{
|
||||
$event->setObject($this->widgetFactory->getById($event->getObjectId()));
|
||||
}
|
||||
}
|
||||
46
lib/Listener/OnPlaylistMaxNumberChange.php
Normal file
46
lib/Listener/OnPlaylistMaxNumberChange.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener;
|
||||
|
||||
use Xibo\Event\PlaylistMaxNumberChangedEvent;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
|
||||
class OnPlaylistMaxNumberChange
|
||||
{
|
||||
/**
|
||||
* @var StorageServiceInterface
|
||||
*/
|
||||
private $storageService;
|
||||
|
||||
public function __construct(StorageServiceInterface $storageService)
|
||||
{
|
||||
$this->storageService = $storageService;
|
||||
}
|
||||
|
||||
public function __invoke(PlaylistMaxNumberChangedEvent $event)
|
||||
{
|
||||
$this->storageService->update('UPDATE `playlist` SET maxNumberOfItems = :newLimit WHERE isDynamic = 1 AND maxNumberOfItems > :newLimit', [
|
||||
'newLimit' => $event->getNewLimit()
|
||||
]);
|
||||
}
|
||||
}
|
||||
60
lib/Listener/OnSystemUserChange.php
Normal file
60
lib/Listener/OnSystemUserChange.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener;
|
||||
|
||||
use Xibo\Event\SystemUserChangedEvent;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
|
||||
class OnSystemUserChange
|
||||
{
|
||||
/**
|
||||
* @var StorageServiceInterface
|
||||
*/
|
||||
private $storageService;
|
||||
|
||||
public function __construct(StorageServiceInterface $storageService)
|
||||
{
|
||||
$this->storageService = $storageService;
|
||||
}
|
||||
|
||||
public function __invoke(SystemUserChangedEvent $event)
|
||||
{
|
||||
// Reassign Module files
|
||||
$this->storageService->update('UPDATE `media` SET userId = :userId WHERE userId = :oldUserId AND type = \'module\'', [
|
||||
'userId' => $event->getNewSystemUser()->userId,
|
||||
'oldUserId' => $event->getOldSystemUser()->userId
|
||||
]);
|
||||
|
||||
// Reassign Display specific Display Groups
|
||||
$this->storageService->update('UPDATE `displaygroup` SET userId = :userId WHERE userId = :oldUserId AND isDisplaySpecific = 1', [
|
||||
'userId' => $event->getNewSystemUser()->userId,
|
||||
'oldUserId' => $event->getOldSystemUser()->userId
|
||||
]);
|
||||
|
||||
// Reassign system dayparts
|
||||
$this->storageService->update('UPDATE `daypart` SET userId = :userId WHERE userId = :oldUserId AND (isCustom = 1 OR isAlways = 1)', [
|
||||
'userId' => $event->getNewSystemUser()->userId,
|
||||
'oldUserId' => $event->getOldSystemUser()->userId
|
||||
]);
|
||||
}
|
||||
}
|
||||
94
lib/Listener/OnUserDelete/ActionListener.php
Normal file
94
lib/Listener/OnUserDelete/ActionListener.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnUserDelete;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Entity\User;
|
||||
use Xibo\Event\UserDeleteEvent;
|
||||
use Xibo\Factory\ActionFactory;
|
||||
use Xibo\Listener\ListenerLoggerTrait;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
|
||||
class ActionListener implements OnUserDeleteInterface
|
||||
{
|
||||
/**
|
||||
* @var ActionFactory
|
||||
*/
|
||||
private $actionFactory;
|
||||
/**
|
||||
* @var StorageServiceInterface
|
||||
*/
|
||||
private $store;
|
||||
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
public function __construct(StorageServiceInterface $store, ActionFactory $actionFactory)
|
||||
{
|
||||
$this->store = $store;
|
||||
$this->actionFactory = $actionFactory;
|
||||
}
|
||||
|
||||
public function __invoke(UserDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$user = $event->getUser();
|
||||
$function = $event->getFunction();
|
||||
$newUser = $event->getNewUser();
|
||||
$systemUser = $event->getSystemUser();
|
||||
|
||||
if ($function === 'delete') {
|
||||
$this->deleteChildren($user, $dispatcher, $systemUser);
|
||||
} elseif ($function === 'reassignAll') {
|
||||
$this->reassignAllTo($user, $newUser, $systemUser);
|
||||
} elseif ($function === 'countChildren') {
|
||||
$event->setReturnValue($event->getReturnValue() + $this->countChildren($user));
|
||||
}
|
||||
}
|
||||
|
||||
/* @inheritDoc */
|
||||
public function deleteChildren(User $user, EventDispatcherInterface $dispatcher, User $systemUser)
|
||||
{
|
||||
// Delete any Actions
|
||||
foreach ($this->actionFactory->getByOwnerId($user->userId) as $action) {
|
||||
$action->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/* @inheritDoc */
|
||||
public function reassignAllTo(User $user, User $newUser, User $systemUser)
|
||||
{
|
||||
// Reassign Actions
|
||||
$this->store->update('UPDATE `action` SET ownerId = :userId WHERE ownerId = :oldUserId', [
|
||||
'userId' => $newUser->userId,
|
||||
'oldUserId' => $user->userId
|
||||
]);
|
||||
}
|
||||
|
||||
/* @inheritDoc */
|
||||
public function countChildren(User $user)
|
||||
{
|
||||
$actions = $this->actionFactory->getByOwnerId($user->userId);
|
||||
$this->getLogger()->debug(sprintf('Counted Children Actions on User ID %d, there are %d', $user->userId, count($actions)));
|
||||
|
||||
return count($actions);
|
||||
}
|
||||
}
|
||||
91
lib/Listener/OnUserDelete/CommandListener.php
Normal file
91
lib/Listener/OnUserDelete/CommandListener.php
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnUserDelete;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Entity\User;
|
||||
use Xibo\Event\CommandDeleteEvent;
|
||||
use Xibo\Event\UserDeleteEvent;
|
||||
use Xibo\Factory\CommandFactory;
|
||||
use Xibo\Listener\ListenerLoggerTrait;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
|
||||
class CommandListener implements OnUserDeleteInterface
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/**
|
||||
* @var CommandFactory
|
||||
*/
|
||||
private $commandFactory;
|
||||
/**
|
||||
* @var StorageServiceInterface
|
||||
*/
|
||||
private $store;
|
||||
|
||||
public function __construct(StorageServiceInterface $store, CommandFactory $commandFactory)
|
||||
{
|
||||
$this->store = $store;
|
||||
$this->commandFactory = $commandFactory;
|
||||
}
|
||||
|
||||
public function __invoke(UserDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$user = $event->getUser();
|
||||
$function = $event->getFunction();
|
||||
$newUser = $event->getNewUser();
|
||||
$systemUser = $event->getSystemUser();
|
||||
|
||||
if ($function === 'delete') {
|
||||
$this->deleteChildren($user, $dispatcher, $systemUser);
|
||||
} elseif ($function === 'reassignAll') {
|
||||
$this->reassignAllTo($user, $newUser, $systemUser);
|
||||
} elseif ($function === 'countChildren') {
|
||||
$event->setReturnValue($event->getReturnValue() + $this->countChildren($user));
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteChildren(User $user, EventDispatcherInterface $dispatcher, User $systemUser)
|
||||
{
|
||||
foreach ($this->commandFactory->getByOwnerId($user->userId) as $command) {
|
||||
$dispatcher->dispatch(CommandDeleteEvent::$NAME, new CommandDeleteEvent($command));
|
||||
$command->delete();
|
||||
}
|
||||
}
|
||||
|
||||
public function reassignAllTo(User $user, User $newUser, User $systemUser)
|
||||
{
|
||||
$this->store->update('UPDATE `command` SET userId = :userId WHERE userId = :oldUserId', [
|
||||
'userId' => $newUser->userId,
|
||||
'oldUserId' => $user->userId
|
||||
]);
|
||||
}
|
||||
|
||||
public function countChildren(User $user)
|
||||
{
|
||||
$commands = $this->commandFactory->getByOwnerId($user->userId);
|
||||
$this->getLogger()->debug(sprintf('Counted Children Command on User ID %d, there are %d', $user->userId, count($commands)));
|
||||
|
||||
return count($commands);
|
||||
}
|
||||
}
|
||||
103
lib/Listener/OnUserDelete/DataSetListener.php
Normal file
103
lib/Listener/OnUserDelete/DataSetListener.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnUserDelete;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Entity\User;
|
||||
use Xibo\Event\UserDeleteEvent;
|
||||
use Xibo\Factory\DataSetFactory;
|
||||
use Xibo\Listener\ListenerLoggerTrait;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
|
||||
class DataSetListener implements OnUserDeleteInterface
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/**
|
||||
* @var StorageServiceInterface
|
||||
*/
|
||||
private $storageService;
|
||||
/**
|
||||
* @var DataSetFactory
|
||||
*/
|
||||
private $dataSetFactory;
|
||||
|
||||
public function __construct(StorageServiceInterface $storageService, DataSetFactory $dataSetFactory)
|
||||
{
|
||||
$this->storageService = $storageService;
|
||||
$this->dataSetFactory = $dataSetFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function __invoke(UserDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$user = $event->getUser();
|
||||
$function = $event->getFunction();
|
||||
$newUser = $event->getNewUser();
|
||||
$systemUser = $event->getSystemUser();
|
||||
|
||||
if ($function === 'delete') {
|
||||
$this->deleteChildren($user, $dispatcher, $systemUser);
|
||||
} elseif ($function === 'reassignAll') {
|
||||
$this->reassignAllTo($user, $newUser, $systemUser);
|
||||
} elseif ($function === 'countChildren') {
|
||||
$event->setReturnValue($event->getReturnValue() + $this->countChildren($user));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function deleteChildren(User $user, EventDispatcherInterface $dispatcher, User $systemUser)
|
||||
{
|
||||
foreach ($this->dataSetFactory->getByOwnerId($user->userId) as $dataSet) {
|
||||
$dataSet->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function reassignAllTo(User $user, User $newUser, User $systemUser)
|
||||
{
|
||||
// Reassign datasets
|
||||
$this->storageService->update('UPDATE `dataset` SET userId = :userId WHERE userId = :oldUserId', [
|
||||
'userId' => $newUser->userId,
|
||||
'oldUserId' => $user->userId
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function countChildren(User $user)
|
||||
{
|
||||
$dataSets = $this->dataSetFactory->getByOwnerId($user->userId);
|
||||
$count = count($dataSets);
|
||||
$this->getLogger()->debug(sprintf('Counted Children DataSet on User ID %d, there are %d', $user->userId, $count));
|
||||
|
||||
return $count;
|
||||
}
|
||||
}
|
||||
124
lib/Listener/OnUserDelete/DayPartListener.php
Normal file
124
lib/Listener/OnUserDelete/DayPartListener.php
Normal file
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2022 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnUserDelete;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Entity\User;
|
||||
use Xibo\Event\UserDeleteEvent;
|
||||
use Xibo\Factory\DayPartFactory;
|
||||
use Xibo\Factory\ScheduleFactory;
|
||||
use Xibo\Listener\ListenerLoggerTrait;
|
||||
use Xibo\Service\DisplayNotifyServiceInterface;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
|
||||
class DayPartListener implements OnUserDeleteInterface
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/**
|
||||
* @var StorageServiceInterface
|
||||
*/
|
||||
private $storageService;
|
||||
/**
|
||||
* @var DayPartFactory
|
||||
*/
|
||||
private $dayPartFactory;
|
||||
/**
|
||||
* @var ScheduleFactory
|
||||
*/
|
||||
private $scheduleFactory;
|
||||
|
||||
/** @var DisplayNotifyServiceInterface */
|
||||
private $displayNotifyService;
|
||||
|
||||
public function __construct(
|
||||
StorageServiceInterface $storageService,
|
||||
DayPartFactory $dayPartFactory,
|
||||
ScheduleFactory $scheduleFactory,
|
||||
DisplayNotifyServiceInterface $displayNotifyService
|
||||
) {
|
||||
$this->storageService = $storageService;
|
||||
$this->dayPartFactory = $dayPartFactory;
|
||||
$this->scheduleFactory = $scheduleFactory;
|
||||
$this->displayNotifyService = $displayNotifyService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function __invoke(UserDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$user = $event->getUser();
|
||||
$function = $event->getFunction();
|
||||
$newUser = $event->getNewUser();
|
||||
$systemUser = $event->getSystemUser();
|
||||
|
||||
if ($function === 'delete') {
|
||||
$this->deleteChildren($user, $dispatcher, $systemUser);
|
||||
} elseif ($function === 'reassignAll') {
|
||||
$this->reassignAllTo($user, $newUser, $systemUser);
|
||||
} elseif ($function === 'countChildren') {
|
||||
$event->setReturnValue($event->getReturnValue() + $this->countChildren($user));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function deleteChildren(User $user, EventDispatcherInterface $dispatcher, User $systemUser)
|
||||
{
|
||||
// system dayParts cannot be deleted, if this user owns them reassign to systemUser
|
||||
foreach ($this->dayPartFactory->getByOwnerId($user->userId) as $dayPart) {
|
||||
if ($dayPart->isSystemDayPart()) {
|
||||
$dayPart->setOwner($systemUser->userId);
|
||||
$dayPart->save(['recalculateHash' => false]);
|
||||
} else {
|
||||
$dayPart->setScheduleFactory($this->scheduleFactory, $this->displayNotifyService)->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function reassignAllTo(User $user, User $newUser, User $systemUser)
|
||||
{
|
||||
// Reassign Dayparts
|
||||
foreach ($this->dayPartFactory->getByOwnerId($user->userId) as $dayPart) {
|
||||
($dayPart->isSystemDayPart()) ? $dayPart->setOwner($systemUser->userId) : $dayPart->setOwner($newUser->getOwnerId());
|
||||
$dayPart->save(['recalculateHash' => false]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function countChildren(User $user)
|
||||
{
|
||||
$dayParts = $this->dayPartFactory->getByOwnerId($user->userId);
|
||||
$count = count($dayParts);
|
||||
$this->getLogger()->debug(sprintf('Counted Children DayParts on User ID %d, there are %d', $user->userId, $count));
|
||||
|
||||
return $count;
|
||||
}
|
||||
}
|
||||
95
lib/Listener/OnUserDelete/DisplayProfileListener.php
Normal file
95
lib/Listener/OnUserDelete/DisplayProfileListener.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnUserDelete;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Entity\User;
|
||||
use Xibo\Event\UserDeleteEvent;
|
||||
use Xibo\Factory\DisplayProfileFactory;
|
||||
use Xibo\Listener\ListenerLoggerTrait;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
|
||||
class DisplayProfileListener implements OnUserDeleteInterface
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/**
|
||||
* @var StorageServiceInterface
|
||||
*/
|
||||
private $store;
|
||||
/**
|
||||
* @var DisplayProfileFactory
|
||||
*/
|
||||
private $displayProfileFactory;
|
||||
|
||||
public function __construct(StorageServiceInterface $store, DisplayProfileFactory $displayProfileFactory)
|
||||
{
|
||||
$this->store = $store;
|
||||
$this->displayProfileFactory = $displayProfileFactory;
|
||||
}
|
||||
|
||||
public function __invoke(UserDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$user = $event->getUser();
|
||||
$function = $event->getFunction();
|
||||
$newUser = $event->getNewUser();
|
||||
$systemUser = $event->getSystemUser();
|
||||
|
||||
if ($function === 'delete') {
|
||||
$this->deleteChildren($user, $dispatcher, $systemUser);
|
||||
} elseif ($function === 'reassignAll') {
|
||||
$this->reassignAllTo($user, $newUser, $systemUser);
|
||||
} elseif ($function === 'countChildren') {
|
||||
$event->setReturnValue($event->getReturnValue() + $this->countChildren($user));
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteChildren(User $user, EventDispatcherInterface $dispatcher, User $systemUser)
|
||||
{
|
||||
// Delete any Display Profiles, reassign any default profiles to systemUser
|
||||
foreach ($this->displayProfileFactory->getByOwnerId($user->userId) as $displayProfile) {
|
||||
if ($displayProfile->isDefault === 1) {
|
||||
$displayProfile->setOwner($systemUser->userId);
|
||||
$displayProfile->save();
|
||||
} else {
|
||||
$displayProfile->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function reassignAllTo(User $user, User $newUser, User $systemUser)
|
||||
{
|
||||
$this->store->update('UPDATE `displayprofile` SET userId = :userId WHERE userId = :oldUserId', [
|
||||
'userId' => $newUser->userId,
|
||||
'oldUserId' => $user->userId
|
||||
]);
|
||||
}
|
||||
|
||||
public function countChildren(User $user)
|
||||
{
|
||||
$profiles = $this->displayProfileFactory->getByOwnerId($user->userId);
|
||||
$this->getLogger()->debug(sprintf('Counted Children Display Profiles on User ID %d, there are %d', $user->userId, count($profiles)));
|
||||
|
||||
return count($profiles);
|
||||
}
|
||||
}
|
||||
103
lib/Listener/OnUserDelete/MenuBoardListener.php
Normal file
103
lib/Listener/OnUserDelete/MenuBoardListener.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnUserDelete;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Entity\User;
|
||||
use Xibo\Event\UserDeleteEvent;
|
||||
use Xibo\Factory\MenuBoardFactory;
|
||||
use Xibo\Listener\ListenerLoggerTrait;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
|
||||
class MenuBoardListener implements OnUserDeleteInterface
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/**
|
||||
* @var StorageServiceInterface
|
||||
*/
|
||||
private $storageService;
|
||||
/**
|
||||
* @var MenuBoardFactory
|
||||
*/
|
||||
private $menuBoardFactory;
|
||||
|
||||
public function __construct(StorageServiceInterface $storageService, MenuBoardFactory $menuBoardFactory)
|
||||
{
|
||||
$this->storageService = $storageService;
|
||||
$this->menuBoardFactory = $menuBoardFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function __invoke(UserDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$user = $event->getUser();
|
||||
$function = $event->getFunction();
|
||||
$newUser = $event->getNewUser();
|
||||
$systemUser = $event->getSystemUser();
|
||||
|
||||
if ($function === 'delete') {
|
||||
$this->deleteChildren($user, $dispatcher, $systemUser);
|
||||
} elseif ($function === 'reassignAll') {
|
||||
$this->reassignAllTo($user, $newUser, $systemUser);
|
||||
} elseif ($function === 'countChildren') {
|
||||
$event->setReturnValue($event->getReturnValue() + $this->countChildren($user));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function deleteChildren(User $user, EventDispatcherInterface $dispatcher, User $systemUser)
|
||||
{
|
||||
foreach ($this->menuBoardFactory->getByOwnerId($user->userId) as $menuBoard) {
|
||||
$menuBoard->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function reassignAllTo(User $user, User $newUser, User $systemUser)
|
||||
{
|
||||
// Reassign Menu Boards
|
||||
$this->storageService->update('UPDATE `menu_board` SET userId = :userId WHERE userId = :oldUserId', [
|
||||
'userId' => $newUser->userId,
|
||||
'oldUserId' => $user->userId
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function countChildren(User $user)
|
||||
{
|
||||
$menuBoards = $this->menuBoardFactory->getByOwnerId($user->userId);
|
||||
$count = count($menuBoards);
|
||||
$this->getLogger()->debug(sprintf('Counted Children Menu Board on User ID %d, there are %d', $user->userId, $count));
|
||||
|
||||
return $count;
|
||||
}
|
||||
}
|
||||
85
lib/Listener/OnUserDelete/NotificationListener.php
Normal file
85
lib/Listener/OnUserDelete/NotificationListener.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnUserDelete;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Entity\User;
|
||||
use Xibo\Event\UserDeleteEvent;
|
||||
use Xibo\Factory\NotificationFactory;
|
||||
use Xibo\Listener\ListenerLoggerTrait;
|
||||
|
||||
class NotificationListener implements OnUserDeleteInterface
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/**
|
||||
* @var NotificationFactory
|
||||
*/
|
||||
private $notificationFactory;
|
||||
|
||||
public function __construct(NotificationFactory $notificationFactory)
|
||||
{
|
||||
$this->notificationFactory = $notificationFactory;
|
||||
}
|
||||
|
||||
public function __invoke(UserDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$user = $event->getUser();
|
||||
$function = $event->getFunction();
|
||||
$newUser = $event->getNewUser();
|
||||
$systemUser = $event->getSystemUser();
|
||||
|
||||
if ($function === 'delete') {
|
||||
$this->deleteChildren($user, $dispatcher, $systemUser);
|
||||
} elseif ($function === 'reassignAll') {
|
||||
$this->reassignAllTo($user, $newUser, $systemUser);
|
||||
} elseif ($function === 'countChildren') {
|
||||
$event->setReturnValue($event->getReturnValue() + $this->countChildren($user));
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteChildren(User $user, EventDispatcherInterface $dispatcher, User $systemUser)
|
||||
{
|
||||
// Delete any Notifications
|
||||
foreach ($this->notificationFactory->getByOwnerId($user->userId) as $notification) {
|
||||
$notification->delete();
|
||||
}
|
||||
}
|
||||
|
||||
public function reassignAllTo(User $user, User $newUser, User $systemUser)
|
||||
{
|
||||
foreach ($this->notificationFactory->getByOwnerId($user->userId) as $notification) {
|
||||
$notification->load();
|
||||
$notification->userId = $newUser->userId;
|
||||
$notification->save();
|
||||
}
|
||||
}
|
||||
|
||||
public function countChildren(User $user)
|
||||
{
|
||||
$notifications = $this->notificationFactory->getByOwnerId($user->userId);
|
||||
$this->getLogger()->debug(sprintf('Counted Children Notifications on User ID %d, there are %d', $user->userId, count($notifications)));
|
||||
|
||||
return count($notifications);
|
||||
}
|
||||
}
|
||||
63
lib/Listener/OnUserDelete/OnUserDelete.php
Normal file
63
lib/Listener/OnUserDelete/OnUserDelete.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnUserDelete;
|
||||
|
||||
use Xibo\Event\UserDeleteEvent;
|
||||
use Xibo\Listener\ListenerLoggerTrait;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
|
||||
class OnUserDelete
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/** @var StorageServiceInterface */
|
||||
private $store;
|
||||
|
||||
public function __construct(StorageServiceInterface $store)
|
||||
{
|
||||
$this->store = $store;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function __invoke(UserDeleteEvent $event)
|
||||
{
|
||||
$user = $event->getUser();
|
||||
$function = $event->getFunction();
|
||||
|
||||
if ($function === 'delete' || $function === 'reassignAll') {
|
||||
$this->deleteChildren($user);
|
||||
}
|
||||
}
|
||||
|
||||
// when we delete a User with or without reassign the session and oauth clients should always be removed
|
||||
// other objects that can be owned by the user are deleted in their respective listeners.
|
||||
private function deleteChildren($user)
|
||||
{
|
||||
// Delete oAuth clients
|
||||
$this->store->update('DELETE FROM `oauth_clients` WHERE userId = :userId', ['userId' => $user->userId]);
|
||||
|
||||
$this->store->update('DELETE FROM `session` WHERE userId = :userId', ['userId' => $user->userId]);
|
||||
}
|
||||
}
|
||||
63
lib/Listener/OnUserDelete/OnUserDeleteInterface.php
Normal file
63
lib/Listener/OnUserDelete/OnUserDeleteInterface.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnUserDelete;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Entity\User;
|
||||
use Xibo\Event\UserDeleteEvent;
|
||||
|
||||
interface OnUserDeleteInterface
|
||||
{
|
||||
/**
|
||||
* Listen to the UserDeleteEvent
|
||||
*
|
||||
* @param UserDeleteEvent $event
|
||||
* @return mixed
|
||||
*/
|
||||
public function __invoke(UserDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher);
|
||||
|
||||
/**
|
||||
* Delete Objects owned by the User we want to delete
|
||||
*
|
||||
* @param User $user
|
||||
* @return mixed
|
||||
*/
|
||||
public function deleteChildren(User $user, EventDispatcherInterface $dispatcher, User $systemUser);
|
||||
|
||||
/**
|
||||
* Reassign objects to a new User
|
||||
*
|
||||
* @param User $user
|
||||
* @param User $newUser
|
||||
* @return mixed
|
||||
*/
|
||||
public function reassignAllTo(User $user, User $newUser, User $systemUser);
|
||||
|
||||
/**
|
||||
* Count Children, return count of objects owned by the User we want to delete
|
||||
*
|
||||
* @param User $user
|
||||
* @return mixed
|
||||
*/
|
||||
public function countChildren(User $user);
|
||||
}
|
||||
94
lib/Listener/OnUserDelete/RegionListener.php
Normal file
94
lib/Listener/OnUserDelete/RegionListener.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnUserDelete;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Entity\User;
|
||||
use Xibo\Event\UserDeleteEvent;
|
||||
use Xibo\Factory\RegionFactory;
|
||||
use Xibo\Listener\ListenerLoggerTrait;
|
||||
|
||||
class RegionListener implements OnUserDeleteInterface
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/**
|
||||
* @var RegionFactory
|
||||
*/
|
||||
private $regionFactory;
|
||||
|
||||
public function __construct(RegionFactory $regionFactory)
|
||||
{
|
||||
$this->regionFactory = $regionFactory;
|
||||
}
|
||||
|
||||
public function __invoke(UserDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$user = $event->getUser();
|
||||
$function = $event->getFunction();
|
||||
$newUser = $event->getNewUser();
|
||||
$systemUser = $event->getSystemUser();
|
||||
|
||||
if ($function === 'delete') {
|
||||
$this->deleteChildren($user, $dispatcher, $systemUser);
|
||||
} elseif ($function === 'reassignAll') {
|
||||
$this->reassignAllTo($user, $newUser, $systemUser);
|
||||
} elseif ($function === 'countChildren') {
|
||||
$event->setReturnValue($event->getReturnValue() + $this->countChildren($user));
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteChildren(User $user, EventDispatcherInterface $dispatcher, User $systemUser)
|
||||
{
|
||||
foreach ($this->regionFactory->getbyOwnerId($user->userId) as $region) {
|
||||
$region->delete();
|
||||
}
|
||||
}
|
||||
|
||||
public function reassignAllTo(User $user, User $newUser, User $systemUser)
|
||||
{
|
||||
$regions = $this->regionFactory->getbyOwnerId($user->userId);
|
||||
|
||||
$this->getLogger()->debug(sprintf('Counted Children Regions on User ID %d, there are %d', $user->userId, count($regions)));
|
||||
|
||||
foreach ($regions as $region) {
|
||||
$region->setOwner($newUser->userId, true);
|
||||
$region->save([
|
||||
'validate' => false,
|
||||
'audit' => false,
|
||||
'notify' => false
|
||||
]);
|
||||
}
|
||||
|
||||
$this->getLogger()->debug(sprintf('Finished reassign Regions, there are %d children', $this->countChildren($user)));
|
||||
}
|
||||
|
||||
public function countChildren(User $user)
|
||||
{
|
||||
$regions = $this->regionFactory->getbyOwnerId($user->userId);
|
||||
|
||||
$this->getLogger()->debug(sprintf('Counted Children Regions on User ID %d, there are %d', $user->userId, count($regions)));
|
||||
|
||||
return count($regions);
|
||||
}
|
||||
}
|
||||
89
lib/Listener/OnUserDelete/ReportScheduleListener.php
Normal file
89
lib/Listener/OnUserDelete/ReportScheduleListener.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnUserDelete;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Entity\User;
|
||||
use Xibo\Event\UserDeleteEvent;
|
||||
use Xibo\Factory\ReportScheduleFactory;
|
||||
use Xibo\Listener\ListenerLoggerTrait;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
|
||||
class ReportScheduleListener implements OnUserDeleteInterface
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/**
|
||||
* @var StorageServiceInterface
|
||||
*/
|
||||
private $store;
|
||||
/**
|
||||
* @var ReportScheduleFactory
|
||||
*/
|
||||
private $reportScheduleFactory;
|
||||
|
||||
public function __construct(StorageServiceInterface $store, ReportScheduleFactory $reportScheduleFactory)
|
||||
{
|
||||
$this->store = $store;
|
||||
$this->reportScheduleFactory = $reportScheduleFactory;
|
||||
}
|
||||
|
||||
public function __invoke(UserDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$user = $event->getUser();
|
||||
$function = $event->getFunction();
|
||||
$newUser = $event->getNewUser();
|
||||
$systemUser = $event->getSystemUser();
|
||||
|
||||
if ($function === 'delete') {
|
||||
$this->deleteChildren($user, $dispatcher, $systemUser);
|
||||
} elseif ($function === 'reassignAll') {
|
||||
$this->reassignAllTo($user, $newUser, $systemUser);
|
||||
} elseif ($function === 'countChildren') {
|
||||
$event->setReturnValue($event->getReturnValue() + $this->countChildren($user));
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteChildren(User $user, EventDispatcherInterface $dispatcher, User $systemUser)
|
||||
{
|
||||
foreach ($this->reportScheduleFactory->getByOwnerId($user->userId) as $reportSchedule) {
|
||||
$reportSchedule->delete();
|
||||
}
|
||||
}
|
||||
|
||||
public function reassignAllTo(User $user, User $newUser, User $systemUser)
|
||||
{
|
||||
$this->store->update('UPDATE `reportschedule` SET userId = :userId WHERE userId = :oldUserId', [
|
||||
'userId' => $newUser->userId,
|
||||
'oldUserId' => $user->userId
|
||||
]);
|
||||
}
|
||||
|
||||
public function countChildren(User $user)
|
||||
{
|
||||
$reportSchedules = $this->reportScheduleFactory->getByOwnerId($user->userId);
|
||||
$this->getLogger()->debug(sprintf('Counted Children Report Schedules on User ID %d, there are %d', $user->userId, count($reportSchedules)));
|
||||
|
||||
return count($reportSchedules);
|
||||
}
|
||||
}
|
||||
94
lib/Listener/OnUserDelete/ResolutionListener.php
Normal file
94
lib/Listener/OnUserDelete/ResolutionListener.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnUserDelete;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Entity\User;
|
||||
use Xibo\Event\UserDeleteEvent;
|
||||
use Xibo\Factory\ResolutionFactory;
|
||||
use Xibo\Listener\ListenerLoggerTrait;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
|
||||
class ResolutionListener implements OnUserDeleteInterface
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/**
|
||||
* @var StorageServiceInterface
|
||||
*/
|
||||
private $store;
|
||||
/**
|
||||
* @var ResolutionFactory
|
||||
*/
|
||||
private $resolutionFactory;
|
||||
|
||||
public function __construct(StorageServiceInterface $store, ResolutionFactory $resolutionFactory)
|
||||
{
|
||||
$this->store = $store;
|
||||
$this->resolutionFactory = $resolutionFactory;
|
||||
}
|
||||
|
||||
public function __invoke(UserDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$user = $event->getUser();
|
||||
$function = $event->getFunction();
|
||||
$newUser = $event->getNewUser();
|
||||
$systemUser = $event->getSystemUser();
|
||||
|
||||
if ($function === 'delete') {
|
||||
$this->deleteChildren($user, $dispatcher, $systemUser);
|
||||
} elseif ($function === 'reassignAll') {
|
||||
$this->reassignAllTo($user, $newUser, $systemUser);
|
||||
} elseif ($function === 'countChildren') {
|
||||
$event->setReturnValue($event->getReturnValue() + $this->countChildren($user));
|
||||
}
|
||||
}
|
||||
|
||||
/* @inheritDoc */
|
||||
public function deleteChildren(User $user, EventDispatcherInterface $dispatcher, User $systemUser)
|
||||
{
|
||||
// Delete any Resolutions
|
||||
foreach ($this->resolutionFactory->getByOwnerId($user->userId) as $resolution) {
|
||||
$resolution->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/* @inheritDoc */
|
||||
public function reassignAllTo(User $user, User $newUser, User $systemUser)
|
||||
{
|
||||
// Reassign Resolutions
|
||||
$this->store->update('UPDATE `resolution` SET userId = :userId WHERE userId = :oldUserId', [
|
||||
'userId' => $newUser->userId,
|
||||
'oldUserId' => $user->userId
|
||||
]);
|
||||
}
|
||||
|
||||
/* @inheritDoc */
|
||||
public function countChildren(User $user)
|
||||
{
|
||||
$resolutions = $this->resolutionFactory->getByOwnerId($user->userId);
|
||||
$this->getLogger()->debug(sprintf('Counted Children Resolution on User ID %d, there are %d', $user->userId, count($resolutions)));
|
||||
|
||||
return count($resolutions);
|
||||
}
|
||||
}
|
||||
89
lib/Listener/OnUserDelete/SavedReportListener.php
Normal file
89
lib/Listener/OnUserDelete/SavedReportListener.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnUserDelete;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Entity\User;
|
||||
use Xibo\Event\UserDeleteEvent;
|
||||
use Xibo\Factory\SavedReportFactory;
|
||||
use Xibo\Listener\ListenerLoggerTrait;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
|
||||
class SavedReportListener implements OnUserDeleteInterface
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/**
|
||||
* @var StorageServiceInterface
|
||||
*/
|
||||
private $store;
|
||||
/**
|
||||
* @var SavedReportFactory
|
||||
*/
|
||||
private $savedReportFactory;
|
||||
|
||||
public function __construct(StorageServiceInterface $store, SavedReportFactory $savedReportFactory)
|
||||
{
|
||||
$this->store = $store;
|
||||
$this->savedReportFactory = $savedReportFactory;
|
||||
}
|
||||
|
||||
public function __invoke(UserDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$user = $event->getUser();
|
||||
$function = $event->getFunction();
|
||||
$newUser = $event->getNewUser();
|
||||
$systemUser = $event->getSystemUser();
|
||||
|
||||
if ($function === 'delete') {
|
||||
$this->deleteChildren($user, $dispatcher, $systemUser);
|
||||
} elseif ($function === 'reassignAll') {
|
||||
$this->reassignAllTo($user, $newUser, $systemUser);
|
||||
} elseif ($function === 'countChildren') {
|
||||
$event->setReturnValue($event->getReturnValue() + $this->countChildren($user));
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteChildren(User $user, EventDispatcherInterface $dispatcher, User $systemUser)
|
||||
{
|
||||
foreach ($this->savedReportFactory->getByOwnerId($user->userId) as $savedReport) {
|
||||
$savedReport->delete();
|
||||
}
|
||||
}
|
||||
|
||||
public function reassignAllTo(User $user, User $newUser, User $systemUser)
|
||||
{
|
||||
$this->store->update('UPDATE `saved_report` SET userId = :userId WHERE userId = :oldUserId', [
|
||||
'userId' => $newUser->userId,
|
||||
'oldUserId' => $user->userId
|
||||
]);
|
||||
}
|
||||
|
||||
public function countChildren(User $user)
|
||||
{
|
||||
$savedReports = $this->savedReportFactory->getByOwnerId($user->userId);
|
||||
$this->getLogger()->debug(sprintf('Counted Children Saved Report on User ID %d, there are %d', $user->userId, count($savedReports)));
|
||||
|
||||
return count($savedReports);
|
||||
}
|
||||
}
|
||||
102
lib/Listener/OnUserDelete/ScheduleListener.php
Normal file
102
lib/Listener/OnUserDelete/ScheduleListener.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnUserDelete;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Entity\Schedule;
|
||||
use Xibo\Entity\User;
|
||||
use Xibo\Event\UserDeleteEvent;
|
||||
use Xibo\Factory\ScheduleFactory;
|
||||
use Xibo\Listener\ListenerLoggerTrait;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
|
||||
class ScheduleListener implements OnUserDeleteInterface
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/** @var StorageServiceInterface */
|
||||
private $storageService;
|
||||
|
||||
/** @var ScheduleFactory */
|
||||
private $scheduleFactory;
|
||||
|
||||
public function __construct(StorageServiceInterface $storageService, ScheduleFactory $scheduleFactory)
|
||||
{
|
||||
$this->storageService = $storageService;
|
||||
$this->scheduleFactory = $scheduleFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function __invoke(UserDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$user = $event->getUser();
|
||||
$function = $event->getFunction();
|
||||
$newUser = $event->getNewUser();
|
||||
$systemUser = $event->getSystemUser();
|
||||
|
||||
if ($function === 'delete') {
|
||||
$this->deleteChildren($user, $dispatcher, $systemUser);
|
||||
} elseif ($function === 'reassignAll') {
|
||||
$this->reassignAllTo($user, $newUser, $systemUser);
|
||||
} elseif ($function === 'countChildren') {
|
||||
$event->setReturnValue($event->getReturnValue() + $this->countChildren($user));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function deleteChildren($user, EventDispatcherInterface $dispatcher, User $systemUser)
|
||||
{
|
||||
// Delete any scheduled events
|
||||
foreach ($this->scheduleFactory->getByOwnerId($user->userId) as $event) {
|
||||
/* @var Schedule $event */
|
||||
$event->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function reassignAllTo(User $user, User $newUser, User $systemUser)
|
||||
{
|
||||
// Reassign events
|
||||
$this->storageService->update('UPDATE `schedule` SET userId = :userId WHERE userId = :oldUserId', [
|
||||
'userId' => $newUser->userId,
|
||||
'oldUserId' => $user->userId
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function countChildren(User $user)
|
||||
{
|
||||
$events = $this->scheduleFactory->getByOwnerId($user->userId);
|
||||
$count = count($events);
|
||||
$this->getLogger()->debug(sprintf('Counted Children Event on User ID %d, there are %d', $user->userId, $count));
|
||||
|
||||
return $count;
|
||||
}
|
||||
}
|
||||
93
lib/Listener/OnUserDelete/WidgetListener.php
Normal file
93
lib/Listener/OnUserDelete/WidgetListener.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2021 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener\OnUserDelete;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Entity\User;
|
||||
use Xibo\Event\UserDeleteEvent;
|
||||
use Xibo\Factory\WidgetFactory;
|
||||
use Xibo\Listener\ListenerLoggerTrait;
|
||||
|
||||
class WidgetListener implements OnUserDeleteInterface
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/**
|
||||
* @var WidgetFactory
|
||||
*/
|
||||
private $widgetFactory;
|
||||
|
||||
public function __construct(WidgetFactory $widgetFactory)
|
||||
{
|
||||
$this->widgetFactory = $widgetFactory;
|
||||
}
|
||||
|
||||
public function __invoke(UserDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$user = $event->getUser();
|
||||
$function = $event->getFunction();
|
||||
$newUser = $event->getNewUser();
|
||||
$systemUser = $event->getSystemUser();
|
||||
|
||||
if ($function === 'delete') {
|
||||
$this->deleteChildren($user, $dispatcher, $systemUser);
|
||||
} elseif ($function === 'reassignAll') {
|
||||
$this->reassignAllTo($user, $newUser, $systemUser);
|
||||
} elseif ($function === 'countChildren') {
|
||||
$event->setReturnValue($event->getReturnValue() + $this->countChildren($user));
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteChildren(User $user, EventDispatcherInterface $dispatcher, User $systemUser)
|
||||
{
|
||||
foreach ($this->widgetFactory->getByOwnerId($user->userId) as $widget) {
|
||||
$widget->delete();
|
||||
}
|
||||
}
|
||||
|
||||
public function reassignAllTo(User $user, User $newUser, User $systemUser)
|
||||
{
|
||||
foreach ($this->widgetFactory->getByOwnerId($user->userId) as $widget) {
|
||||
$widget->setOwner($newUser->userId);
|
||||
$widget->save([
|
||||
'saveWidgetOptions' => false,
|
||||
'saveWidgetAudio' => false,
|
||||
'saveWidgetMedia' => false,
|
||||
'notify' => false,
|
||||
'notifyPlaylists' => false,
|
||||
'notifyDisplays' => false,
|
||||
'audit' => true,
|
||||
'alwaysUpdate' => true
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function countChildren(User $user)
|
||||
{
|
||||
$widgets = $this->widgetFactory->getByOwnerId($user->userId);
|
||||
|
||||
$this->getLogger()->debug(sprintf('Counted Children Widgets on User ID %d, there are %d', $user->userId, count($widgets)));
|
||||
|
||||
return count($widgets);
|
||||
}
|
||||
}
|
||||
159
lib/Listener/PlaylistListener.php
Normal file
159
lib/Listener/PlaylistListener.php
Normal file
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2022 Xibo Signage Ltd
|
||||
*
|
||||
* Xibo - Digital Signage - http://www.xibo.org.uk
|
||||
*
|
||||
* 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\Listener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Event\FolderMovingEvent;
|
||||
use Xibo\Event\ParsePermissionEntityEvent;
|
||||
use Xibo\Event\TagDeleteEvent;
|
||||
use Xibo\Event\TriggerTaskEvent;
|
||||
use Xibo\Event\UserDeleteEvent;
|
||||
use Xibo\Factory\PlaylistFactory;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
|
||||
/**
|
||||
* Playlist events
|
||||
*/
|
||||
class PlaylistListener
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/**
|
||||
* @var PlaylistFactory
|
||||
*/
|
||||
private $playlistFactory;
|
||||
/**
|
||||
* @var StorageServiceInterface
|
||||
*/
|
||||
private $storageService;
|
||||
|
||||
/**
|
||||
* @param PlaylistFactory $playlistFactory
|
||||
* @param StorageServiceInterface $storageService
|
||||
*/
|
||||
public function __construct(
|
||||
PlaylistFactory $playlistFactory,
|
||||
StorageServiceInterface $storageService
|
||||
) {
|
||||
$this->playlistFactory = $playlistFactory;
|
||||
$this->storageService = $storageService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return $this
|
||||
*/
|
||||
public function registerWithDispatcher(EventDispatcherInterface $dispatcher) : PlaylistListener
|
||||
{
|
||||
$dispatcher->addListener(UserDeleteEvent::$NAME, [$this, 'onUserDelete']);
|
||||
$dispatcher->addListener(ParsePermissionEntityEvent::$NAME . 'playlist', [$this, 'onParsePermissions']);
|
||||
$dispatcher->addListener(FolderMovingEvent::$NAME, [$this, 'onFolderMoving']);
|
||||
$dispatcher->addListener(TagDeleteEvent::$NAME, [$this, 'onTagDelete']);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserDeleteEvent $event
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\DuplicateEntityException
|
||||
* @throws \Xibo\Support\Exception\InvalidArgumentException
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function onUserDelete(UserDeleteEvent $event)
|
||||
{
|
||||
$user = $event->getUser();
|
||||
$function = $event->getFunction();
|
||||
$newUser = $event->getNewUser();
|
||||
|
||||
if ($function === 'delete') {
|
||||
// Delete Playlists owned by this user
|
||||
foreach ($this->playlistFactory->getByOwnerId($user->userId) as $playlist) {
|
||||
$playlist->delete();
|
||||
}
|
||||
} else if ($function === 'reassignAll') {
|
||||
// Reassign playlists and widgets
|
||||
foreach ($this->playlistFactory->getByOwnerId($user->userId) as $playlist) {
|
||||
$playlist->setOwner($newUser->userId);
|
||||
$playlist->save();
|
||||
}
|
||||
} else if ($function === 'countChildren') {
|
||||
$playlists = $this->playlistFactory->getByOwnerId($user->userId);
|
||||
|
||||
$count = count($playlists);
|
||||
$this->getLogger()->debug(
|
||||
sprintf(
|
||||
'Counted Children Playlists on User ID %d, there are %d',
|
||||
$user->userId,
|
||||
$count
|
||||
)
|
||||
);
|
||||
|
||||
$event->setReturnValue($event->getReturnValue() + $count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ParsePermissionEntityEvent $event
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function onParsePermissions(ParsePermissionEntityEvent $event)
|
||||
{
|
||||
$this->getLogger()->debug('onParsePermissions');
|
||||
$event->setObject($this->playlistFactory->getById($event->getObjectId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FolderMovingEvent $event
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function onFolderMoving(FolderMovingEvent $event)
|
||||
{
|
||||
$folder = $event->getFolder();
|
||||
$newFolder = $event->getNewFolder();
|
||||
|
||||
foreach ($this->playlistFactory->getbyFolderId($folder->getId()) as $playlist) {
|
||||
$playlist->folderId = $newFolder->getId();
|
||||
$playlist->permissionsFolderId = $newFolder->getPermissionFolderIdOrThis();
|
||||
$playlist->updateFolders('playlist');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TagDeleteEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return void
|
||||
*/
|
||||
public function onTagDelete(TagDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->storageService->update(
|
||||
'DELETE FROM `lktagplaylist` WHERE `lktagplaylist`.tagId = :tagId',
|
||||
['tagId' => $event->getTagId()]
|
||||
);
|
||||
|
||||
$dispatcher->dispatch(new TriggerTaskEvent('\Xibo\XTR\DynamicPlaylistSyncTask'), TriggerTaskEvent::$NAME);
|
||||
}
|
||||
}
|
||||
133
lib/Listener/SyncGroupListener.php
Normal file
133
lib/Listener/SyncGroupListener.php
Normal file
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2023 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\Listener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Event\FolderMovingEvent;
|
||||
use Xibo\Event\ParsePermissionEntityEvent;
|
||||
use Xibo\Event\UserDeleteEvent;
|
||||
use Xibo\Factory\SyncGroupFactory;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
|
||||
/**
|
||||
* SyncGroup events
|
||||
*/
|
||||
class SyncGroupListener
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
private SyncGroupFactory $syncGroupFactory;
|
||||
private StorageServiceInterface $storageService;
|
||||
|
||||
/**
|
||||
* @param SyncGroupFactory $syncGroupFactory
|
||||
* @param StorageServiceInterface $storageService
|
||||
*/
|
||||
public function __construct(
|
||||
SyncGroupFactory $syncGroupFactory,
|
||||
StorageServiceInterface $storageService
|
||||
) {
|
||||
$this->syncGroupFactory = $syncGroupFactory;
|
||||
$this->storageService = $storageService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return $this
|
||||
*/
|
||||
public function registerWithDispatcher(EventDispatcherInterface $dispatcher): SyncGroupListener
|
||||
{
|
||||
$dispatcher->addListener(UserDeleteEvent::$NAME, [$this, 'onUserDelete']);
|
||||
$dispatcher->addListener(ParsePermissionEntityEvent::$NAME . 'syncGroup', [$this, 'onParsePermissions']);
|
||||
$dispatcher->addListener(FolderMovingEvent::$NAME, [$this, 'onFolderMoving']);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserDeleteEvent $event
|
||||
* @param $eventName
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\GeneralException
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function onUserDelete(UserDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$user = $event->getUser();
|
||||
$function = $event->getFunction();
|
||||
$newUser = $event->getNewUser();
|
||||
|
||||
if ($function === 'delete') {
|
||||
// we do not want to delete Display specific Display Groups, reassign to systemUser instead.
|
||||
foreach ($this->syncGroupFactory->getByOwnerId($user->userId) as $syncGroup) {
|
||||
$syncGroup->delete();
|
||||
}
|
||||
} else if ($function === 'reassignAll') {
|
||||
foreach ($this->syncGroupFactory->getByOwnerId($user->userId) as $syncGroup) {
|
||||
$syncGroup->setOwner($newUser->getOwnerId());
|
||||
$syncGroup->save();
|
||||
}
|
||||
} else if ($function === 'countChildren') {
|
||||
$syncGroups = $this->syncGroupFactory->getByOwnerId($user->userId);
|
||||
|
||||
$count = count($syncGroups);
|
||||
$this->getLogger()->debug(
|
||||
sprintf(
|
||||
'Counted Children Sync Groups on User ID %d, there are %d',
|
||||
$user->userId,
|
||||
$count
|
||||
)
|
||||
);
|
||||
|
||||
$event->setReturnValue($event->getReturnValue() + $count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ParsePermissionEntityEvent $event
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function onParsePermissions(ParsePermissionEntityEvent $event)
|
||||
{
|
||||
$this->getLogger()->debug('onParsePermissions');
|
||||
$event->setObject($this->syncGroupFactory->getById($event->getObjectId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FolderMovingEvent $event
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function onFolderMoving(FolderMovingEvent $event)
|
||||
{
|
||||
$folder = $event->getFolder();
|
||||
$newFolder = $event->getNewFolder();
|
||||
|
||||
foreach ($this->syncGroupFactory->getByFolderId($folder->getId()) as $syncGroup) {
|
||||
$syncGroup->folderId = $newFolder->getId();
|
||||
$syncGroup->permissionsFolderId = $newFolder->getPermissionFolderIdOrThis();
|
||||
$syncGroup->updateFolders('syncgroup');
|
||||
}
|
||||
}
|
||||
}
|
||||
74
lib/Listener/TaskListener.php
Normal file
74
lib/Listener/TaskListener.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2025 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\Listener;
|
||||
|
||||
use Stash\Interfaces\PoolInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Event\TriggerTaskEvent;
|
||||
use Xibo\Factory\TaskFactory;
|
||||
use Xibo\Service\ConfigServiceInterface;
|
||||
|
||||
/**
|
||||
* A listener for events related to tasks
|
||||
*/
|
||||
class TaskListener
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
public function __construct(
|
||||
private readonly TaskFactory $taskFactory,
|
||||
private readonly ConfigServiceInterface $configService,
|
||||
private readonly PoolInterface $pool
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return $this
|
||||
*/
|
||||
public function registerWithDispatcher(EventDispatcherInterface $dispatcher) : TaskListener
|
||||
{
|
||||
$dispatcher->addListener(TriggerTaskEvent::$NAME, [$this, 'onTriggerTask']);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TriggerTaskEvent $event
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\InvalidArgumentException
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function onTriggerTask(TriggerTaskEvent $event): void
|
||||
{
|
||||
if (!empty($event->getKey())) {
|
||||
// Drop this setting from the cache
|
||||
$this->pool->deleteItem($event->getKey());
|
||||
}
|
||||
|
||||
// Mark the task to run now
|
||||
$task = $this->taskFactory->getByClass($event->getClassName());
|
||||
$task->runNow = 1;
|
||||
$task->save(['validate' => false]);
|
||||
}
|
||||
}
|
||||
768
lib/Listener/WidgetListener.php
Normal file
768
lib/Listener/WidgetListener.php
Normal file
@@ -0,0 +1,768 @@
|
||||
<?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\Listener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Xibo\Entity\Widget;
|
||||
use Xibo\Event\RegionAddedEvent;
|
||||
use Xibo\Event\SubPlaylistDurationEvent;
|
||||
use Xibo\Event\SubPlaylistItemsEvent;
|
||||
use Xibo\Event\SubPlaylistValidityEvent;
|
||||
use Xibo\Event\SubPlaylistWidgetsEvent;
|
||||
use Xibo\Event\WidgetDeleteEvent;
|
||||
use Xibo\Event\WidgetEditEvent;
|
||||
use Xibo\Factory\ModuleFactory;
|
||||
use Xibo\Factory\PlaylistFactory;
|
||||
use Xibo\Factory\WidgetFactory;
|
||||
use Xibo\Service\ConfigServiceInterface;
|
||||
use Xibo\Storage\StorageServiceInterface;
|
||||
use Xibo\Support\Exception\GeneralException;
|
||||
use Xibo\Support\Exception\InvalidArgumentException;
|
||||
use Xibo\Support\Exception\NotFoundException;
|
||||
use Xibo\Widget\SubPlaylistItem;
|
||||
|
||||
/**
|
||||
* Widget Listener.
|
||||
*
|
||||
* Sub Playlist Events
|
||||
* -------------------
|
||||
* Sub Playlists are a special case in that they resolve to multiple widgets
|
||||
* This is handled by the standard widget edit/delete events and a special event to calculate the duration
|
||||
* These events are processed by a SubPlaylistListener included with core.
|
||||
*
|
||||
* Region Events
|
||||
* -------------
|
||||
* We listen for a region being added and if its a canvas we add a "global" widget to it.
|
||||
*/
|
||||
class WidgetListener
|
||||
{
|
||||
use ListenerLoggerTrait;
|
||||
|
||||
/** @var PlaylistFactory */
|
||||
private $playlistFactory;
|
||||
|
||||
/** @var \Xibo\Factory\ModuleFactory */
|
||||
private $moduleFactory;
|
||||
|
||||
/** @var WidgetFactory */
|
||||
private $widgetFactory;
|
||||
|
||||
/** @var StorageServiceInterface */
|
||||
private $storageService;
|
||||
|
||||
/** @var \Xibo\Service\ConfigServiceInterface */
|
||||
private $configService;
|
||||
|
||||
/**
|
||||
* @param PlaylistFactory $playlistFactory
|
||||
* @param \Xibo\Factory\ModuleFactory $moduleFactory
|
||||
* @param StorageServiceInterface $storageService
|
||||
* @param \Xibo\Service\ConfigServiceInterface $configService
|
||||
*/
|
||||
public function __construct(
|
||||
PlaylistFactory $playlistFactory,
|
||||
ModuleFactory $moduleFactory,
|
||||
WidgetFactory $widgetFactory,
|
||||
StorageServiceInterface $storageService,
|
||||
ConfigServiceInterface $configService
|
||||
) {
|
||||
$this->playlistFactory = $playlistFactory;
|
||||
$this->moduleFactory = $moduleFactory;
|
||||
$this->widgetFactory = $widgetFactory;
|
||||
$this->storageService = $storageService;
|
||||
$this->configService = $configService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @return $this
|
||||
*/
|
||||
public function registerWithDispatcher(EventDispatcherInterface $dispatcher) : WidgetListener
|
||||
{
|
||||
$dispatcher->addListener(WidgetEditEvent::$NAME, [$this, 'onWidgetEdit']);
|
||||
$dispatcher->addListener(WidgetDeleteEvent::$NAME, [$this, 'onWidgetDelete']);
|
||||
$dispatcher->addListener(SubPlaylistDurationEvent::$NAME, [$this, 'onDuration']);
|
||||
$dispatcher->addListener(SubPlaylistWidgetsEvent::$NAME, [$this, 'onWidgets']);
|
||||
$dispatcher->addListener(SubPlaylistItemsEvent::$NAME, [$this, 'onSubPlaylistItems']);
|
||||
$dispatcher->addListener(SubPlaylistValidityEvent::$NAME, [$this, 'onSubPlaylistValid']);
|
||||
$dispatcher->addListener(RegionAddedEvent::$NAME, [$this, 'onRegionAdded']);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Widget Edit
|
||||
* @param \Xibo\Event\WidgetEditEvent $event
|
||||
* @throws \Xibo\Support\Exception\InvalidArgumentException
|
||||
*/
|
||||
public function onWidgetEdit(WidgetEditEvent $event)
|
||||
{
|
||||
$widget = $event->getWidget();
|
||||
if ($widget->type !== 'subplaylist') {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->getLogger()->debug('onWidgetEdit: processing subplaylist for widgetId ' . $widget->widgetId);
|
||||
|
||||
// Get the IDs we had before the edit and work out the difference between then and now.
|
||||
$existingSubPlaylistIds = [];
|
||||
foreach ($this->getAssignedPlaylists($widget, true) as $assignedPlaylist) {
|
||||
if (!in_array($assignedPlaylist->playlistId, $existingSubPlaylistIds)) {
|
||||
$existingSubPlaylistIds[] = $assignedPlaylist->playlistId;
|
||||
}
|
||||
}
|
||||
|
||||
$this->getLogger()->debug('onWidgetEdit: there are ' . count($existingSubPlaylistIds) . ' existing playlists');
|
||||
|
||||
// Make up a companion setting which maps the playlistIds to the options
|
||||
$subPlaylists = $this->getAssignedPlaylists($widget);
|
||||
$subPlaylistIds = [];
|
||||
|
||||
foreach ($subPlaylists as $playlist) {
|
||||
if ($playlist->spots < 0) {
|
||||
throw new InvalidArgumentException(
|
||||
__('Number of spots must be empty, 0 or a positive number'),
|
||||
'subPlaylistIdSpots'
|
||||
);
|
||||
}
|
||||
|
||||
if ($playlist->spotLength < 0) {
|
||||
throw new InvalidArgumentException(
|
||||
__('Spot length must be empty, 0 or a positive number'),
|
||||
'subPlaylistIdSpotLength'
|
||||
);
|
||||
}
|
||||
|
||||
if (!in_array($playlist->playlistId, $subPlaylistIds)) {
|
||||
$subPlaylistIds[] = $playlist->playlistId;
|
||||
}
|
||||
}
|
||||
|
||||
// Validation
|
||||
if (count($subPlaylists) < 1) {
|
||||
throw new InvalidArgumentException(__('Please select at least 1 Playlist to embed'), 'subPlaylistId');
|
||||
}
|
||||
|
||||
// Work out whether we've added/removed
|
||||
$addedEntries = array_diff($subPlaylistIds, $existingSubPlaylistIds);
|
||||
$removedEntries = array_diff($existingSubPlaylistIds, $subPlaylistIds);
|
||||
|
||||
$this->logger->debug('onWidgetEdit Added ' . var_export($addedEntries, true));
|
||||
$this->logger->debug('onWidgetEdit Removed ' . var_export($removedEntries, true));
|
||||
|
||||
// Remove items from closure table if necessary
|
||||
foreach ($removedEntries as $entry) {
|
||||
$this->logger->debug('Removing old link - existing link child is ' . $entry);
|
||||
|
||||
$this->storageService->update('
|
||||
DELETE link
|
||||
FROM `lkplaylistplaylist` p, `lkplaylistplaylist` link, `lkplaylistplaylist` c
|
||||
WHERE p.parentId = link.parentId AND c.childId = link.childId
|
||||
AND p.childId = :parentId AND c.parentId = :childId
|
||||
', [
|
||||
'parentId' => $widget->playlistId,
|
||||
'childId' => $entry
|
||||
]);
|
||||
}
|
||||
|
||||
foreach ($addedEntries as $addedEntry) {
|
||||
$this->logger->debug('Manage closure table for parent ' . $widget->playlistId
|
||||
. ' and child ' . $addedEntry);
|
||||
|
||||
if ($this->storageService->exists('
|
||||
SELECT parentId, childId, depth
|
||||
FROM lkplaylistplaylist
|
||||
WHERE childId = :childId AND parentId = :parentId
|
||||
', [
|
||||
'parentId' => $widget->playlistId,
|
||||
'childId' => $addedEntry
|
||||
])) {
|
||||
throw new InvalidArgumentException(__('Cannot add the same SubPlaylist twice.'), 'playlistId');
|
||||
}
|
||||
|
||||
$this->storageService->insert('
|
||||
INSERT INTO `lkplaylistplaylist` (parentId, childId, depth)
|
||||
SELECT p.parentId, c.childId, p.depth + c.depth + 1
|
||||
FROM lkplaylistplaylist p, lkplaylistplaylist c
|
||||
WHERE p.childId = :parentId AND c.parentId = :childId
|
||||
', [
|
||||
'parentId' => $widget->playlistId,
|
||||
'childId' => $addedEntry
|
||||
]);
|
||||
}
|
||||
|
||||
// Make sure we've not created a circular reference
|
||||
// this is a lazy last minute check as we can't really tell if there is a circular reference unless
|
||||
// we've inserted the records already.
|
||||
if ($this->storageService->exists('
|
||||
SELECT depth
|
||||
FROM `lkplaylistplaylist`
|
||||
WHERE parentId = :parentId
|
||||
AND childId = parentId
|
||||
AND depth > 0
|
||||
', ['parentId' => $widget->playlistId])) {
|
||||
throw new InvalidArgumentException(
|
||||
__('This assignment creates a loop because the Playlist being assigned contains the Playlist being worked on.'),//phpcs:ignore
|
||||
'subPlaylistId'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Xibo\Event\WidgetDeleteEvent $event
|
||||
* @return void
|
||||
*/
|
||||
public function onWidgetDelete(WidgetDeleteEvent $event)
|
||||
{
|
||||
$widget = $event->getWidget();
|
||||
|
||||
$this->getLogger()->debug('onWidgetDelete: processing widgetId ' . $widget->widgetId);
|
||||
|
||||
// Clear cache
|
||||
$renderer = $this->moduleFactory->createWidgetHtmlRenderer();
|
||||
$renderer->clearWidgetCache($widget);
|
||||
|
||||
// Everything else relates to sub-playlists
|
||||
if ($widget->type !== 'subplaylist') {
|
||||
return;
|
||||
}
|
||||
|
||||
$subPlaylists = $this->getAssignedPlaylists($widget);
|
||||
|
||||
// tidy up the closure table records.
|
||||
foreach ($subPlaylists as $subPlaylist) {
|
||||
$this->storageService->update('
|
||||
DELETE link
|
||||
FROM `lkplaylistplaylist` p, `lkplaylistplaylist` link, `lkplaylistplaylist` c
|
||||
WHERE p.parentId = link.parentId AND c.childId = link.childId
|
||||
AND p.childId = :parentId AND c.parentId = :childId
|
||||
', [
|
||||
'parentId' => $widget->playlistId,
|
||||
'childId' => $subPlaylist->playlistId,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Xibo\Event\SubPlaylistDurationEvent $event
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\GeneralException
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function onDuration(SubPlaylistDurationEvent $event)
|
||||
{
|
||||
$widget = $event->getWidget();
|
||||
$this->getLogger()->debug('onDuration: for ' . $widget->type);
|
||||
|
||||
if ($widget->type !== 'subplaylist') {
|
||||
return;
|
||||
}
|
||||
|
||||
// We give our widgetId to the resolve method so that it resolves us as if we're a child.
|
||||
// we only resolve top-level sub-playlists when we build the layout XLF
|
||||
$duration = 0;
|
||||
$countWidgets = 0;
|
||||
foreach ($this->getSubPlaylistResolvedWidgets($widget, $widget->widgetId ?? 0) as $resolvedWidget) {
|
||||
$duration += $resolvedWidget->calculatedDuration;
|
||||
$countWidgets++;
|
||||
}
|
||||
|
||||
if ($widget->getOptionValue('cyclePlaybackEnabled', 0) === 1 && $countWidgets > 0) {
|
||||
$this->getLogger()->debug('onDuration: cycle playback is enabled and there are ' . $countWidgets
|
||||
. ' widgets with a total of ' . $duration . ' seconds');
|
||||
|
||||
$duration = intval(ceil($duration / $countWidgets));
|
||||
}
|
||||
|
||||
$event->appendDuration($duration);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Xibo\Event\SubPlaylistWidgetsEvent $event
|
||||
* @return void
|
||||
* @throws \Xibo\Support\Exception\GeneralException
|
||||
* @throws \Xibo\Support\Exception\NotFoundException
|
||||
*/
|
||||
public function onWidgets(SubPlaylistWidgetsEvent $event)
|
||||
{
|
||||
$widget = $event->getWidget();
|
||||
if ($widget->type !== 'subplaylist') {
|
||||
return;
|
||||
}
|
||||
|
||||
$event->setWidgets($this->getSubPlaylistResolvedWidgets($widget, $event->getTempId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SubPlaylistItemsEvent $event
|
||||
* @return void
|
||||
*/
|
||||
public function onSubPlaylistItems(SubPlaylistItemsEvent $event)
|
||||
{
|
||||
$widget = $event->getWidget();
|
||||
if ($widget->type !== 'subplaylist') {
|
||||
return;
|
||||
}
|
||||
|
||||
$event->setItems($this->getAssignedPlaylists($widget));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SubPlaylistValidityEvent $event
|
||||
* @return void
|
||||
*/
|
||||
public function onSubPlaylistValid(SubPlaylistValidityEvent $event): void
|
||||
{
|
||||
$playlists = $this->getAssignedPlaylists($event->getWidget());
|
||||
if (count($playlists) <= 0) {
|
||||
$event->setIsValid(false);
|
||||
return;
|
||||
} else {
|
||||
foreach ($playlists as $playlistItem) {
|
||||
try {
|
||||
$this->playlistFactory->getById($playlistItem->playlistId);
|
||||
} catch (NotFoundException $e) {
|
||||
$this->getLogger()->error('Misconfigured sub playlist, playlist ID '
|
||||
. $playlistItem->playlistId . ' Not found');
|
||||
$event->setIsValid(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
$event->setIsValid(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Xibo\Widget\SubPlaylistItem[]
|
||||
*/
|
||||
private function getAssignedPlaylists(Widget $widget, bool $originalValue = false): array
|
||||
{
|
||||
$this->getLogger()->debug('getAssignedPlaylists: original value: ' . var_export($originalValue, true));
|
||||
|
||||
$playlistItems = [];
|
||||
foreach (json_decode($widget->getOptionValue('subPlaylists', '[]', $originalValue), true) as $playlist) {
|
||||
$item = new SubPlaylistItem();
|
||||
$item->rowNo = intval($playlist['rowNo']);
|
||||
$item->playlistId = $playlist['playlistId'];
|
||||
$item->spotFill = $playlist['spotFill'] ?? null;
|
||||
$item->spotLength = $playlist['spotLength'] !== '' ? intval($playlist['spotLength']) : null;
|
||||
$item->spots = $playlist['spots'] !== '' ? intval($playlist['spots']) : null;
|
||||
|
||||
$playlistItems[] = $item;
|
||||
}
|
||||
return $playlistItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $parentWidgetId this tracks the top level widgetId
|
||||
* @return Widget[] $widgets
|
||||
* @throws NotFoundException
|
||||
* @throws GeneralException
|
||||
*/
|
||||
private function getSubPlaylistResolvedWidgets(Widget $widget, int $parentWidgetId = 0): array
|
||||
{
|
||||
$this->getLogger()->debug('getSubPlaylistResolvedWidgets: widgetId is ' . $widget->widgetId
|
||||
. ', parentWidgetId is ' . $parentWidgetId);
|
||||
|
||||
$arrangement = $widget->getOptionValue('arrangement', 'none');
|
||||
$remainder = $widget->getOptionValue('remainder', 'none');
|
||||
$cyclePlayback = $widget->getOptionValue('cyclePlaybackEnabled', 0);
|
||||
$playCount = $widget->getOptionValue('playCount', 0);
|
||||
$isRandom = $widget->getOptionValue('cycleRandomWidget', 0);
|
||||
|
||||
$this->logger->debug('Resolve widgets for Sub-Playlist ' . $widget->widgetId
|
||||
. ' with arrangement ' . $arrangement . ' and remainder ' . $remainder);
|
||||
|
||||
// As a first step, get all of our playlists widgets loaded into an array
|
||||
/** @var Widget[] $resolvedWidgets */
|
||||
$resolvedWidgets = [];
|
||||
$widgets = [];
|
||||
$firstList = null;
|
||||
$firstListCount = 0;
|
||||
$largestListKey = null;
|
||||
$largestListCount = 0;
|
||||
$smallestListCount = 0;
|
||||
|
||||
// Expand or Shrink each of our assigned lists according to the Spot options (if any)
|
||||
// Expand all widgets from sub-playlists
|
||||
foreach ($this->getAssignedPlaylists($widget) as $playlistItem) {
|
||||
try {
|
||||
$playlist = $this->playlistFactory->getById($playlistItem->playlistId)
|
||||
->setModuleFactory($this->moduleFactory);
|
||||
} catch (NotFoundException $notFoundException) {
|
||||
$this->logger->error('getSubPlaylistResolvedWidgets: widget references a playlist which no longer exists. widgetId: '//phpcs:ignore
|
||||
. $widget->widgetId . ', playlistId: ' . $playlistItem->playlistId);
|
||||
continue;
|
||||
}
|
||||
$expanded = $playlist->expandWidgets($parentWidgetId);
|
||||
$countExpanded = count($expanded);
|
||||
|
||||
// Assert top level options
|
||||
// ------------------------
|
||||
// options such as stats/cycle playback are asserted from the top down
|
||||
// this is not a saved change, we assess this every time
|
||||
$playlistEnableStat = empty($playlist->enableStat)
|
||||
? $this->configService->getSetting('PLAYLIST_STATS_ENABLED_DEFAULT')
|
||||
: $playlist->enableStat;
|
||||
|
||||
foreach ($expanded as $subPlaylistWidget) {
|
||||
// Handle proof of play
|
||||
// Go through widgets assigned to this Playlist, if their enableStat is set to Inherit alter that option
|
||||
// in memory for this widget.
|
||||
$subPlaylistWidgetEnableStat = $subPlaylistWidget->getOptionValue(
|
||||
'enableStat',
|
||||
$this->configService->getSetting('WIDGET_STATS_ENABLED_DEFAULT')
|
||||
);
|
||||
|
||||
if ($subPlaylistWidgetEnableStat == 'Inherit') {
|
||||
$this->logger->debug('For widget ID ' . $subPlaylistWidget->widgetId
|
||||
. ' enableStat was Inherit, changed to Playlist enableStat value - ' . $playlistEnableStat);
|
||||
$subPlaylistWidget->setOptionValue('enableStat', 'attrib', $playlistEnableStat);
|
||||
}
|
||||
|
||||
// Cycle Playback
|
||||
// --------------
|
||||
// currently we only support cycle playback on the topmost level.
|
||||
// https://github.com/xibosignage/xibo/issues/2869
|
||||
$subPlaylistWidget->setOptionValue('cyclePlayback', 'attrib', $cyclePlayback);
|
||||
$subPlaylistWidget->setOptionValue('playCount', 'attrib', $playCount);
|
||||
$subPlaylistWidget->setOptionValue('isRandom', 'attrib', $isRandom);
|
||||
}
|
||||
|
||||
// Do we have a number of spots set?
|
||||
$this->logger->debug($playlistItem->spots . ' spots for playlistId ' . $playlistItem->playlistId);
|
||||
|
||||
// Do we need to expand or shrink our list to make our Spot length
|
||||
if ($playlistItem->spots !== null && $playlistItem->spots != $countExpanded) {
|
||||
// We do need to do something!
|
||||
$this->logger->debug('There are ' . count($expanded) . ' Widgets in the list and we want '
|
||||
. $playlistItem->spots . ' fill is ' . $playlistItem->spotFill);
|
||||
|
||||
// If our spot size is 0, then we deliberately do not add to the final widgets array
|
||||
if ($playlistItem->spots == 0) {
|
||||
if ($firstList === null && count($expanded) > 0) {
|
||||
// If this is the first list, and it contains some values, then set it.
|
||||
$firstList = $expanded;
|
||||
}
|
||||
|
||||
// Skip over this one (we want to ignore it as it has spots = 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
// If there are 0 items in the list, we need to fill
|
||||
if (count($expanded) <= 0) {
|
||||
// If this is the first list, then we need to skip it completely
|
||||
if ($firstList === null) {
|
||||
continue;
|
||||
} else {
|
||||
// Not the first list, so we can swap over to fill mode and use the first list instead
|
||||
$playlistItem->spotFill = 'fill';
|
||||
}
|
||||
}
|
||||
|
||||
// Expand the list out, using the fill options.
|
||||
$spotFillIndex = 0;
|
||||
while (count($expanded) < $playlistItem->spots) {
|
||||
$spotsToFill = $playlistItem->spots - count($expanded);
|
||||
|
||||
if ($playlistItem->spotFill == 'repeat' || $firstList === null) {
|
||||
// Repeat the list to fill the spots
|
||||
$expanded = array_merge($expanded, $expanded);
|
||||
} else if ($playlistItem->spotFill == 'fill') {
|
||||
// Get Playlist 1 and use it to fill
|
||||
// Filling means taking playlist 1 and putting in on the end of the current list
|
||||
// until we're full
|
||||
$expanded = array_merge($expanded, $firstList);
|
||||
} else if ($playlistItem->spotFill == 'pad') {
|
||||
// Get Playlist 1 and use it to pad
|
||||
// padding means taking playlist 1 and interleaving it with the current list, until we're
|
||||
// full
|
||||
$new = [];
|
||||
$loops = $spotsToFill / count($expanded);
|
||||
|
||||
for ($i = 0; $i < count($expanded); $i++) {
|
||||
// Take one from the playlist we're operating on
|
||||
$new[] = $expanded[$i];
|
||||
|
||||
// Take $loops from the filler playlist (the first one)
|
||||
for ($j = 0; $j < $loops; $j++) {
|
||||
$new[] = $firstList[$spotFillIndex];
|
||||
$spotFillIndex++;
|
||||
|
||||
// if we've gone around too far, then start from the beginning.
|
||||
if ($spotFillIndex >= count($firstList)) {
|
||||
$spotFillIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
$expanded = $new;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($expanded) > $playlistItem->spots) {
|
||||
// Chop the list down to size.
|
||||
$expanded = array_slice($expanded, 0, $playlistItem->spots);
|
||||
}
|
||||
|
||||
// Update our count of expanded widgets to be the spots
|
||||
$countExpanded = $playlistItem->spots;
|
||||
} else if ($countExpanded <= 0) {
|
||||
// No spots required and no content in this list.
|
||||
continue;
|
||||
}
|
||||
|
||||
// first watermark
|
||||
if ($firstList === null) {
|
||||
$firstList = $expanded;
|
||||
}
|
||||
|
||||
if ($firstListCount === 0) {
|
||||
$firstListCount = $countExpanded;
|
||||
}
|
||||
|
||||
// high watermark
|
||||
if ($countExpanded > $largestListCount) {
|
||||
$largestListCount = $countExpanded;
|
||||
$largestListKey = $playlistItem->playlistId . '_' . $playlistItem->rowNo;
|
||||
}
|
||||
|
||||
// low watermark
|
||||
if ($countExpanded < $smallestListCount || $smallestListCount === 0) {
|
||||
$smallestListCount = $countExpanded;
|
||||
}
|
||||
|
||||
// Adjust the widget duration if necessary
|
||||
if ($playlistItem->spotLength !== null && $playlistItem->spotLength > 0) {
|
||||
foreach ($expanded as $widget) {
|
||||
$widget->useDuration = 1;
|
||||
$widget->duration = $playlistItem->spotLength;
|
||||
$widget->calculatedDuration = $playlistItem->spotLength;
|
||||
}
|
||||
}
|
||||
|
||||
$widgets[$playlistItem->playlistId . '_' . $playlistItem->rowNo] = $expanded;
|
||||
}
|
||||
|
||||
$this->logger->debug('Finished parsing all sub-playlists, smallest list is ' . $smallestListCount
|
||||
. ' widgets in size, largest is ' . $largestListCount);
|
||||
|
||||
if ($smallestListCount == 0 && $largestListCount == 0) {
|
||||
$this->logger->debug('No Widgets to order');
|
||||
return [];
|
||||
}
|
||||
|
||||
// Enable for debugging only - large log
|
||||
//$thislogger->debug(json_encode($widgets));
|
||||
$takeIndices = [];
|
||||
$lastTakeIndices = [];
|
||||
|
||||
// Arrangement first
|
||||
if ($arrangement === 'even' && $smallestListCount > 0) {
|
||||
// Evenly distributed by round-robin
|
||||
$arrangement = 'roundrobin';
|
||||
|
||||
// We need to decide how frequently we take from the respective lists.
|
||||
// this is different for each list.
|
||||
foreach (array_keys($widgets) as $listKey) {
|
||||
$takeIndices[$listKey] = intval(floor(count($widgets[$listKey]) / $smallestListCount));
|
||||
$lastTakeIndices[$listKey] = -1;
|
||||
}
|
||||
} else {
|
||||
// On a standard round-robin, we take every 1 item (i.e. one from each).
|
||||
foreach (array_keys($widgets) as $listKey) {
|
||||
$takeIndices[$listKey] = 1;
|
||||
$lastTakeIndices[$listKey] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
$this->logger->debug('Take Indices: ' . json_encode($takeIndices));
|
||||
|
||||
// Round-robin or sequentially
|
||||
if ($arrangement === 'roundrobin') {
|
||||
// Round Robin
|
||||
// Take 1 from each until we have run out, use the smallest list as the "key"
|
||||
$loopCount = $largestListCount / $takeIndices[$largestListKey];
|
||||
|
||||
$this->logger->debug('Round-Robin: We will loop a maximum of ' . $loopCount . ' times');
|
||||
|
||||
for ($i = 0; $i < $loopCount; $i++) {
|
||||
$this->logger->debug('Loop number ' . $i);
|
||||
|
||||
foreach (array_keys($widgets) as $listKey) {
|
||||
// How many items should we take from this list each time we go around?
|
||||
$takeEvery = $takeIndices[$listKey];
|
||||
$countInList = count($widgets[$listKey]);
|
||||
|
||||
$this->logger->debug('Assessing playlistId ' . $listKey . ' which has '
|
||||
. $countInList . ' widgets.');
|
||||
|
||||
for ($count = 1; $count <= $takeEvery; $count++) {
|
||||
// Increment the last index we consumed from this list each time
|
||||
$index = $lastTakeIndices[$listKey] + 1;
|
||||
|
||||
// Does this key actually have this many items?
|
||||
if ($index >= $countInList) {
|
||||
// it does not :o
|
||||
$this->logger->debug('Index ' . $index
|
||||
. ' is higher than the count of widgets in the list ' . $countInList);
|
||||
// what we do depends on our remainder setting
|
||||
// if we drop, we stop, otherwise we skip
|
||||
if ($remainder === 'drop') {
|
||||
// Stop everything, we've got enough
|
||||
break 3;
|
||||
} else if ($remainder === 'repeat') {
|
||||
// start this list again from the beginning.
|
||||
$index = 0;
|
||||
} else {
|
||||
// Just skip this key
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
|
||||
$this->logger->debug('Selecting widget at position ' . $index
|
||||
. ' from playlistId ' . $listKey);
|
||||
|
||||
// Append the key at the position
|
||||
$resolvedWidgets[] = $widgets[$listKey][$index];
|
||||
|
||||
// Update our last take index for this list.
|
||||
$lastTakeIndices[$listKey] = $index;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// None
|
||||
// If the arrangement is none we just add all the widgets together
|
||||
// Merge the arrays together for returning
|
||||
foreach ($widgets as $items) {
|
||||
if ($remainder === 'drop') {
|
||||
$this->logger->debug('Dropping list of ' . count($items)
|
||||
. ' widgets down to ' . $smallestListCount);
|
||||
|
||||
// We trim all arrays down to the smallest of them
|
||||
$items = array_slice($items, 0, $smallestListCount);
|
||||
} else if ($remainder === 'repeat') {
|
||||
$this->logger->debug('Expanding list of ' . count($items) . ' widgets to ' . $largestListCount);
|
||||
|
||||
while (count($items) < $largestListCount) {
|
||||
$items = array_merge($items, $items);
|
||||
}
|
||||
|
||||
// Finally trim (we might have added too many if the list sizes aren't exactly divisible)
|
||||
$items = array_slice($items, 0, $largestListCount);
|
||||
}
|
||||
|
||||
$resolvedWidgets = array_merge($resolvedWidgets, $items);
|
||||
}
|
||||
}
|
||||
|
||||
// At the end of it, log out what we've calculated
|
||||
$log = 'Resolved: ';
|
||||
foreach ($resolvedWidgets as $resolvedWidget) {
|
||||
$log .= $resolvedWidget->playlistId . '-' . $resolvedWidget->widgetId . ',';
|
||||
|
||||
// Should my from/to dates be applied to the resolved widget?
|
||||
// only if they are more restrictive.
|
||||
// because this is recursive, we should end up with the top most widget being "ruler" of the from/to dates
|
||||
if ($widget->fromDt > $resolvedWidget->fromDt) {
|
||||
$resolvedWidget->fromDt = $widget->fromDt;
|
||||
}
|
||||
|
||||
if ($widget->toDt < $resolvedWidget->toDt) {
|
||||
$resolvedWidget->toDt = $widget->toDt;
|
||||
}
|
||||
}
|
||||
$this->logger->debug($log);
|
||||
|
||||
return $resolvedWidgets;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: we will need a way to upgrade from early v3 to late v3
|
||||
* (this can replace convertOldPlaylistOptions in Layout Factory)
|
||||
* @return void
|
||||
*/
|
||||
private function toDoUpgrade(Widget $widget)
|
||||
{
|
||||
$playlists = json_decode($widget->getOptionValue('subPlaylists', '[]'), true);
|
||||
if (count($playlists) <= 0) {
|
||||
// Try and load them the old way.
|
||||
$this->getLogger()->debug('getAssignedPlaylists: playlists not found in subPlaylists option, loading the old way.');//@phpcs:ignore
|
||||
|
||||
$playlistIds = json_decode($widget->getOptionValue('subPlaylistIds', '[]'), true);
|
||||
$subPlaylistOptions = json_decode($widget->getOptionValue('subPlaylistOptions', '[]'), true);
|
||||
$i = 0;
|
||||
foreach ($playlistIds as $playlistId) {
|
||||
$i++;
|
||||
$playlists[] = [
|
||||
'rowNo' => $i,
|
||||
'playlistId' => $playlistId,
|
||||
'spotFill' => $subPlaylistOptions[$playlistId]['subPlaylistIdSpotFill'] ?? null,
|
||||
'spotLength' => $subPlaylistOptions[$playlistId]['subPlaylistIdSpotLength'] ?? null,
|
||||
'spots' => $subPlaylistOptions[$playlistId]['subPlaylistIdSpots'] ?? null,
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$this->getLogger()->debug('getAssignedPlaylists: playlists found in subPlaylists option.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Tidy up any old options
|
||||
if ($widget->getOptionValue('subPlaylistIds', null) !== null) {
|
||||
$widget->setOptionValue('subPlaylistIds', 'attrib', null);
|
||||
$widget->setOptionValue('subPlaylistOptions', 'attrib', null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a region being added
|
||||
* @param RegionAddedEvent $event
|
||||
* @return void
|
||||
* @throws InvalidArgumentException
|
||||
* @throws NotFoundException
|
||||
* @throws \Xibo\Support\Exception\DuplicateEntityException
|
||||
*/
|
||||
public function onRegionAdded(RegionAddedEvent $event)
|
||||
{
|
||||
// We are a canvas region
|
||||
if ($event->getRegion()->type === 'canvas') {
|
||||
$this->getLogger()->debug('onRegionAdded: canvas region found, adding global widget');
|
||||
|
||||
// Add the global widget
|
||||
$module = $this->moduleFactory->getById('core-canvas');
|
||||
|
||||
$widget = $this->widgetFactory->create(
|
||||
$event->getRegion()->getOwnerId(),
|
||||
$event->getRegion()->regionPlaylist->playlistId,
|
||||
$module->type,
|
||||
$module->defaultDuration,
|
||||
$module->schemaVersion
|
||||
);
|
||||
|
||||
$widget->calculateDuration($module);
|
||||
|
||||
$event->getRegion()->regionPlaylist->assignWidget($widget, 1);
|
||||
$event->getRegion()->regionPlaylist->save(['notify' => false, 'validate' => false]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user