芝麻web文件管理V1.00
编辑当前文件:/home/mgatv524/public_html/sommatv/lib/Factory/MediaFactory.php
. */ namespace Xibo\Factory; use GuzzleHttp\Client; use GuzzleHttp\Exception\RequestException; use GuzzleHttp\Pool; use Xibo\Entity\Media; use Xibo\Entity\User; use Xibo\Exception\NotFoundException; use Xibo\Service\ConfigServiceInterface; use Xibo\Service\LogServiceInterface; use Xibo\Service\SanitizerServiceInterface; use Xibo\Storage\StorageServiceInterface; /** * Class MediaFactory * @package Xibo\Factory */ class MediaFactory extends BaseFactory { /** @var Media[] */ private $remoteDownloadQueue = []; /** @var Media[] */ private $remoteDownloadNotRequiredQueue = []; /** * @var ConfigServiceInterface */ private $config; /** * @var PermissionFactory */ private $permissionFactory; /** * @var TagFactory */ private $tagFactory; /** * @var PlaylistFactory */ private $playlistFactory; /** * Construct a factory * @param StorageServiceInterface $store * @param LogServiceInterface $log * @param SanitizerServiceInterface $sanitizerService * @param User $user * @param UserFactory $userFactory * @param ConfigServiceInterface $config * @param PermissionFactory $permissionFactory * @param TagFactory $tagFactory * @param PlaylistFactory $playlistFactory */ public function __construct($store, $log, $sanitizerService, $user, $userFactory, $config, $permissionFactory, $tagFactory, $playlistFactory) { $this->setCommonDependencies($store, $log, $sanitizerService); $this->setAclDependencies($user, $userFactory); $this->config = $config; $this->permissionFactory = $permissionFactory; $this->tagFactory = $tagFactory; $this->playlistFactory = $playlistFactory; } /** * Create Empty * @return Media */ public function createEmpty() { return new Media($this->getStore(), $this->getLog(), $this->config, $this, $this->permissionFactory, $this->tagFactory, $this->playlistFactory); } /** * Create New Media * @param string $name * @param string $fileName * @param string $type * @param int $ownerId * @param int $duration * @return Media */ public function create($name, $fileName, $type, $ownerId, $duration = 0) { $media = $this->createEmpty(); $media->name = $name; $media->fileName = $fileName; $media->mediaType = $type; $media->ownerId = $ownerId; $media->duration = $duration; return $media; } /** * Create System Module File * @param $name * @param string $file * @return Media */ public function createModuleSystemFile($name, $file = '') { return $this->createModuleFile($name, $file, 1); } /** * Create Module File * @param $name * @param $file * @param $systemFile * @return Media */ public function createModuleFile($name, $file = '', $systemFile = 0) { if ($file == '') { $file = $name; $name = basename($file); } try { $media = $this->getByNameAndType($name, 'module'); // Reassert the new file (which we might want to download) $media->fileName = $file; $media->storedAs = $name; } catch (NotFoundException $e) { $media = $this->createEmpty(); $media->name = $name; $media->fileName = $file; $media->mediaType = 'module'; $media->expires = 0; $media->storedAs = $name; $media->ownerId = $this->getUserFactory()->getSystemUser()->getOwnerId(); $media->moduleSystemFile = $systemFile; } return $media; } /** * Create module files from folder * @param string $folder The path to the folder to add. * @return array[Media] */ public function createModuleFileFromFolder($folder) { $media = []; if (!is_dir($folder)) throw new \InvalidArgumentException(__('Not a folder')); foreach (array_diff(scandir($folder), array('..', '.')) as $file) { if (is_dir($folder . DIRECTORY_SEPARATOR . $file)) continue; $file = $this->createModuleSystemFile($file, $folder . DIRECTORY_SEPARATOR . $file); $file->moduleSystemFile = true; $media[] = $file; } return $media; } /** * Queue remote file download * @param $name * @param $uri * @param $expiry * @return Media */ public function queueDownload($name, $uri, $expiry) { $this->getLog()->debug('Queue download of: ' . $uri); $media = $this->createModuleFile($name, $uri); $media->isRemote = true; // We update the desired expiry here - isSavedRequired is tested agains the original value $media->expires = $expiry; // Save the file, but do not download yet. $media->saveAsync(); // Add to our collection of queued downloads // but only if its not already in the queue (we might have tried to queue it multiple times in the same request) if ($media->isSaveRequired) { $queueItem = true; if ($media->getId() != null) { // Existing media, check to see if we're already queued foreach ($this->remoteDownloadQueue as $queue) { // If we find this item already, don't queue if ($queue->getId() === $media->getId()) { $queueItem = false; break; } } } if ($queueItem) $this->remoteDownloadQueue[] = $media; } else { // Queue in the not required download queue $queueItem = true; if ($media->getId() != null) { // Existing media, check to see if we're already queued foreach ($this->remoteDownloadNotRequiredQueue as $queue) { // If we find this item already, don't queue if ($queue->getId() === $media->getId()) { $queueItem = false; break; } } } if ($queueItem) $this->remoteDownloadNotRequiredQueue[] = $media; } // Return the media item return $media; } /** * Process the queue of downloads * @param null|callable $success success callable * @param null|callable $failure failure callable */ public function processDownloads($success = null, $failure = null) { if (count($this->remoteDownloadQueue) > 0) { $this->getLog()->debug('Processing Queue of ' . count($this->remoteDownloadQueue) . ' downloads.'); // Create a generator and Pool $log = $this->getLog(); $queue = $this->remoteDownloadQueue; $client = new Client($this->config->getGuzzleProxy()); $downloads = function () use ($client, $queue) { foreach ($queue as $media) { $url = $media->downloadUrl(); $sink = $media->downloadSink(); yield function () use ($client, $url, $sink) { return $client->getAsync($url, ['save_to' => $sink]); }; } }; $pool = new Pool($client, $downloads(), [ 'concurrency' => 5, 'fulfilled' => function ($response, $index) use ($log, $queue, $success, $failure) { /** @var Media $item */ $item = $queue[$index]; // File is downloaded, call save to move it appropriately try { $item->saveFile(); // If a success callback has been provided, call it if ($success !== null && is_callable($success)) $success($item); } catch (\Exception $e) { $this->getLog()->error('Unable to save:' . $item->mediaId . '. ' . $e->getMessage()); // Remove it $item->delete(['rollback' => true]); // If a failure callback has been provided, call it if ($failure !== null && is_callable($failure)) $failure($item); } }, 'rejected' => function ($reason, $index) use ($log) { /* @var RequestException $reason */ $log->error(sprintf('Rejected Request %d to %s because %s', $index, $reason->getRequest()->getUri(), $reason->getMessage())); } ]); $promise = $pool->promise(); $promise->wait(); } // Handle the downloads that did not require downloading if (count($this->remoteDownloadNotRequiredQueue) > 0) { foreach ($this->remoteDownloadNotRequiredQueue as $item) { // If a success callback has been provided, call it if ($success !== null && is_callable($success)) $success($item); } } } /** * Get by Media Id * @param int $mediaId * @return Media * @throws NotFoundException */ public function getById($mediaId) { $media = $this->query(null, array('disableUserCheck' => 1, 'mediaId' => $mediaId, 'allModules' => 1)); if (count($media) <= 0) throw new NotFoundException(__('Cannot find media')); return $media[0]; } /** * Get by Parent Media Id * @param int $mediaId * @return Media * @throws NotFoundException */ public function getParentById($mediaId) { $media = $this->query(null, array('disableUserCheck' => 1, 'parentMediaId' => $mediaId, 'allModules' => 1)); if (count($media) <= 0) throw new NotFoundException(__('Cannot find media')); return $media[0]; } /** * Get by Media Name * @param string $name * @return Media * @throws NotFoundException */ public function getByName($name) { $media = $this->query(null, array('disableUserCheck' => 1, 'nameExact' => $name, 'allModules' => 1)); if (count($media) <= 0) throw new NotFoundException(__('Cannot find media')); return $media[0]; } /** * Get by Media Name * @param string $name * @param string $type * @return Media * @throws NotFoundException */ public function getByNameAndType($name, $type) { $media = $this->query(null, array('disableUserCheck' => 1, 'nameExact' => $name, 'type' => $type, 'allModules' => 1)); if (count($media) <= 0) throw new NotFoundException(__('Cannot find media')); return $media[0]; } /** * Get by Owner Id * @param int $ownerId * @return array[Media] * @throws NotFoundException */ public function getByOwnerId($ownerId) { return $this->query(null, array('disableUserCheck' => 1, 'ownerId' => $ownerId)); } /** * Get by Type * @param string $type * @return array[Media] */ public function getByMediaType($type) { return $this->query(null, array('disableUserCheck' => 1, 'type' => $type, 'allModules' => 1)); } /** * Get by Display Group Id * @param int $displayGroupId * @return array[Media] */ public function getByDisplayGroupId($displayGroupId) { return $this->query(null, array('disableUserCheck' => 1, 'displayGroupId' => $displayGroupId)); } /** * Get Media by LayoutId * @param int $layoutId * @return array[Media] */ public function getByLayoutId($layoutId) { return $this->query(null, ['disableUserCheck' => 1, 'layoutId' => $layoutId]); } /** * Get Media by LayoutId * @param int $layoutId * @param int $widgetId * @return array[Media] */ public function getByLayoutAndWidget($layoutId, $widgetId) { return $this->query(null, ['disableUserCheck' => 1, 'layoutId' => $layoutId, 'widgetId' => $widgetId]); } /** * @param null $sortOrder * @param array $filterBy * @return Media[] */ public function query($sortOrder = null, $filterBy = []) { if ($sortOrder === null) $sortOrder = ['name']; $entries = array(); $params = array(); $select = ' SELECT media.mediaId, media.name, media.type AS mediaType, media.duration, media.userId AS ownerId, media.fileSize, media.storedAs, media.valid, media.moduleSystemFile, media.expires, media.md5, media.retired, media.isEdited, IFNULL(parentmedia.mediaId, 0) AS parentId, '; if (DBVERSION >= 125) { $select .= ' `media`.released, `media`.apiRef, '; } if (DBVERSION >= 134) { $select .= ' `media`.createdDt, `media`.modifiedDt, '; } $select .= " (SELECT GROUP_CONCAT(DISTINCT tag) FROM tag INNER JOIN lktagmedia ON lktagmedia.tagId = tag.tagId WHERE lktagmedia.mediaId = media.mediaID GROUP BY lktagmedia.mediaId) AS tags, "; $select .= " `user`.UserName AS owner, "; $select .= " (SELECT GROUP_CONCAT(DISTINCT `group`.group) FROM `permission` INNER JOIN `permissionentity` ON `permissionentity`.entityId = permission.entityId INNER JOIN `group` ON `group`.groupId = `permission`.groupId WHERE entity = :entity AND objectId = media.mediaId AND view = 1 ) AS groupsWithPermissions, "; $params['entity'] = 'Xibo\\Entity\\Media'; $select .= " media.originalFileName AS fileName "; $body = " FROM media "; $body .= " LEFT OUTER JOIN media parentmedia "; $body .= " ON parentmedia.editedMediaId = media.mediaId "; // Media might be linked to the system user (userId 0) $body .= " LEFT OUTER JOIN `user` ON `user`.userId = `media`.userId "; if ($this->getSanitizer()->getInt('displayGroupId', $filterBy) !== null) { $body .= ' INNER JOIN `lkmediadisplaygroup` ON lkmediadisplaygroup.mediaid = media.mediaid AND lkmediadisplaygroup.displayGroupId = :displayGroupId '; $params['displayGroupId'] = $this->getSanitizer()->getInt('displayGroupId', $filterBy); } $body .= " WHERE 1 = 1 "; // View Permissions $this->viewPermissionSql('Xibo\Entity\Media', $body, $params, '`media`.mediaId', '`media`.userId', $filterBy); if ($this->getSanitizer()->getInt('allModules', $filterBy) == 0) { $body .= ' AND media.type <> \'module\' '; } if ($this->getSanitizer()->getInt('assignable', -1, $filterBy) == 1) { $body .= ' AND media.type <> \'genericfile\' AND media.type <> \'font\' '; } if ($this->getSanitizer()->getInt('assignable', -1, $filterBy) == 0) { $body .= ' AND (media.type = \'genericfile\' OR media.type = \'font\') '; } // Unused only? if ($this->getSanitizer()->getInt('unusedOnly', $filterBy) !== null) { $body .= ' AND media.mediaId NOT IN (SELECT mediaId FROM `lkwidgetmedia`) AND media.mediaId NOT IN (SELECT mediaId FROM `lkmediadisplaygroup`) AND media.mediaId NOT IN (SELECT backgroundImageId FROM `layout` WHERE backgroundImageId IS NOT NULL) AND media.type <> \'module\' AND media.type <> \'font\' '; // DataSets with library images $dataSetSql = ' SELECT dataset.dataSetId, datasetcolumn.heading FROM dataset INNER JOIN datasetcolumn ON datasetcolumn.DataSetID = dataset.DataSetID WHERE DataTypeID = 5; '; $dataSets = $this->getStore()->select($dataSetSql, []); if (count($dataSets) > 0) { $body .= ' AND media.mediaID NOT IN ('; $first = true; foreach ($dataSets as $dataSet) { if (!$first) $body .= ' UNION ALL '; $first = false; $dataSetId = $this->getSanitizer()->getInt('dataSetId', $dataSet); $heading = $this->getSanitizer()->getString('heading', $dataSet); $body .= ' SELECT ' . $heading . ' AS mediaId FROM `dataset_' . $dataSetId . '`'; } $body .= ') '; } } if ($this->getSanitizer()->getString('name', $filterBy) != '') { // convert into a space delimited array $names = explode(' ', $this->getSanitizer()->getString('name', $filterBy)); $i = 0; foreach($names as $searchName) { $i++; // Not like, or like? if (substr($searchName, 0, 1) == '-') { $body .= ' AND media.name NOT LIKE :notLike' . $i . ' '; $params['notLike' . $i] = '%' . ltrim($searchName, '-') . '%'; } else { $body .= ' AND media.name LIKE :like' . $i . ' '; $params['like' . $i] = '%' . $searchName . '%'; } } } if ($this->getSanitizer()->getString('nameExact', $filterBy) != '') { $body .= ' AND media.name = :exactName '; $params['exactName'] = $this->getSanitizer()->getString('nameExact', $filterBy); } if ($this->getSanitizer()->getInt('mediaId', -1, $filterBy) != -1) { $body .= " AND media.mediaId = :mediaId "; $params['mediaId'] = $this->getSanitizer()->getInt('mediaId', $filterBy); } else if ($this->getSanitizer()->getInt('parentMediaId', $filterBy) !== null) { $body .= ' AND media.editedMediaId = :mediaId '; $params['mediaId'] = $this->getSanitizer()->getInt('parentMediaId', $filterBy); } else { $body .= ' AND media.isEdited = 0 '; } if ($this->getSanitizer()->getString('type', $filterBy) != '') { $body .= 'AND media.type = :type '; $params['type'] = $this->getSanitizer()->getString('type', $filterBy); } if ($this->getSanitizer()->getString('storedAs', $filterBy) != '') { $body .= 'AND media.storedAs = :storedAs '; $params['storedAs'] = $this->getSanitizer()->getString('storedAs', $filterBy); } if ($this->getSanitizer()->getInt('ownerId', $filterBy) !== null) { $body .= " AND media.userid = :ownerId "; $params['ownerId'] = $this->getSanitizer()->getInt('ownerId', $filterBy); } // User Group filter if ($this->getSanitizer()->getInt('ownerUserGroupId', 0, $filterBy) != 0) { $body .= ' AND media.userid IN (SELECT DISTINCT userId FROM `lkusergroup` WHERE groupId = :ownerUserGroupId) '; $params['ownerUserGroupId'] = $this->getSanitizer()->getInt('ownerUserGroupId', 0, $filterBy); } if ($this->getSanitizer()->getInt('retired', -1, $filterBy) == 1) $body .= " AND media.retired = 1 "; if ($this->getSanitizer()->getInt('retired', -1, $filterBy) == 0) $body .= " AND media.retired = 0 "; // Expired files? if ($this->getSanitizer()->getInt('expires', $filterBy) != 0) { $body .= ' AND media.expires < :expires AND IFNULL(media.expires, 0) <> 0 AND media.mediaId NOT IN (SELECT mediaId FROM `lkwidgetmedia`) '; $params['expires'] = $this->getSanitizer()->getInt('expires', $filterBy); } if ($this->getSanitizer()->getInt('layoutId', $filterBy) !== null) { $body .= ' AND media.mediaId IN ( SELECT `lkwidgetmedia`.mediaId FROM`lkwidgetmedia` INNER JOIN `widget` ON `widget`.widgetId = `lkwidgetmedia`.widgetId INNER JOIN `lkregionplaylist` ON `lkregionplaylist`.playlistId = `widget`.playlistId INNER JOIN `region` ON `region`.regionId = `lkregionplaylist`.regionId WHERE region.layoutId = :layoutId '; if ($this->getSanitizer()->getInt('widgetId', $filterBy) !== null) { $body .= ' AND `widget`.widgetId = :widgetId '; $params['widgetId'] = $this->getSanitizer()->getInt('widgetId', $filterBy); } $body .= ' ) AND media.type <> \'module\' '; $params['layoutId'] = $this->getSanitizer()->getInt('layoutId', $filterBy); } // Tags if ($this->getSanitizer()->getString('tags', $filterBy) != '') { $tagFilter = $this->getSanitizer()->getString('tags', $filterBy); if (trim($tagFilter) === '--no-tag') { $body .= ' AND `media`.mediaId NOT IN ( SELECT `lktagmedia`.mediaId FROM tag INNER JOIN `lktagmedia` ON `lktagmedia`.tagId = tag.tagId ) '; } else { $operator = $this->getSanitizer()->getCheckbox('exactTags') == 1 ? '=' : 'LIKE'; $body .= " AND `media`.mediaId IN ( SELECT `lktagmedia`.mediaId FROM tag INNER JOIN `lktagmedia` ON `lktagmedia`.tagId = tag.tagId "; $i = 0; foreach (explode(',', $tagFilter) as $tag) { $i++; if ($i == 1) $body .= ' WHERE `tag` ' . $operator . ' :tags' . $i; else $body .= ' OR `tag` ' . $operator . ' :tags' . $i; if ($operator === '=') $params['tags' . $i] = $tag; else $params['tags' . $i] = '%' . $tag . '%'; } $body .= " ) "; } } // File size if ($this->getSanitizer()->getString('fileSize', $filterBy) != null) { $fileSize = $this->parseComparisonOperator($this->getSanitizer()->getString('fileSize', $filterBy)); $body .= ' AND `media`.fileSize ' . $fileSize['operator'] . ' :fileSize '; $params['fileSize'] = $fileSize['variable']; } // Duration if ($this->getSanitizer()->getString('duration', $filterBy) != null) { $duration = $this->parseComparisonOperator($this->getSanitizer()->getString('duration', $filterBy)); $body .= ' AND `media`.duration ' . $duration['operator'] . ' :duration '; $params['duration'] = $duration['variable']; } // Sorting? $order = ''; if (is_array($sortOrder)) $order .= 'ORDER BY ' . implode(',', $sortOrder); $limit = ''; // Paging if ($filterBy !== null && $this->getSanitizer()->getInt('start', $filterBy) !== null && $this->getSanitizer()->getInt('length', $filterBy) !== null) { $limit = ' LIMIT ' . intval($this->getSanitizer()->getInt('start', $filterBy), 0) . ', ' . $this->getSanitizer()->getInt('length', 10, $filterBy); } $sql = $select . $body . $order . $limit; foreach ($this->getStore()->select($sql, $params) as $row) { $entries[] = $media = $this->createEmpty()->hydrate($row, [ 'intProperties' => [ 'duration', 'size', 'released', 'moduleSystemFile' ] ]); } // Paging if ($limit != '' && count($entries) > 0) { unset($params['entity']); $results = $this->getStore()->select('SELECT COUNT(*) AS total ' . $body, $params); $this->_countLast = intval($results[0]['total']); } return $entries; } }