Completed
Pull Request — stable9 (#47)
by Olivier
08:46
created

Environment::setTokenBasedEnv()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 1

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 11
ccs 9
cts 9
cp 1
rs 9.4285
cc 1
eloc 8
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\Share\IShare;
20
use OCP\ILogger;
21
use OCP\Files\IRootFolder;
22
use OCP\Files\Folder;
23
use OCP\Files\Node;
24
use OCP\Files\File;
25
use OCP\Files\NotFoundException;
26
27
/**
28
 * Builds the environment so that the services have access to the files and folders' owner
29
 *
30
 * @package OCA\GalleryPlus\Environment
31
 */
32
class Environment {
33
34
	/**
35
	 * @var string
36
	 */
37
	private $appName;
38
	/**
39
	 * The userId of the logged-in user or the person sharing a folder publicly
40
	 *
41
	 * @var string
42
	 */
43
	private $userId;
44
	/**
45
	 * The userFolder of the logged-in user or the ORIGINAL owner of the files which are shared
46
	 * publicly
47
	 *
48
	 * A share needs to be tracked back to its original owner in order to be able to access the
49
	 * resource
50
	 *
51
	 * @var Folder|null
52
	 */
53
	private $userFolder;
54
	/**
55
	 * @var IUserManager
56
	 */
57
	private $userManager;
58
	/**
59
	 * @var int
60
	 */
61
	private $sharedNodeId;
62
	/**
63
	 * @var IRootFolder
64
	 */
65
	private $rootFolder;
66
	/**
67
	 * @var ILogger
68
	 */
69
	private $logger;
70
	/**
71
	 * The path to the userFolder for users with accounts: /userId/files
72
	 *
73
	 * For public folders, it's the path from the shared folder to the root folder in the original
74
	 * owner's filesystem: /userId/files/parent_folder/shared_folder
75
	 *
76
	 * @var string
77
	 */
78
	private $fromRootToFolder;
79
	/**
80
	 * The name of the shared folder
81
	 *
82
	 * @var string
83
	 */
84
	private $folderName;
85
	/**
86
	 * @var string|null
87
	 */
88
	private $sharePassword;
89
90
	/***
91
	 * Constructor
92
	 *
93
	 * @param string $appName
94
	 * @param string|null $userId
95
	 * @param Folder|null $userFolder
96
	 * @param IUserManager $userManager
97
	 * @param IRootFolder $rootFolder
98
	 * @param ILogger $logger
99
	 */
100 58
	public function __construct(
101
		$appName,
102
		$userId,
103
		$userFolder,
104
		IUserManager $userManager,
105
		IRootFolder $rootFolder,
106
		ILogger $logger
107
	) {
108 58
		$this->appName = $appName;
109 58
		$this->userId = $userId;
110 58
		$this->userFolder = $userFolder;
111 58
		$this->userManager = $userManager;
112 58
		$this->rootFolder = $rootFolder;
113 58
		$this->logger = $logger;
114 58
	}
115
116
	/**
117
	 * Creates the environment based on the share the token links to
118
	 *
119
	 * @param IShare $share
120
	 */
121 20
	public function setTokenBasedEnv($share) {
122 20
		$origShareOwnerId = $share->getShareOwner();
123 20
		$this->userFolder = $this->rootFolder->getUserFolder($origShareOwnerId);
124
125 20
		$this->sharedNodeId = $share->getNodeId();
126 20
		$this->fromRootToFolder = $this->buildFromRootToFolder($this->sharedNodeId);
127
128 20
		$this->folderName = $share->getTarget();
129 20
		$this->userId = $origShareOwnerId;
130 20
		$this->sharePassword = $share->getPassword();
131 20
	}
132
133
	/**
134
	 * Creates the environment for a logged-in user
135
	 *
136
	 * userId and userFolder are already known, we define fromRootToFolder
137
	 * so that the services can use one method to have access to resources
138
	 * without having to know whether they're private or public
139
	 */
140 29
	public function setStandardEnv() {
141 29
		$this->fromRootToFolder = $this->userFolder->getPath() . '/';
142 29
	}
143
144
	/**
145
	 * Returns the Node based on a path starting from the virtual root
146
	 *
147
	 * @param string $subPath
148
	 *
149
	 * @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...
150
	 */
151 8
	public function getNodeFromVirtualRoot($subPath) {
152 8
		$relativePath = $this->getRelativePath($this->fromRootToFolder);
153 8
		$path = $relativePath . '/' . $subPath;
154 8
		$node = $this->getNodeFromUserFolder($path);
155
156 8
		return $this->getResourceFromId($node->getId());
157
	}
158
159
	/**
160
	 * Returns the Node based on a path starting from the files' owner user folder
161
	 *
162
	 * When logged in, this is the current user's user folder
163
	 * When visiting a link, this is the sharer's user folder
164
	 *
165
	 * @param string $path
166
	 *
167
	 * @return File|Folder
168
	 *
169
	 * @throws NotFoundEnvException
170
	 */
171 11
	public function getNodeFromUserFolder($path) {
172 11
		$folder = $this->userFolder;
173 11
		if ($folder === null) {
174 1
			throw new NotFoundEnvException("Could not access the user's folder");
175
		} else {
176
			try {
177 10
				$node = $folder->get($path);
178 2
			} catch (NotFoundException $exception) {
179 2
				$message = 'Could not find anything at: ' . $exception->getMessage();
180 2
				throw new NotFoundEnvException($message);
181
			}
182
		}
183
184 10
		return $node;
185
	}
186
187
	/**
188
	 * Returns the resource identified by the given ID
189
	 *
190
	 * @param int $resourceId
191
	 *
192
	 * @return Node
193
	 *
194
	 * @throws NotFoundEnvException
195
	 */
196 36
	public function getResourceFromId($resourceId) {
197 36
		$resourcesArray = $this->userFolder->getById($resourceId);
198 36
		if ($resourcesArray[0] === null) {
199 3
			throw new NotFoundEnvException('Could not locate file linked to ID: ' . $resourceId);
200
		}
201
202 33
		return $resourcesArray[0];
203
	}
204
205
	/**
206
	 * Returns the shared node
207
	 *
208
	 * @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...
209
	 */
210 8
	public function getSharedNode() {
211 8
		return $this->getResourceFromId($this->sharedNodeId);
212
	}
213
214
	/**
215
	 * Returns the virtual root where the user lands after logging in or when following a link
216
	 *
217
	 * @return Folder
218
	 * @throws NotFoundEnvException
219
	 */
220 14
	public function getVirtualRootFolder() {
221 14
		$rootFolder = $this->userFolder;
222 14
		if (!empty($this->sharedNodeId)) {
223 4
			$node = $this->getSharedNode();
224 4
			$nodeType = $node->getType();
225 4
			if ($nodeType === 'dir') {
226 3
				$rootFolder = $node;
227
			} else {
228 1
				throw new NotFoundEnvException($node->getPath() . ' is not a folder');
229
			}
230
		}
231
232 13
		return $rootFolder;
233
	}
234
235
	/**
236
	 * Returns the userId of the currently logged-in user or the sharer
237
	 *
238
	 * @return string
239
	 */
240 9
	public function getUserId() {
241 9
		return $this->userId;
242
	}
243
244
	/**
245
	 * Returns the name of the user sharing files publicly
246
	 *
247
	 * @return string
248
	 * @throws NotFoundEnvException
249
	 */
250 2
	public function getDisplayName() {
251 2
		$user = null;
252 2
		$userId = $this->userId;
253
254 2
		if (isset($userId)) {
255 1
			$user = $this->userManager->get($userId);
256
		}
257 2
		if ($user === null) {
258 1
			throw new NotFoundEnvException('Could not find user');
259
		}
260
261 1
		return $user->getDisplayName();
262
	}
263
264
	/**
265
	 * Returns the name of shared folder
266
	 *
267
	 * @return string
268
	 */
269 1
	public function getSharedFolderName() {
270 1
		return trim($this->folderName, '//');
271
	}
272
273
	/**
274
	 * Returns the password for the share, if there is one
275
	 *
276
	 * @return string|null
277
	 */
278 1
	public function getSharePassword() {
279 1
		return $this->sharePassword;
280
	}
281
282
	/**
283
	 * Returns the path which goes from the file, up to the user folder, based on a node:
284
	 * parent_folder/current_folder/my_file
285
	 *
286
	 * This is used for the preview system, which needs a full path
287
	 *
288
	 * getPath() on the file produces a path like:
289
	 * '/userId/files/my_folder/my_sub_folder/my_file'
290
	 *
291
	 * So we substract the path to the folder, giving us a relative path
292
	 * 'my_folder/my_sub_folder/my_file'
293
	 *
294
	 * @param Node $file
295
	 *
296
	 * @return string
297
	 */
298 9
	public function getPathFromUserFolder($file) {
299 9
		$path = $file->getPath();
300
301 9
		return $this->getRelativePath($path);
302
	}
303
304
	/**
305
	 * Returns the path which goes from the file, up to the root folder of the Gallery:
306
	 * current_folder/my_file
307
	 *
308
	 * That root folder changes when folders are shared publicly
309
	 *
310
	 * @param File|Folder|Node $node
311
	 *
312
	 * @return string
313
	 */
314 10
	public function getPathFromVirtualRoot($node) {
315 10
		$path = $node->getPath();
316 10
		$nodeType = $node->getType();
317
318
		// Needed because fromRootToFolder always ends with a slash
319 10
		if ($nodeType === 'dir') {
320 8
			$path .= '/';
321
		}
322
323 10
		$path = str_replace($this->fromRootToFolder, '', $path);
324 10
		$path = rtrim($path, '/');
325
326 10
		return $path;
327
	}
328
329
	/**
330
	 * Returns the path from the shared folder to the root folder in the original
331
	 * owner's filesystem: /userId/files/parent_folder/shared_folder
332
	 *
333
	 * This cannot be calculated with paths and IDs, the share's file source is required
334
	 *
335
	 * @param string $fileSource
336
	 *
337
	 * @return string
338
	 */
339 20
	private function buildFromRootToFolder($fileSource) {
340 20
		$resource = $this->getResourceFromId($fileSource);
341 20
		$fromRootToFolder = $resource->getPath() . '/';
342
343 20
		return $fromRootToFolder;
344
	}
345
346
	/**
347
	 * Returns the path which goes from the file, up to the user folder, based on a path:
348
	 * parent_folder/current_folder/my_file
349
	 *
350
	 * getPath() on the file produces a path like:
351
	 * '/userId/files/my_folder/my_sub_folder/my_file'
352
	 *
353
	 * So we substract the path to the user folder, giving us a relative path
354
	 * 'my_folder/my_sub_folder'
355
	 *
356
	 * @param string $fullPath
357
	 *
358
	 * @return string
359
	 */
360 17
	private function getRelativePath($fullPath) {
361 17
		$folderPath = $this->userFolder->getPath() . '/';
362 17
		$origShareRelPath = str_replace($folderPath, '', $fullPath);
363
364 17
		return $origShareRelPath;
365
	}
366
367
}
368