芝麻web文件管理V1.00
编辑当前文件:/home/mgatv524/cms.mgaplay.com.br/lib/Entity/DisplayGroup.php
. */ namespace Xibo\Entity; use Carbon\Carbon; use Respect\Validation\Validator as v; use Xibo\Factory\DisplayFactory; use Xibo\Factory\DisplayGroupFactory; use Xibo\Factory\PermissionFactory; use Xibo\Factory\TagFactory; use Xibo\Helper\DateFormatHelper; use Xibo\Service\LogServiceInterface; use Xibo\Storage\StorageServiceInterface; use Xibo\Support\Exception\DuplicateEntityException; use Xibo\Support\Exception\GeneralException; use Xibo\Support\Exception\InvalidArgumentException; use Xibo\Support\Exception\NotFoundException; /** * Class DisplayGroup * @package Xibo\Entity * * @SWG\Definition() */ class DisplayGroup implements \JsonSerializable { use EntityTrait; /** * @SWG\Property( * description="The displayGroup Id" * ) * @var int */ public $displayGroupId; /** * @SWG\Property( * description="The displayGroup Name" * ) * @var string */ public $displayGroup; /** * @SWG\Property( * description="The displayGroup Description" * ) * @var string */ public $description; /** * @SWG\Property( * description="A flag indicating whether this displayGroup is a single display displayGroup", * ) * @var int */ public $isDisplaySpecific = 0; /** * @SWG\Property( * description="A flag indicating whether this displayGroup is dynamic", * ) * @var int */ public $isDynamic = 0; /** * @SWG\Property( * description="Criteria for this dynamic group. A comma separated set of regular expressions to apply", * ) * @var string */ public $dynamicCriteria; /** * @SWG\Property(description="Which logical operator should be used when filtering by multiple dynamic criteria? OR|AND") * @var string */ public $dynamicCriteriaLogicalOperator; /** * @SWG\Property( * description="Criteria for this dynamic group. A comma separated set of tags to apply", * ) * @var string */ public $dynamicCriteriaTags; /** * @SWG\Property(description="Flag indicating whether to filter by exact Tag match") * @var int */ public $dynamicCriteriaExactTags; /** * @SWG\Property(description="Which logical operator should be used when filtering by multiple Tags? OR|AND") * @var string */ public $dynamicCriteriaTagsLogicalOperator; /** * @SWG\Property( * description="The UserId who owns this display group", * ) * @var int */ public $userId = 0; /** * @SWG\Property(description="Tags associated with this DisplayGroup") * @var Tag[] */ public $tags = []; /** * @SWG\Property(description="The display bandwidth limit") * @var int */ public $bandwidthLimit; /** * @SWG\Property(description="A comma separated list of groups/users with permissions to this DisplayGroup") * @var string */ public $groupsWithPermissions; /** * @SWG\Property(description="The datetime this entity was created") * @var string */ public $createdDt; /** * @SWG\Property(description="The datetime this entity was last modified") * @var string */ public $modifiedDt; /** * @SWG\Property(description="The id of the Folder this Display Group belongs to") * @var int */ public $folderId; /** * @SWG\Property(description="The id of the Folder responsible for providing permissions for this Display Group") * @var int */ public $permissionsFolderId; /** * @SWG\Property(description="Optional Reference 1") * @var string */ public $ref1; /** * @SWG\Property(description="Optional Reference 2") * @var string */ public $ref2; /** * @SWG\Property(description="Optional Reference 3") * @var string */ public $ref3; /** * @SWG\Property(description="Optional Reference 4") * @var string */ public $ref4; /** * @SWG\Property(description="Optional Reference 5") * @var string */ public $ref5; // Child Items the Display Group is linked to public $displays = []; public $media = []; public $layouts = []; public $events = []; private $displayGroups = []; private $permissions = []; private $unassignTags = []; private $jsonInclude = ['displayGroupId', 'displayGroup']; // Track original assignments private $originalDisplayGroups = []; /** * Is notify required during save? * @var bool */ private $notifyRequired = false; /** * Is collect required? * @var bool */ private $collectRequired = true; /** * @var bool Are we allowed to notify? */ private $allowNotify = true; /** * @var DisplayFactory */ private $displayFactory; /** * @var DisplayGroupFactory */ private $displayGroupFactory; /** * @var PermissionFactory */ private $permissionFactory; /** * @var TagFactory */ private $tagFactory; /** * Entity constructor. * @param StorageServiceInterface $store * @param LogServiceInterface $log * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher * @param DisplayGroupFactory $displayGroupFactory * @param PermissionFactory $permissionFactory * @param TagFactory $tagFactory */ public function __construct($store, $log, $dispatcher, $displayGroupFactory, $permissionFactory, $tagFactory) { $this->setCommonDependencies($store, $log, $dispatcher); $this->displayGroupFactory = $displayGroupFactory; $this->permissionFactory = $permissionFactory; $this->tagFactory = $tagFactory; } public function setDisplayFactory(DisplayFactory $displayFactory) { $this->displayFactory = $displayFactory; } public function __clone() { $this->displayGroupId = null; $this->originalDisplayGroups = []; $this->loaded = false; if ($this->isDynamic) { $this->clearDisplays()->clearDisplayGroups(); } } /** * @return int */ public function getId() { return $this->displayGroupId; } public function getPermissionFolderId() { return $this->permissionsFolderId; } /** * @return int */ public function getOwnerId() { return $this->userId; } /** * Set the owner of this group * @param $userId */ public function setOwner($userId) { $this->userId = $userId; } /** * @return bool */ public function canChangeOwner() { return $this->isDisplaySpecific == 0; } /** * Set Collection Required * If true will send a player action to collect immediately * @param bool|true $collectRequired */ public function setCollectRequired($collectRequired = true) { $this->collectRequired = $collectRequired; } /** * Set the Owner of this Group * @param Display $display * @throws NotFoundException */ public function setDisplaySpecificDisplay($display) { $this->load(); $this->isDisplaySpecific = 1; $this->assignDisplay($display); } public function clearDisplays(): DisplayGroup { $this->displays = []; return $this; } public function clearDisplayGroups(): DisplayGroup { $this->displayGroups = []; return $this; } public function clearTags(): DisplayGroup { $this->tags = []; return $this; } public function clearLayouts(): DisplayGroup { $this->layouts = []; return $this; } public function clearMedia(): DisplayGroup { $this->media = []; return $this; } /** * Set the Media Status to Incomplete * @param int[] $displayIds */ public function notify($displayIds = []) { if ($this->allowNotify) { $notify = $this->displayFactory->getDisplayNotifyService(); if ($this->collectRequired) $notify->collectNow(); if (count($displayIds) > 0) { foreach ($displayIds as $displayId) { $notify->notifyByDisplayId($displayId); } } else { $notify->notifyByDisplayGroupId($this->displayGroupId); } } } /** * Assign Display * @param Display $display * @throws NotFoundException */ public function assignDisplay($display) { $found = false; foreach ($this->displays as $existingDisplay) { if ($existingDisplay->getId() === $display->getId()) { $found = true; break; } } if (!$found) $this->displays[] = $display; } /** * Unassign Display * @param Display $display * @throws NotFoundException */ public function unassignDisplay($display) { // Changes made? $countBefore = count($this->displays); $this->displays = array_udiff($this->displays, [$display], function($a, $b) { /** * @var Display $a * @var Display $b */ return $a->getId() - $b->getId(); }); // Notify if necessary if ($countBefore !== count($this->displays)) $this->notifyRequired = true; } /** * Assign DisplayGroup * @param DisplayGroup $displayGroup * @throws NotFoundException */ public function assignDisplayGroup($displayGroup) { if (!in_array($displayGroup, $this->displayGroups)) $this->displayGroups[] = $displayGroup; } /** * Unassign DisplayGroup * @param DisplayGroup $displayGroup * @throws NotFoundException */ public function unassignDisplayGroup($displayGroup) { // Changes made? $countBefore = count($this->displayGroups); $this->displayGroups = array_udiff($this->displayGroups, [$displayGroup], function($a, $b) { /** * @var DisplayGroup $a * @var DisplayGroup $b */ return $a->getId() - $b->getId(); }); // Notify if necessary if ($countBefore !== count($this->displayGroups)) $this->notifyRequired = true; } /** * Assign Media * @param Media $media * @throws NotFoundException */ public function assignMedia($media) { if (!in_array($media, $this->media)) { $this->media[] = $media; // We should notify $this->notifyRequired = true; } } /** * Unassign Media * @param Media $media * @throws NotFoundException */ public function unassignMedia($media) { // Changes made? $countBefore = count($this->media); $this->media = array_udiff($this->media, [$media], function($a, $b) { /** * @var Media $a * @var Media $b */ return $a->getId() - $b->getId(); }); // Notify if necessary if ($countBefore !== count($this->media)) $this->notifyRequired = true; } /** * Assign Layout * @param Layout $layout * @throws NotFoundException */ public function assignLayout($layout) { if (!in_array($layout, $this->layouts)) { $this->layouts[] = $layout; // We should notify $this->notifyRequired = true; } } /** * Unassign Layout * @param Layout $layout * @throws NotFoundException */ public function unassignLayout($layout) { // Changes made? $countBefore = count($this->layouts); $this->layouts = array_udiff($this->layouts, [$layout], function($a, $b) { /** * @var Layout $a * @var Layout $b */ return $a->getId() - $b->getId(); }); // Notify if necessary if ($countBefore !== count($this->layouts)) $this->notifyRequired = true; } /** * Does the campaign have the provided tag? * @param $searchTag * @return bool * @throws NotFoundException */ public function hasTag($searchTag) { $this->load(); foreach ($this->tags as $tag) { /* @var Tag $tag */ if ($tag->tag == $searchTag) return true; } return false; } /** * Assign Tag * @param Tag $tag * @return $this * @throws NotFoundException */ public function assignTag($tag): DisplayGroup { $this->getLog()->debug('Assigning tag: ' . $tag->tag); $this->load(); $this->handleTagAssign($tag); $this->getLog()->debug(sprintf('Tags after assignment %s', json_encode($this->tags))); return $this; } /** * Unassign tag * @param Tag $tag * @return $this * @throws NotFoundException */ public function unassignTag($tag) { $this->getLog()->debug('Unassigning tag: ' . $tag->tag); $this->load(); foreach ($this->tags as $key => $currentTag) { if ($currentTag->tagId === $tag->tagId && $currentTag->value === $tag->value) { $this->unassignTags[] = $tag; array_splice($this->tags, $key, 1); } } $this->getLog()->debug(sprintf('Tags after removal %s', json_encode($this->tags))); return $this; } /** * @param array[Tag] $tags */ public function replaceTags($tags = []) { if (!is_array($this->tags) || count($this->tags) <= 0) $this->tags = $this->tagFactory->loadByDisplayGroupId($this->displayGroupId); if ($this->tags != $tags) { $this->unassignTags = array_udiff($this->tags, $tags, function ($a, $b) { /* @var Tag $a */ /* @var Tag $b */ return $a->tagId - $b->tagId; }); $this->getLog()->debug(sprintf('Tags to be removed: %s', json_encode($this->unassignTags))); // Replace the arrays $this->tags = $tags; $this->getLog()->debug(sprintf('Tags remaining: %s', json_encode($this->tags))); } else { $this->getLog()->debug('Tags were not changed'); } } /** * Load the contents for this display group * @param array $options * @throws NotFoundException */ public function load($options = []) { $options = array_merge([ 'loadTags' => true ], $options); if ($this->loaded || $this->displayGroupId == null || $this->displayGroupId == 0) { return; } $this->permissions = $this->permissionFactory->getByObjectId(get_class($this), $this->displayGroupId); $this->displayGroups = $this->displayGroupFactory->getByParentId($this->displayGroupId); // Load all tags if ($options['loadTags']) { $this->tags = $this->tagFactory->loadByDisplayGroupId($this->displayGroupId); } // Set the originals $this->originalDisplayGroups = $this->displayGroups; // We are loaded $this->loaded = true; } /** * Validate this display * @throws DuplicateEntityException * @throws InvalidArgumentException */ public function validate() { if (!v::stringType()->notEmpty()->validate($this->displayGroup)) throw new InvalidArgumentException(__('Please enter a display group name'), 'displayGroup'); if (!empty($this->description) && !v::stringType()->length(null, 254)->validate($this->description)) throw new InvalidArgumentException(__('Description can not be longer than 254 characters'), 'description'); if ($this->isDisplaySpecific == 0) { // Check the name $result = $this->getStore()->select('SELECT DisplayGroup FROM displaygroup WHERE DisplayGroup = :displayGroup AND IsDisplaySpecific = 0 AND displayGroupId <> :displayGroupId', [ 'displayGroup' => $this->displayGroup, 'displayGroupId' => (($this->displayGroupId == null) ? 0 : $this->displayGroupId) ]); if (count($result) > 0) throw new DuplicateEntityException(sprintf(__('You already own a display group called "%s". Please choose another name.'), $this->displayGroup)); // If we are dynamic, then make sure we have some criteria if ($this->isDynamic == 1 && ($this->dynamicCriteria == '' && $this->dynamicCriteriaTags == '')) throw new InvalidArgumentException(__('Dynamic Display Groups must have at least one Criteria specified.'), 'dynamicCriteria'); } } /** * Save * @param array $options * @throws GeneralException */ public function save($options = []) { $options = array_merge([ 'validate' => true, 'saveGroup' => true, 'manageLinks' => true, 'manageDisplayLinks' => true, 'manageDynamicDisplayLinks' => true, 'allowNotify' => true, 'saveTags' => true ], $options); // Should we allow notification or not? $this->allowNotify = $options['allowNotify']; if ($options['validate']) $this->validate(); if ($this->displayGroupId == null || $this->displayGroupId == 0) { $this->add(); $this->loaded = true; } else if ($options['saveGroup']) { $this->edit(); } if ($options['saveTags']) { // Remove unwanted ones if (is_array($this->unassignTags)) { foreach ($this->unassignTags as $tag) { /* @var Tag $tag */ $this->getLog()->debug('Unassigning tag ' . $tag->tag); $tag->unassignDisplayGroup($this->displayGroupId); $tag->save(); } } // Save Tags if (is_array($this->tags)) { foreach ($this->tags as $tag) { /* @var Tag $tag */ $this->getLog()->debug('Assigning tag ' . $tag->tag); $tag->assignDisplayGroup($this->displayGroupId); $tag->save(); } } } if ($this->loaded) { $this->getLog()->debug('Manage links'); if ($options['manageLinks']) { // Handle any changes in the media linked $this->linkMedia(); $this->unlinkMedia(); // Handle any changes in the layouts linked $this->linkLayouts(); $this->unlinkLayouts(); } if ($options['manageDisplayLinks']) { // Handle any changes in the displays linked $this->manageDisplayLinks($options['manageDynamicDisplayLinks']); // Handle any group links $this->manageDisplayGroupLinks(); } } else if ($this->isDynamic == 1 && $options['manageDynamicDisplayLinks']) { $this->manageDisplayLinks(); } // Set media incomplete if necessary if ($this->notifyRequired) { $this->notify(); } } /** * Delete * @throws NotFoundException * @throws GeneralException */ public function delete() { // Load everything for the delete $this->load(); // Delete things this group can own foreach ($this->permissions as $permission) { /* @var Permission $permission */ $permission->delete(); } foreach ($this->events as $event) { /* @var Schedule $event */ $event->unassignDisplayGroup($this); $event->save([ 'audit' => false, 'validate' => false, 'deleteOrphaned' => true, 'notify' => false ]); } foreach ($this->tags as $tag) { /* @var Tag $tag */ $tag->unassignDisplayGroup($this->displayGroupId); $tag->save(); } // Delete assignments $this->removeAssignments(); // delete link to ad campaign. $this->getStore()->update('DELETE FROM `lkcampaigndisplaygroup` WHERE displayGroupId = :displayGroupId', ['displayGroupId' => $this->displayGroupId]); // Delete the Group itself $this->getStore()->update('DELETE FROM `displaygroup` WHERE DisplayGroupID = :displayGroupId', ['displayGroupId' => $this->displayGroupId]); } /** * Remove any assignments */ public function removeAssignments() { $this->displays = []; $this->displayGroups = []; $this->layouts = []; $this->media = []; $this->unlinkDisplays(); $this->unlinkAllDisplayGroups(); $this->unlinkLayouts(); $this->unlinkMedia(); // Delete Notifications // NB: notifications aren't modelled as child objects because there could be many thousands of notifications on each // displaygroup. We consider the notification to be the parent here and it manages the assignments. // This does mean that we might end up with an empty notification (not assigned to anything) $this->getStore()->update('DELETE FROM `lknotificationdg` WHERE `displayGroupId` = :displayGroupId', ['displayGroupId' => $this->displayGroupId]); } private function add() { $time = Carbon::now()->format(DateFormatHelper::getSystemFormat()); $this->displayGroupId = $this->getStore()->insert(' INSERT INTO displaygroup (DisplayGroup, IsDisplaySpecific, Description, `isDynamic`, `dynamicCriteria`, `dynamicCriteriaLogicalOperator`, `dynamicCriteriaTags`, `dynamicCriteriaExactTags`, `dynamicCriteriaTagsLogicalOperator`, `userId`, `createdDt`, `modifiedDt`, `folderId`, `permissionsFolderId`, `ref1`, `ref2`, `ref3`, `ref4`, `ref5`) VALUES (:displayGroup, :isDisplaySpecific, :description, :isDynamic, :dynamicCriteria, :dynamicCriteriaLogicalOperator, :dynamicCriteriaTags, :dynamicCriteriaExactTags, :dynamicCriteriaTagsLogicalOperator, :userId, :createdDt, :modifiedDt, :folderId, :permissionsFolderId, :ref1, :ref2, :ref3, :ref4, :ref5) ', [ 'displayGroup' => $this->displayGroup, 'isDisplaySpecific' => $this->isDisplaySpecific, 'description' => $this->description, 'isDynamic' => $this->isDynamic, 'dynamicCriteria' => $this->dynamicCriteria, 'dynamicCriteriaLogicalOperator' => $this->dynamicCriteriaLogicalOperator ?? 'OR', 'dynamicCriteriaTags' => $this->dynamicCriteriaTags, 'dynamicCriteriaExactTags' => $this->dynamicCriteriaExactTags ?? 0, 'dynamicCriteriaTagsLogicalOperator' => $this->dynamicCriteriaTagsLogicalOperator ?? 'OR', 'userId' => $this->userId, 'createdDt' => $time, 'modifiedDt' => $time, 'folderId' => ($this->folderId === null) ? 1 : $this->folderId, 'permissionsFolderId' => ($this->permissionsFolderId == null) ? 1 : $this-> permissionsFolderId, 'ref1' => $this->ref1, 'ref2' => $this->ref2, 'ref3' => $this->ref3, 'ref4' => $this->ref4, 'ref5' => $this->ref5 ]); // Insert my self link $this->getStore()->insert('INSERT INTO `lkdgdg` (`parentId`, `childId`, `depth`) VALUES (:parentId, :childId, 0)', [ 'parentId' => $this->displayGroupId, 'childId' => $this->displayGroupId ]); } private function edit() { $this->getLog()->debug(sprintf('Updating Display Group. %s, %d', $this->displayGroup, $this->displayGroupId)); $this->getStore()->update(' UPDATE displaygroup SET DisplayGroup = :displayGroup, Description = :description, `isDynamic` = :isDynamic, `dynamicCriteria` = :dynamicCriteria, `dynamicCriteriaLogicalOperator` = :dynamicCriteriaLogicalOperator, `dynamicCriteriaTags` = :dynamicCriteriaTags, `dynamicCriteriaExactTags` = :dynamicCriteriaExactTags, `dynamicCriteriaTagsLogicalOperator` = :dynamicCriteriaTagsLogicalOperator, `bandwidthLimit` = :bandwidthLimit, `userId` = :userId, `modifiedDt` = :modifiedDt, `folderId` = :folderId, `permissionsFolderId` = :permissionsFolderId, `ref1` = :ref1, `ref2` = :ref2, `ref3` = :ref3, `ref4` = :ref4, `ref5` = :ref5 WHERE DisplayGroupID = :displayGroupId ', [ 'displayGroup' => $this->displayGroup, 'description' => $this->description, 'displayGroupId' => $this->displayGroupId, 'isDynamic' => $this->isDynamic, 'dynamicCriteria' => $this->dynamicCriteria, 'dynamicCriteriaLogicalOperator' => $this->dynamicCriteriaLogicalOperator ?? 'OR', 'dynamicCriteriaTags' => $this->dynamicCriteriaTags, 'dynamicCriteriaExactTags' => $this->dynamicCriteriaExactTags ?? 0, 'dynamicCriteriaTagsLogicalOperator' => $this->dynamicCriteriaTagsLogicalOperator ?? 'OR', 'bandwidthLimit' => $this->bandwidthLimit, 'userId' => $this->userId, 'modifiedDt' => Carbon::now()->format(DateFormatHelper::getSystemFormat()), 'folderId' => $this->folderId, 'permissionsFolderId' => $this->permissionsFolderId, 'ref1' => $this->ref1, 'ref2' => $this->ref2, 'ref3' => $this->ref3, 'ref4' => $this->ref4, 'ref5' => $this->ref5 ]); } /** * Manage the links to this display, dynamic or otherwise * @var bool $manageDynamic * @throws NotFoundException */ private function manageDisplayLinks($manageDynamic = true) { $this->getLog()->debug('Manage display links. Manage Dynamic = ' . $manageDynamic . ', Dynamic = ' . $this->isDynamic); $difference = []; if ($this->isDynamic == 1 && $manageDynamic) { $this->getLog()->info('Managing Display Links for Dynamic Display Group ' . $this->displayGroup); $originalDisplays = ($this->loaded) ? $this->displays : $this->displayFactory->getByDisplayGroupId($this->displayGroupId); // Update the linked displays based on the filter criteria // these displays must be permission checked based on the owner of the group NOT the logged in user $this->displays = $this->displayFactory->query(null, [ 'display' => $this->dynamicCriteria, 'logicalOperatorName' => $this->dynamicCriteriaLogicalOperator, 'tags' => $this->dynamicCriteriaTags, 'exactTags' => $this->dynamicCriteriaExactTags, 'logicalOperator' => $this->dynamicCriteriaTagsLogicalOperator, 'userCheckUserId' => $this->getOwnerId(), 'useRegexForName' => true ]); $this->getLog()->debug(sprintf('There are %d original displays and %d displays that match the filter criteria now.', count($originalDisplays), count($this->displays))); // Map our arrays to simple displayId lists $displayIds = array_map(function ($element) { return $element->displayId; }, $this->displays); $originalDisplayIds = array_map(function ($element) { return $element->displayId; }, $originalDisplays); $difference = array_merge(array_diff($displayIds, $originalDisplayIds), array_diff($originalDisplayIds, $displayIds)); // This is a dynamic display group // only manage the links that have changed if (count($difference) > 0) { $this->getLog()->debug(count($difference) . ' changes in dynamic Displays, will notify individually'); $this->notifyRequired = true; } else { $this->getLog()->debug('No changes in dynamic Displays, wont notify'); $this->notifyRequired = false; } } // Manage the links we've made either way // Link $this->linkDisplays(); // Check if we should notify if ($this->notifyRequired) { // We must notify before we unlink $this->notify($difference); } // Unlink // we never unlink from a display specific display group, unless we're deleting which does not call // manage display links. if ($this->isDisplaySpecific == 0) { $this->unlinkDisplays(); } // Don't do it again $this->notifyRequired = false; } /** * Manage display group links * @throws InvalidArgumentException */ private function manageDisplayGroupLinks() { $this->linkDisplayGroups(); $this->unlinkDisplayGroups(); // Check for circular references // 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->getStore()->exists('SELECT depth FROM `lkdgdg` WHERE parentId = :parentId AND childId = parentId AND depth > 0', ['parentId' => $this->displayGroupId])) throw new InvalidArgumentException(__('This assignment creates a circular reference')); } private function linkDisplays() { foreach ($this->displays as $display) { /* @var Display $display */ $this->getStore()->update('INSERT INTO lkdisplaydg (DisplayGroupID, DisplayID) VALUES (:displayGroupId, :displayId) ON DUPLICATE KEY UPDATE DisplayID = DisplayID', [ 'displayGroupId' => $this->displayGroupId, 'displayId' => $display->displayId ]); } } private function unlinkDisplays() { // Unlink any displays that are NOT in the collection $params = ['displayGroupId' => $this->displayGroupId]; $sql = 'DELETE FROM lkdisplaydg WHERE DisplayGroupID = :displayGroupId AND DisplayID NOT IN (0'; $i = 0; foreach ($this->displays as $display) { /* @var Display $display */ $i++; $sql .= ',:displayId' . $i; $params['displayId' . $i] = $display->displayId; } $sql .= ')'; $this->getStore()->update($sql, $params); } /** * Links the display groups that have been added to the OM * adding them to the closure table `lkdgdg` */ private function linkDisplayGroups() { $links = array_udiff($this->displayGroups, $this->originalDisplayGroups, function($a, $b) { /** * @var DisplayGroup $a * @var DisplayGroup $b */ return $a->getId() - $b->getId(); }); $this->getLog()->debug('Linking %d display groups to Display Group %s', count($links), $this->displayGroup); foreach ($links as $displayGroup) { /* @var DisplayGroup $displayGroup */ $this->getStore()->insert(' INSERT INTO lkdgdg (parentId, childId, depth) SELECT p.parentId, c.childId, p.depth + c.depth + 1 FROM lkdgdg p, lkdgdg c WHERE p.childId = :parentId AND c.parentId = :childId ', [ 'parentId' => $this->displayGroupId, 'childId' => $displayGroup->displayGroupId ]); } } /** * Unlinks the display groups that have been removed from the OM * removing them from the closure table `lkdgdg` */ private function unlinkDisplayGroups() { $links = array_udiff($this->originalDisplayGroups, $this->displayGroups, function($a, $b) { /** * @var DisplayGroup $a * @var DisplayGroup $b */ return $a->getId() - $b->getId(); }); $this->getLog()->debug('Unlinking ' . count($links) . ' display groups to Display Group ' . $this->displayGroup); foreach ($links as $displayGroup) { /* @var DisplayGroup $displayGroup */ // Only ever delete 1 because if there are more than 1, we can assume that it is linked at that level from // somewhere else // https://github.com/xibosignage/xibo/issues/1417 $linksToDelete = $this->getStore()->select(' SELECT DISTINCT link.parentId, link.childId, link.depth FROM `lkdgdg` p INNER JOIN `lkdgdg` link ON p.parentId = link.parentId INNER JOIN `lkdgdg` c ON c.childId = link.childId WHERE p.childId = :parentId AND c.parentId = :childId ', [ 'parentId' => $this->displayGroupId, 'childId' => $displayGroup->displayGroupId ]); foreach ($linksToDelete as $linkToDelete) { $this->getStore()->update(' DELETE FROM `lkdgdg` WHERE parentId = :parentId AND childId = :childId AND depth = :depth LIMIT 1 ', [ 'parentId' => $linkToDelete['parentId'], 'childId' => $linkToDelete['childId'], 'depth' => $linkToDelete['depth'] ]); } } } /** * Unlinks all display groups * usually in preparation for a delete */ private function unlinkAllDisplayGroups() { $this->getStore()->update(' DELETE link FROM `lkdgdg` p, `lkdgdg` link, `lkdgdg` c, `lkdgdg` to_delete WHERE p.parentId = link.parentId AND c.childId = link.childId AND p.childId = to_delete.parentId AND c.parentId = to_delete.childId AND (to_delete.parentId = :parentId OR to_delete.childId = :childId) AND to_delete.depth < 2 ', [ 'parentId' => $this->displayGroupId, 'childId' => $this->displayGroupId ]); } private function linkMedia() { foreach ($this->media as $media) { /* @var Media $media */ $this->getStore()->update('INSERT INTO `lkmediadisplaygroup` (mediaid, displaygroupid) VALUES (:mediaId, :displayGroupId) ON DUPLICATE KEY UPDATE mediaid = mediaid', [ 'displayGroupId' => $this->displayGroupId, 'mediaId' => $media->mediaId ]); } } private function unlinkMedia() { // Unlink any media that is NOT in the collection $params = ['displayGroupId' => $this->displayGroupId]; $sql = 'DELETE FROM `lkmediadisplaygroup` WHERE DisplayGroupID = :displayGroupId AND mediaId NOT IN (0'; $i = 0; foreach ($this->media as $media) { /* @var Media $media */ $i++; $sql .= ',:mediaId' . $i; $params['mediaId' . $i] = $media->mediaId; } $sql .= ')'; $this->getStore()->update($sql, $params); } private function linkLayouts() { foreach ($this->layouts as $layout) { /* @var Layout $media */ $this->getStore()->update('INSERT INTO `lklayoutdisplaygroup` (layoutid, displaygroupid) VALUES (:layoutId, :displayGroupId) ON DUPLICATE KEY UPDATE layoutid = layoutid', [ 'displayGroupId' => $this->displayGroupId, 'layoutId' => $layout->layoutId ]); } } private function unlinkLayouts() { // Unlink any layout that is NOT in the collection $params = ['displayGroupId' => $this->displayGroupId]; $sql = 'DELETE FROM `lklayoutdisplaygroup` WHERE DisplayGroupID = :displayGroupId AND layoutId NOT IN (0'; $i = 0; foreach ($this->layouts as $layout) { /* @var Layout $layout */ $i++; $sql .= ',:layoutId' . $i; $params['layoutId' . $i] = $layout->layoutId; } $sql .= ')'; $this->getStore()->update($sql, $params); } }