Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/gallery.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'service/filesservice.php')
-rw-r--r--service/filesservice.php294
1 files changed, 294 insertions, 0 deletions
diff --git a/service/filesservice.php b/service/filesservice.php
new file mode 100644
index 00000000..56bfe327
--- /dev/null
+++ b/service/filesservice.php
@@ -0,0 +1,294 @@
+<?php
+/**
+ * ownCloud - galleryplus
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later. See the COPYING file.
+ *
+ * @author Olivier Paroz <owncloud@interfasys.ch>
+ *
+ * @copyright Olivier Paroz 2014-2015
+ */
+
+namespace OCA\GalleryPlus\Service;
+
+use OCP\Files\Folder;
+use OCP\Files\File;
+use OCP\Files\Node;
+
+/**
+ * Contains various methods which provide initial information about the
+ * supported media types, the folder permissions and the images contained in
+ * the system
+ *
+ * @package OCA\GalleryPlus\Service
+ */
+class FilesService extends Service {
+
+ /**
+ * @type null|array<string,string|int>
+ */
+ private $images = [];
+ /**
+ * @type string[]
+ */
+ private $supportedMediaTypes;
+
+ /**
+ * This returns the list of all media files which can be shown starting from the given folder
+ *
+ * @param Folder $folder
+ * @param string[] $supportedMediaTypes
+ *
+ * @return array<string,string|int> all the images we could find
+ */
+ public function getMediaFiles($folder, $supportedMediaTypes) {
+ $this->supportedMediaTypes = $supportedMediaTypes;
+
+ $this->searchFolder($folder);
+
+ return $this->images;
+ }
+
+ /**
+ * Look for media files and folders in the given folder
+ *
+ * @param Folder $folder
+ * @param int $subDepth
+ *
+ * @return int
+ */
+ private function searchFolder($folder, $subDepth = 0) {
+ $albumImageCounter = 0;
+ $subFolders = [];
+
+ $nodes = $this->getNodes($folder, $subDepth);
+ foreach ($nodes as $node) {
+ //$this->logger->debug("Sub-Node path : {path}", ['path' => $node->getPath()]);
+ $nodeType = $this->getNodeType($node);
+ $subFolders = array_merge($subFolders, $this->isFolder($node, $nodeType));
+
+ if ($nodeType === 'file') {
+ $albumImageCounter = $albumImageCounter + (int)$this->isPreviewAvailable($node);
+ if ($this->haveEnoughPictures($albumImageCounter, $subDepth)) {
+ break;
+ }
+ }
+ }
+ $this->searchSubFolders($subFolders, $subDepth, $albumImageCounter);
+
+ return $albumImageCounter;
+ }
+
+ /**
+ * Retrieves all files and sub-folders contained in a folder
+ *
+ * If we can't find anything in the current folder, we throw an exception as there is no point
+ * in doing any more work, but if we're looking at a sub-folder, we return an empty array so
+ * that it can be simply ignored
+ *
+ * @param Folder $folder
+ * @param int $subDepth
+ *
+ * @return array
+ *
+ * @throws NotFoundServiceException
+ */
+ private function getNodes($folder, $subDepth) {
+ $nodes = [];
+ try {
+ if ($folder->isReadable()
+ && $folder->getStorage()
+ ->isLocal()
+ ) {
+ $nodes = $folder->getDirectoryListing();
+ }
+ } catch (\Exception $exception) {
+ $nodes = $this->recoverFromGetNodesError($subDepth, $exception);
+ }
+
+ return $nodes;
+ }
+
+ /**
+ * Throws an exception if this problem occurs in the current folder, otherwise just ignores the
+ * sub-folder
+ *
+ * @param int $subDepth
+ * @param \Exception $exception
+ *
+ * @return array
+ * @throws NotFoundServiceException
+ */
+ private function recoverFromGetNodesError($subDepth, $exception) {
+ if ($subDepth === 0) {
+ $this->logAndThrowNotFound($exception->getMessage());
+ }
+
+ return [];
+ }
+
+ /**
+ * Returns the node type, either 'dir' or 'file'
+ *
+ * If there is a problem, we return an empty string so that the node can be ignored
+ *
+ * @param Node $node
+ *
+ * @return string
+ */
+ private function getNodeType($node) {
+ try {
+ $nodeType = $node->getType();
+ } catch (\Exception $exception) {
+ return '';
+ }
+
+ return $nodeType;
+ }
+
+ /**
+ * Returns the node if it's a folder we have access to
+ *
+ * @param Folder $node
+ * @param string $nodeType
+ *
+ * @return array|Folder
+ */
+ private function isFolder($node, $nodeType) {
+ if ($nodeType === 'dir') {
+ return [$node];
+ }
+
+ return [];
+ }
+
+ /**
+ * Checks if we've collected enough pictures to be able to build the view
+ *
+ * An album is full when we find max 4 pictures at the same level
+ *
+ * @param int $albumImageCounter
+ * @param int $subDepth
+ *
+ * @return bool
+ */
+ private function haveEnoughPictures($albumImageCounter, $subDepth) {
+ if ($subDepth === 0) {
+ return false;
+ }
+ if ($albumImageCounter === 4) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Looks for pictures in sub-folders
+ *
+ * If we're at level 0, we need to look for pictures in sub-folders no matter what
+ * If we're at deeper levels, we only need to go further if we haven't managed to find one
+ * picture in the current folder
+ *
+ * @param array<Folder> $subFolders
+ * @param int $subDepth
+ * @param int $albumImageCounter
+ */
+ private function searchSubFolders($subFolders, $subDepth, $albumImageCounter) {
+ if ($this->folderNeedsToBeSearched($subFolders, $subDepth, $albumImageCounter)) {
+ $subDepth++;
+ foreach ($subFolders as $subFolder) {
+ $count = $this->searchFolder($subFolder, $subDepth);
+ if ($this->abortSearch($subDepth, $count)) {
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks if we need to look for media files in the specified folder
+ *
+ * @param array<Folder> $subFolders
+ * @param int $subDepth
+ * @param int $albumImageCounter
+ *
+ * @return bool
+ */
+ private function folderNeedsToBeSearched($subFolders, $subDepth, $albumImageCounter) {
+ if (!empty($subFolders) && ($subDepth === 0 || $albumImageCounter === 0)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns true if there is no need to check any other sub-folder at the same depth level
+ *
+ * @param int $subDepth
+ * @param int $count
+ *
+ * @return bool
+ */
+ private function abortSearch($subDepth, $count) {
+ if ($subDepth > 1 && $count > 0) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns true if the file is of a supported media type and adds it to the array of items to
+ * return
+ *
+ * @todo We could potentially check if the file is readable ($file->stat() maybe) in order to
+ * only return valid files, but this may slow down operations
+ *
+ * @param File $file the file to test
+ *
+ * @return bool
+ */
+ private function isPreviewAvailable($file) {
+ try {
+ $mimeType = $file->getMimetype();
+ $isLocal = $file->getStorage()
+ ->isLocal();
+ if ($isLocal && in_array($mimeType, $this->supportedMediaTypes)) {
+ $this->addFileToResults($file);
+
+ return true;
+ }
+ } catch (\Exception $exception) {
+ return false;
+ }
+
+ return false;
+ }
+
+ /**
+ * Adds various information about a file to the list of results
+ *
+ * @param File $file
+ */
+ private function addFileToResults($file) {
+ $imagePath = $this->environment->getPathFromVirtualRoot($file);
+ $imageId = $file->getId();
+ $mimeType = $file->getMimetype();
+ $mTime = $file->getMTime();
+
+ $imageData = [
+ 'path' => $imagePath,
+ 'fileid' => $imageId,
+ 'mimetype' => $mimeType,
+ 'mtime' => $mTime
+ ];
+
+ $this->images[] = $imageData;
+
+ //$this->logger->debug("Image path : {path}", ['path' => $imagePath]);
+ }
+
+}