Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
100.00% |
1 / 1 |
|
100.00% |
14 / 14 |
CRAP | |
100.00% |
70 / 70 |
FilesService | |
100.00% |
1 / 1 |
|
100.00% |
14 / 14 |
30 | |
100.00% |
70 / 70 |
getNodes | |
100.00% |
1 / 1 |
2 | |
100.00% |
4 / 4 |
|||
isAllowedAndAvailable | |
100.00% |
1 / 1 |
4 | |
100.00% |
5 / 5 |
|||
getNodeType | |
100.00% |
1 / 1 |
2 | |
100.00% |
4 / 4 |
|||
getNodeData | |
100.00% |
1 / 1 |
1 | |
100.00% |
9 / 9 |
|||
getFolderData | |
100.00% |
1 / 1 |
1 | |
100.00% |
3 / 3 |
|||
getAllowedSubFolder | |
100.00% |
1 / 1 |
3 | |
100.00% |
4 / 4 |
|||
isRootFolder | |
100.00% |
1 / 1 |
3 | |
100.00% |
8 / 8 |
|||
recoverFromGetNodesError | |
100.00% |
1 / 1 |
2 | |
100.00% |
3 / 3 |
|||
isAllowed | |
100.00% |
1 / 1 |
4 | |
100.00% |
7 / 7 |
|||
isAvailable | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
isExternalShareAllowed | |
100.00% |
1 / 1 |
2 | |
100.00% |
3 / 3 |
|||
isExternalShare | |
100.00% |
1 / 1 |
2 | |
100.00% |
5 / 5 |
|||
getOwnerData | |
100.00% |
1 / 1 |
2 | |
100.00% |
6 / 6 |
|||
formatNodeData | |
100.00% |
1 / 1 |
1 | |
100.00% |
8 / 8 |
<?php | |
/** | |
* Gallery | |
* | |
* This file is licensed under the Affero General Public License version 3 or | |
* later. See the COPYING file. | |
* | |
* @author Olivier Paroz <galleryapps@oparoz.com> | |
* | |
* @copyright Olivier Paroz 2014-2016 | |
*/ | |
namespace OCA\Gallery\Service; | |
use OCP\Files\File; | |
use OCP\Files\Folder; | |
use OCP\Files\Node; | |
/** | |
* Contains various methods to retrieve information from the filesystem | |
* | |
* @package OCA\Gallery\Service | |
*/ | |
abstract class FilesService extends Service { | |
/** @var int */ | |
protected $virtualRootLevel = null; | |
/** @var string[] */ | |
protected $features; | |
/** @var string */ | |
protected $ignoreAlbum = '.nomedia'; | |
/** | |
* 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 | |
*/ | |
protected function getNodes($folder, $subDepth) { | |
try { | |
$nodes = $folder->getDirectoryListing(); | |
} catch (\Exception $exception) { | |
$nodes = $this->recoverFromGetNodesError($subDepth, $exception); | |
} | |
return $nodes; | |
} | |
/** | |
* Determines if the files are hosted locally (shared or not) and can be used by the preview | |
* system | |
* | |
* isMounted() doesn't include externally hosted shares, so we need to exclude those from the | |
* non-mounted nodes | |
* | |
* @param Node $node | |
* | |
* @return bool | |
*/ | |
protected function isAllowedAndAvailable($node) { | |
try { | |
return $node && $this->isAllowed($node) && $this->isAvailable($node); | |
} catch (\Exception $exception) { | |
$message = 'The folder is not available: ' . $exception->getMessage(); | |
$this->logger->error($message); | |
return false; | |
} | |
} | |
/** | |
* 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 | |
*/ | |
protected function getNodeType($node) { | |
try { | |
$nodeType = $node->getType(); | |
} catch (\Exception $exception) { | |
return ''; | |
} | |
return $nodeType; | |
} | |
/** | |
* Returns various information about a node | |
* | |
* @param Node|File|Folder $node | |
* | |
* @return array<string,int|string|bool|array<string,int|string>> | |
*/ | |
protected function getNodeData($node) { | |
$imagePath = $this->environment->getPathFromVirtualRoot($node); | |
$nodeId = $node->getId(); | |
$mTime = $node->getMTime(); | |
$etag = $node->getEtag(); | |
$size = $node->getSize(); | |
$sharedWithUser = $node->isShared(); | |
$ownerData = $this->getOwnerData($node); | |
$permissions = $node->getPermissions(); | |
//$this->logger->debug("Image path : {var1}", ['var1' => $imagePath]); | |
return $this->formatNodeData( | |
$imagePath, $nodeId, $mTime, $etag, $size, $sharedWithUser, $ownerData, $permissions | |
); | |
} | |
/** | |
* Returns various information about a folder | |
* | |
* @param Folder $node | |
* | |
* @return array<string,int|string|bool|array<string,int|string>> | |
*/ | |
protected function getFolderData($node) { | |
$folderData = $this->getNodeData($node); | |
$folderData['freespace'] = $node->getFreeSpace(); | |
return $folderData; | |
} | |
/** | |
* Returns the node if it's a folder we have access to | |
* | |
* @param Folder $node | |
* @param string $nodeType | |
* | |
* @return array|Folder | |
*/ | |
protected function getAllowedSubFolder($node, $nodeType) { | |
if ($nodeType === 'dir') { | |
/** @var Folder $node */ | |
if (!$node->nodeExists($this->ignoreAlbum)) { | |
return [$node]; | |
} | |
} | |
return []; | |
} | |
/** | |
* Determines if we've reached the root folder | |
* | |
* @param Folder $folder | |
* @param int $level | |
* | |
* @return bool | |
*/ | |
protected function isRootFolder($folder, $level) { | |
$isRootFolder = false; | |
$rootFolder = $this->environment->getVirtualRootFolder(); | |
if ($folder->getPath() === $rootFolder->getPath()) { | |
$isRootFolder = true; | |
} | |
$virtualRootFolder = $this->environment->getPathFromVirtualRoot($folder); | |
if (empty($virtualRootFolder)) { | |
$this->virtualRootLevel = $level; | |
} | |
return $isRootFolder; | |
} | |
/** | |
* 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) { | |
throw new NotFoundServiceException($exception->getMessage()); | |
} | |
return []; | |
} | |
/** | |
* Determines if we can consider the node mounted locally or if it's been authorised to be | |
* scanned | |
* | |
* @param Node $node | |
* | |
* @return bool | |
*/ | |
private function isAllowed($node) { | |
$allowed = true; | |
if ($this->isExternalShare($node)) { | |
$allowed = $this->isExternalShareAllowed(); | |
} | |
if ($node->isMounted()) { | |
$mount = $node->getMountPoint(); | |
$allowed = $mount && $mount->getOption('previews', true); | |
} | |
return $allowed; | |
} | |
/** | |
* Determines if the node is available, as in readable | |
* | |
* @todo Test to see by how much using file_exists slows things down | |
* | |
* @param Node $node | |
* | |
* @return bool | |
*/ | |
private function isAvailable($node) { | |
return $node->isReadable(); | |
} | |
/** | |
* Determines if the user has allowed the use of external shares | |
* | |
* @return bool | |
*/ | |
private function isExternalShareAllowed() { | |
$rootFolder = $this->environment->getVirtualRootFolder(); | |
return ($this->isExternalShare($rootFolder) | |
|| in_array('external_shares', $this->features)); | |
} | |
/** | |
* Determines if the node is a share which is hosted externally | |
* | |
* | |
* @param Node $node | |
* | |
* @return bool | |
*/ | |
private function isExternalShare($node) { | |
$sid = explode( | |
':', | |
$node->getStorage() | |
->getId() | |
); | |
return ($sid[0] === 'shared' && $sid[2][0] !== '/'); | |
} | |
/** | |
* Returns what we known about the owner of a node | |
* | |
* @param Node $node | |
* | |
* @return null|array<string,int|string> | |
*/ | |
private function getOwnerData($node) { | |
$owner = $node->getOwner(); | |
$ownerData = []; | |
if ($owner) { | |
$ownerData = [ | |
'uid' => $owner->getUID(), | |
'displayname' => $owner->getDisplayName() | |
]; | |
} | |
return $ownerData; | |
} | |
/** | |
* Returns an array containing information about a node | |
* | |
* @param string $imagePath | |
* @param int $nodeId | |
* @param int $mTime | |
* @param string $etag | |
* @param int $size | |
* @param bool $sharedWithUser | |
* @param array <string,int|string> $ownerData | |
* @param int $permissions | |
* | |
* @return array | |
*/ | |
private function formatNodeData( | |
$imagePath, $nodeId, $mTime, $etag, $size, $sharedWithUser, $ownerData, $permissions | |
) { | |
return [ | |
'path' => $imagePath, | |
'nodeid' => $nodeId, | |
'mtime' => $mTime, | |
'etag' => $etag, | |
'size' => $size, | |
'sharedwithuser' => $sharedWithUser, | |
'owner' => $ownerData, | |
'permissions' => $permissions | |
]; | |
} | |
} |