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

Environment::getNodeFromVirtualRoot()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 5
cts 5
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
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
 * @author Authors of \OCA\Files_Sharing\Helper
10
 *
11
 * @copyright Olivier Paroz 2015
12
 * @copyright Authors of \OCA\Files_Sharing\Helper 2014-2015
13
 */
14
15
namespace OCA\GalleryPlus\Environment;
16
17
use OCP\IUserManager;
18
use OCP\Share;
19
use OCP\ILogger;
20
use OCP\Files\IRootFolder;
21
use OCP\Files\Folder;
22
use OCP\Files\Node;
23
use OCP\Files\File;
24
use OCP\Files\NotFoundException;
25
26
/**
27
 * Builds the environment so that the services have access to the files and folders' owner
28
 *
29
 * @package OCA\GalleryPlus\Environment
30
 */
31
class Environment {
32
33
	/**
34
	 * @var string
35
	 */
36
	private $appName;
37
	/**
38
	 * The userId of the logged-in user or the person sharing a folder publicly
39
	 *
40
	 * @var string
41
	 */
42
	private $userId;
43
	/**
44
	 * The userFolder of the logged-in user or the ORIGINAL owner of the files which are shared
45
	 * publicly
46
	 *
47
	 * A share needs to be tracked back to its original owner in order to be able to access the
48
	 * resource
49
	 *
50
	 * @var Folder|null
51
	 */
52
	private $userFolder;
53
	/**
54
	 * @var IUserManager
55
	 */
56
	private $userManager;
57
	/**
58
	 * @var int
59
	 */
60
	private $sharedNodeId;
61
	/**
62
	 * @var IRootFolder
63
	 */
64
	private $rootFolder;
65
	/**
66
	 * @var ILogger
67
	 */
68
	private $logger;
69
	/**
70
	 * The path to the userFolder for users with accounts: /userId/files
71
	 *
72
	 * For public folders, it's the path from the shared folder to the root folder in the original
73
	 * owner's filesystem: /userId/files/parent_folder/shared_folder
74
	 *
75
	 * @var string
76
	 */
77
	private $fromRootToFolder;
78
	/**
79
	 * The name of the shared folder
80
	 *
81
	 * @var string
82
	 */
83
	private $folderName;
84
	/**
85
	 * @var string|null
86
	 */
87
	private $sharePassword;
88
89
	/***
90
	 * Constructor
91
	 *
92
	 * @param string $appName
93
	 * @param string|null $userId
94
	 * @param Folder|null $userFolder
95
	 * @param IUserManager $userManager
96
	 * @param IRootFolder $rootFolder
97
	 * @param ILogger $logger
98
	 */
99 58
	public function __construct(
100
		$appName,
101
		$userId,
102
		$userFolder,
103
		IUserManager $userManager,
104
		IRootFolder $rootFolder,
105
		ILogger $logger
106
	) {
107 58
		$this->appName = $appName;
108 58
		$this->userId = $userId;
109 58
		$this->userFolder = $userFolder;
110 58
		$this->userManager = $userManager;
111 58
		$this->rootFolder = $rootFolder;
112 58
		$this->logger = $logger;
113 58
	}
114
115
	/**
116
	 * Creates the environment based on the linkItem the token links to
117
	 *
118
	 * @param array $linkItem
119
	 */
120 20
	public function setTokenBasedEnv($linkItem) {
121
		// Resolves reshares down to the last real share
122 20
		$rootLinkItem = Share::resolveReShare($linkItem);
123 20
		$origShareOwner = $rootLinkItem['uid_owner'];
124 20
		$this->userFolder = $this->rootFolder->getUserFolder($origShareOwner);
125
126
		// This is actually the node ID
127 20
		$this->sharedNodeId = $linkItem['file_source'];
128 20
		$this->fromRootToFolder = $this->buildFromRootToFolder($this->sharedNodeId);
129
130 20
		$this->folderName = $linkItem['file_target'];
131 20
		$this->userId = $rootLinkItem['uid_owner'];
132 20
		$this->sharePassword = $linkItem['share_with'];
133 20
	}
134
135
	/**
136
	 * Creates the environment for a logged-in user
137
	 *
138
	 * userId and userFolder are already known, we define fromRootToFolder
139
	 * so that the services can use one method to have access to resources
140
	 * without having to know whether they're private or public
141
	 */
142 29
	public function setStandardEnv() {
143 29
		$this->fromRootToFolder = $this->userFolder->getPath() . '/';
144 29
	}
145
146
	/**
147
	 * Returns the Node based on a path starting from the virtual root
148
	 *
149
	 * @param string $subPath
150
	 *
151
	 * @return File|Folder
0 ignored issues
show
Documentation introduced by
Should the return type not be Node?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
152
	 */
153 8
	public function getNodeFromVirtualRoot($subPath) {
154 8
		$relativePath = $this->getRelativePath($this->fromRootToFolder);
155 8
		$path = $relativePath . '/' . $subPath;
156 8
		$node = $this->getNodeFromUserFolder($path);
157
158 8
		return $this->getResourceFromId($node->getId());
159
	}
160
161
	/**
162
	 * Returns the Node based on a path starting from the files' owner user folder
163
	 *
164
	 * When logged in, this is the current user's user folder
165
	 * When visiting a link, this is the sharer's user folder
166
	 *
167
	 * @param string $path
168
	 *
169
	 * @return File|Folder
170
	 *
171
	 * @throws NotFoundEnvException
172
	 */
173 11
	public function getNodeFromUserFolder($path) {
174 11
		$folder = $this->userFolder;
175 11
		if ($folder === null) {
176 1
			throw new NotFoundEnvException("Could not access the user's folder");
177
		} else {
178
			try {
179 10
				$node = $folder->get($path);
180 2
			} catch (NotFoundException $exception) {
181 2
				$message = 'Could not find anything at: ' . $exception->getMessage();
182 2
				throw new NotFoundEnvException($message);
183
			}
184
		}
185
186 10
		return $node;
187
	}
188
189
	/**
190
	 * Returns the resource identified by the given ID
191
	 *
192
	 * @param int $resourceId
193
	 *
194
	 * @return Node
195
	 *
196
	 * @throws NotFoundEnvException
197
	 */
198 36
	public function getResourceFromId($resourceId) {
199 36
		$resourcesArray = $this->userFolder->getById($resourceId);
200 36
		if ($resourcesArray[0] === null) {
201 3
			throw new NotFoundEnvException('Could not locate file linked to ID: ' . $resourceId);
202
		}
203
204 33
		return $resourcesArray[0];
205
	}
206
207
	/**
208
	 * Returns the shared node
209
	 *
210
	 * @return File|Folder
0 ignored issues
show
Documentation introduced by
Should the return type not be Node?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
211
	 */
212 8
	public function getSharedNode() {
213 8
		return $this->getResourceFromId($this->sharedNodeId);
214
	}
215
216
	/**
217
	 * Returns the virtual root where the user lands after logging in or when following a link
218
	 *
219
	 * @return Folder
220
	 * @throws NotFoundEnvException
221
	 */
222 14
	public function getVirtualRootFolder() {
223 14
		$rootFolder = $this->userFolder;
224 14
		if (!empty($this->sharedNodeId)) {
225 4
			$node = $this->getSharedNode();
226 4
			$nodeType = $node->getType();
227 4
			if ($nodeType === 'dir') {
228 3
				$rootFolder = $node;
229
			} else {
230 1
				throw new NotFoundEnvException($node->getPath() . ' is not a folder');
231
			}
232
		}
233
234 13
		return $rootFolder;
235
	}
236
237
	/**
238
	 * Returns the userId of the currently logged-in user or the sharer
239
	 *
240
	 * @return string
241
	 */
242 9
	public function getUserId() {
243 9
		return $this->userId;
244
	}
245
246
	/**
247
	 * Returns the name of the user sharing files publicly
248
	 *
249
	 * @return string
250
	 * @throws NotFoundEnvException
251
	 */
252 2
	public function getDisplayName() {
253 2
		$user = null;
254 2
		$userId = $this->userId;
255
256 2
		if (isset($userId)) {
257 1
			$user = $this->userManager->get($userId);
258
		}
259 2
		if ($user === null) {
260 1
			throw new NotFoundEnvException('Could not find user');
261
		}
262
263 1
		return $user->getDisplayName();
264
	}
265
266
	/**
267
	 * Returns the name of shared folder
268
	 *
269
	 * @return string
270
	 */
271 1
	public function getSharedFolderName() {
272 1
		return trim($this->folderName, '//');
273
	}
274
275
	/**
276
	 * Returns the password for the share, if there is one
277
	 *
278
	 * @return string|null
279
	 */
280 1
	public function getSharePassword() {
281 1
		return $this->sharePassword;
282
	}
283
284
	/**
285
	 * Returns the path which goes from the file, up to the user folder, based on a node:
286
	 * parent_folder/current_folder/my_file
287
	 *
288
	 * This is used for the preview system, which needs a full path
289
	 *
290
	 * getPath() on the file produces a path like:
291
	 * '/userId/files/my_folder/my_sub_folder/my_file'
292
	 *
293
	 * So we substract the path to the folder, giving us a relative path
294
	 * 'my_folder/my_sub_folder/my_file'
295
	 *
296
	 * @param Node $file
297
	 *
298
	 * @return string
299
	 */
300 9
	public function getPathFromUserFolder($file) {
301 9
		$path = $file->getPath();
302
303 9
		return $this->getRelativePath($path);
304
	}
305
306
	/**
307
	 * Returns the path which goes from the file, up to the root folder of the Gallery:
308
	 * current_folder/my_file
309
	 *
310
	 * That root folder changes when folders are shared publicly
311
	 *
312
	 * @param File|Folder|N $node
313
	 *
314
	 * @return string
315
	 */
316 10
	public function getPathFromVirtualRoot($node) {
317 10
		$path = $node->getPath();
318 10
		$nodeType = $node->getType();
319
320
		// Needed because fromRootToFolder always ends with a slash
321 10
		if ($nodeType === 'dir') {
322 8
			$path .= '/';
323
		}
324
325 10
		$path = str_replace($this->fromRootToFolder, '', $path);
326 10
		$path = rtrim($path, '/');
327
328 10
		return $path;
329
	}
330
331
	/**
332
	 * Returns the path from the shared folder to the root folder in the original
333
	 * owner's filesystem: /userId/files/parent_folder/shared_folder
334
	 *
335
	 * This cannot be calculated with paths and IDs, the linkitem's file source is required
336
	 *
337
	 * @param string $fileSource
338
	 *
339
	 * @return string
340
	 */
341 20
	private function buildFromRootToFolder($fileSource) {
342 20
		$resource = $this->getResourceFromId($fileSource);
343 20
		$fromRootToFolder = $resource->getPath() . '/';
344
345 20
		return $fromRootToFolder;
346
	}
347
348
	/**
349
	 * Returns the path which goes from the file, up to the user folder, based on a path:
350
	 * parent_folder/current_folder/my_file
351
	 *
352
	 * getPath() on the file produces a path like:
353
	 * '/userId/files/my_folder/my_sub_folder/my_file'
354
	 *
355
	 * So we substract the path to the user folder, giving us a relative path
356
	 * 'my_folder/my_sub_folder'
357
	 *
358
	 * @param string $fullPath
359
	 *
360
	 * @return string
361
	 */
362 17
	private function getRelativePath($fullPath) {
363 17
		$folderPath = $this->userFolder->getPath() . '/';
364 17
		$origShareRelPath = str_replace($folderPath, '', $fullPath);
365
366 17
		return $origShareRelPath;
367
	}
368
369
}
370