Completed
Push — stable8.2 ( 09e830...ae9bfd )
by Olivier
12:09
created

FilesService::getFolderData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 6
ccs 4
cts 4
cp 1
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
crap 1
1
<?php
2
/**
3
 * ownCloud - galleryplus
4
 *
5
 * This file is licensed under the Affero General Public License version 3 or
6
 * later. See the COPYING file.
7
 *
8
 * @author Olivier Paroz <[email protected]>
9
 *
10
 * @copyright Olivier Paroz 2014-2015
11
 */
12
13
namespace OCA\GalleryPlus\Service;
14
15
use OCP\Files\File;
16
use OCP\Files\Folder;
17
use OCP\Files\Node;
18
19
/**
20
 * Contains various methods to retrieve information from the filesystem
21
 *
22
 * @package OCA\GalleryPlus\Service
23
 */
24
abstract class FilesService extends Service {
25
26
	/** @var int */
27
	protected $virtualRootLevel = null;
28
	/** @var string[] */
29
	protected $features;
30
	/** @var string */
31
	protected $ignoreAlbum = '.nomedia';
32
33
	/**
34
	 * Retrieves all files and sub-folders contained in a folder
35
	 *
36
	 * If we can't find anything in the current folder, we throw an exception as there is no point
37
	 * in doing any more work, but if we're looking at a sub-folder, we return an empty array so
38
	 * that it can be simply ignored
39
	 *
40
	 * @param Folder $folder
41
	 * @param int $subDepth
42
	 *
43
	 * @return array
44
	 */
45 15
	protected function getNodes($folder, $subDepth) {
46
		try {
47 15
			$nodes = $folder->getDirectoryListing();
48 2
		} catch (\Exception $exception) {
49 2
			$nodes = $this->recoverFromGetNodesError($subDepth, $exception);
50
		}
51
52 14
		return $nodes;
53
	}
54
55
	/**
56
	 * Determines if the files are hosted locally (shared or not) and can be used by the preview
57
	 * system
58
	 *
59
	 * isMounted() doesn't include externally hosted shares, so we need to exclude those from the
60
	 * non-mounted nodes
61
	 *
62
	 * @param Node $node
63
	 *
64
	 * @return bool
65
	 */
66 35
	protected function isAllowedAndAvailable($node) {
67
		try {
68 35
			return $node && $this->isAllowed($node) && $this->isAvailable($node);
69 2
		} catch (\Exception $exception) {
70 2
			$message = 'The folder is not available: ' . $exception->getMessage();
71 2
			$this->logger->error($message);
72
73 2
			return false;
74
		}
75
	}
76
77
	/**
78
	 * Returns the node type, either 'dir' or 'file'
79
	 *
80
	 * If there is a problem, we return an empty string so that the node can be ignored
81
	 *
82
	 * @param Node $node
83
	 *
84
	 * @return string
85
	 */
86 14
	protected function getNodeType($node) {
87
		try {
88 14
			$nodeType = $node->getType();
89 1
		} catch (\Exception $exception) {
90 1
			return '';
91
		}
92
93 13
		return $nodeType;
94
	}
95
96
	/**
97
	 * Returns various information about a node
98
	 *
99
	 * @param Node|File|Folder $node
100
	 *
101
	 * @return array<string,int|string|bool|array<string,int|string>>
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,string|integer|boolean>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
102
	 */
103 13
	protected function getNodeData($node) {
104 13
		$imagePath = $this->environment->getPathFromVirtualRoot($node);
105 13
		$nodeId = $node->getId();
106 13
		$mTime = $node->getMTime();
107 13
		$etag = $node->getEtag();
108 13
		$size = $node->getSize();
109 13
		$sharedWithUser = $node->isShared();
110 13
		$permissions = $node->getPermissions();
111
112
		//$this->logger->debug("Image path : {var1}", ['var1' => $imagePath]);
113
114 13
		return $this->formatNodeData(
115
			$imagePath, $nodeId, $mTime, $etag, $size, $sharedWithUser, $permissions
116
		);
117
	}
118
119
	/**
120
	 * Returns various information about a folder
121
	 *
122
	 * @param Folder $node
123
	 *
124
	 * @return array<string,int|string|bool|array<string,int|string>>
125
	 */
126 13
	protected function getFolderData($node) {
127 13
		$folderData = $this->getNodeData($node);
128 13
		$folderData['freespace'] = $node->getFreeSpace();
129
130 13
		return $folderData;
131
	}
132
133
	/**
134
	 * Returns the node if it's a folder we have access to
135
	 *
136
	 * @param Folder $node
137
	 * @param string $nodeType
138
	 *
139
	 * @return array|Folder
140
	 */
141 14
	protected function getAllowedSubFolder($node, $nodeType) {
142 14
		if ($nodeType === 'dir') {
143
			/** @var Folder $node */
144 13
			if (!$node->nodeExists($this->ignoreAlbum)) {
145 11
				return [$node];
146
			}
147
		}
148
149 14
		return [];
150
	}
151
152
	/**
153
	 * Determines if we've reached the root folder
154
	 *
155
	 * @param Folder $folder
156
	 * @param int $level
157
	 *
158
	 * @return bool
159
	 */
160 5
	protected function isRootFolder($folder, $level) {
161 5
		$isRootFolder = false;
162 5
		$rootFolder = $this->environment->getVirtualRootFolder();
163 5
		if ($folder->getPath() === $rootFolder->getPath()) {
164 5
			$isRootFolder = true;
165
		}
166 5
		$virtualRootFolder = $this->environment->getPathFromVirtualRoot($folder);
167 5
		if (empty($virtualRootFolder)) {
168 5
			$this->virtualRootLevel = $level;
169
		}
170
171 5
		return $isRootFolder;
172
	}
173
174
	/**
175
	 * Throws an exception if this problem occurs in the current folder, otherwise just ignores the
176
	 * sub-folder
177
	 *
178
	 * @param int $subDepth
179
	 * @param \Exception $exception
180
	 *
181
	 * @return array
182
	 * @throws NotFoundServiceException
183
	 */
184 4
	private function recoverFromGetNodesError($subDepth, $exception) {
185 4
		if ($subDepth === 0) {
186 2
			throw new NotFoundServiceException($exception->getMessage());
187
		}
188
189 2
		return [];
190
	}
191
192
	/**
193
	 * Determines if we can consider the node mounted locally or if it's been authorised to be
194
	 * scanned
195
	 *
196
	 * @param Node $node
197
	 *
198
	 * @return bool
199
	 */
200 34
	private function isAllowed($node) {
201 34
		$allowed = true;
202 34
		if ($this->isExternalShare($node)) {
203 6
			$allowed = $this->isExternalShareAllowed();
204
		}
205
206 33
		if ($node->isMounted()) {
207 3
			$mount = $node->getMountPoint();
208 3
			$allowed = $mount && $mount->getOption('previews', true);
209
		}
210
211 33
		return $allowed;
212
	}
213
214
	/**
215
	 * Determines if the node is available, as in readable
216
	 *
217
	 * @todo Test to see by how much using file_exists slows things down
218
	 *
219
	 * @param Node $node
220
	 *
221
	 * @return bool
222
	 */
223 31
	private function isAvailable($node) {
224 31
		return $node->isReadable();
225
	}
226
227
	/**
228
	 * Determines if the user has allowed the use of external shares
229
	 *
230
	 * @return bool
231
	 */
232 6
	private function isExternalShareAllowed() {
233 6
		$rootFolder = $this->environment->getVirtualRootFolder();
234
235 6
		return ($this->isExternalShare($rootFolder)
0 ignored issues
show
Bug introduced by
It seems like $rootFolder defined by $this->environment->getVirtualRootFolder() on line 233 can also be of type null; however, OCA\GalleryPlus\Service\...vice::isExternalShare() does only seem to accept object<OCP\Files\Node>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
236 6
				|| in_array('external_shares', $this->features));
237
	}
238
239
	/**
240
	 * Determines if the node is a share which is hosted externally
241
	 *
242
	 *
243
	 * @param Node $node
244
	 *
245
	 * @return bool
246
	 */
247 34
	private function isExternalShare($node) {
248 34
		$sid = explode(
249 34
			':',
250 34
			$node->getStorage()
251 34
				 ->getId()
252
		);
253
254 34
		return ($sid[0] === 'shared' && $sid[2][0] !== '/');
255
	}
256
257
	/**
258
	 * Returns an array containing information about a node
259
	 *
260
	 * @param string $imagePath
261
	 * @param int $nodeId
262
	 * @param int $mTime
263
	 * @param string $etag
264
	 * @param int $size
265
	 * @param bool $sharedWithUser
266
	 * @param int $permissions
267
	 *
268
	 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,string|integer|boolean>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
269
	 */
270 13
	private function formatNodeData(
271
		$imagePath, $nodeId, $mTime, $etag, $size, $sharedWithUser, $permissions
272
	) {
273
		return [
274 13
			'path'           => $imagePath,
275 13
			'nodeid'         => $nodeId,
276 13
			'mtime'          => $mTime,
277 13
			'etag'           => $etag,
278 13
			'size'           => $size,
279 13
			'sharedwithuser' => $sharedWithUser,
280 13
			'permissions'    => $permissions
281
		];
282
	}
283
284
}
285