Passed
Push — master ( 39bde9...53659e )
by
unknown
02:47
created

Environment::getNodeFromUserFolder()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 10
nc 3
nop 1
dl 0
loc 14
rs 9.9332
c 0
b 0
f 0
1
<?php
2
/**
3
 * Nextcloud - Gallery
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 2017
12
 * @copyright Authors of \OCA\Files_Sharing\Helper 2014-2016
13
 */
14
15
namespace OCA\Gallery\Environment;
16
17
use OCP\IUserManager;
0 ignored issues
show
Bug introduced by
The type OCP\IUserManager was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
18
use OCP\Share;
0 ignored issues
show
Bug introduced by
The type OCP\Share was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
19
use OCP\Share\IShare;
0 ignored issues
show
Bug introduced by
The type OCP\Share\IShare was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
20
use OCP\ILogger;
0 ignored issues
show
Bug introduced by
The type OCP\ILogger was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
21
use OCP\Files\IRootFolder;
0 ignored issues
show
Bug introduced by
The type OCP\Files\IRootFolder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
22
use OCP\Files\Folder;
0 ignored issues
show
Bug introduced by
The type OCP\Files\Folder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
23
use OCP\Files\Node;
0 ignored issues
show
Bug introduced by
The type OCP\Files\Node was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
24
use OCP\Files\File;
0 ignored issues
show
Bug introduced by
The type OCP\Files\File was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
25
use OCP\Files\NotFoundException;
0 ignored issues
show
Bug introduced by
The type OCP\Files\NotFoundException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
26
27
/**
28
 * Builds the environment so that the services have access to the files and folders' owner
29
 *
30
 * @package OCA\Gallery\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 File|Folder
64
	 */
65
	private $sharedNode;
66
	/**
67
	 * @var IRootFolder
68
	 */
69
	private $rootFolder;
70
	/**
71
	 * @var ILogger
72
	 */
73
	private $logger;
74
	/**
75
	 * The path to the userFolder for users with accounts: /userId/files
76
	 *
77
	 * For public folders, it's the path from the shared folder to the root folder in the original
78
	 * owner's filesystem: /userId/files/parent_folder/shared_folder
79
	 *
80
	 * @var string
81
	 */
82
	private $fromRootToFolder;
83
	/**
84
	 * The name of the shared folder
85
	 *
86
	 * @var string
87
	 */
88
	private $folderName;
89
	/**
90
	 * @var string|null
91
	 */
92
	private $sharePassword;
93
94
	/***
95
	 * Constructor
96
	 *
97
	 * @param string $appName
98
	 * @param string|null $userId
99
	 * @param Folder|null $userFolder
100
	 * @param IUserManager $userManager
101
	 * @param IRootFolder $rootFolder
102
	 * @param ILogger $logger
103
	 */
104
	public function __construct(
105
		$appName,
106
		$userId,
107
		$userFolder,
108
		IUserManager $userManager,
109
		IRootFolder $rootFolder,
110
		ILogger $logger
111
	) {
112
		$this->appName = $appName;
113
		$this->userId = $userId;
114
		$this->userFolder = $userFolder;
115
		$this->userManager = $userManager;
116
		$this->rootFolder = $rootFolder;
117
		$this->logger = $logger;
118
	}
119
120
	/**
121
	 * Creates the environment based on the share the token links to
122
	 *
123
	 * @param IShare $share
124
	 */
125
	public function setTokenBasedEnv($share) {
126
		$origShareOwnerId = $share->getShareOwner();
127
		$this->userFolder = $this->rootFolder->getUserFolder($origShareOwnerId);
128
129
		$this->sharedNodeId = $share->getNodeId();
130
		$this->sharedNode = $share->getNode();
131
		$this->fromRootToFolder = $this->buildFromRootToFolder($this->sharedNodeId);
132
133
		$this->folderName = $share->getTarget();
134
		$this->userId = $origShareOwnerId;
135
		$this->sharePassword = $share->getPassword();
136
	}
137
138
	/**
139
	 * Creates the environment for a logged-in user
140
	 *
141
	 * userId and userFolder are already known, we define fromRootToFolder
142
	 * so that the services can use one method to have access to resources
143
	 * without having to know whether they're private or public
144
	 */
145
	public function setStandardEnv() {
146
		$this->fromRootToFolder = $this->userFolder->getPath() . '/';
0 ignored issues
show
Bug introduced by
The method getPath() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

146
		$this->fromRootToFolder = $this->userFolder->/** @scrutinizer ignore-call */ getPath() . '/';

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
147
	}
148
149
	/**
150
	 * Returns true if the environment has been setup using a token
151
	 *
152
	 * @return bool
153
	 */
154
	public function isTokenBasedEnv() {
155
		return !empty($this->sharedNodeId);
156
	}
157
158
	/**
159
	 * Returns the Node based on a path starting from the virtual root
160
	 *
161
	 * @param string $subPath
162
	 *
163
	 * @return File|Folder
164
	 */
165
	public function getNodeFromVirtualRoot($subPath) {
166
		$relativePath = $this->getRelativePath($this->fromRootToFolder);
167
		$path = $relativePath . '/' . $subPath;
168
		$node = $this->getNodeFromUserFolder($path);
169
170
		return $this->getResourceFromId($node->getId());
171
	}
172
173
	/**
174
	 * Returns the Node based on a path starting from the files' owner user folder
175
	 *
176
	 * When logged in, this is the current user's user folder
177
	 * When visiting a link, this is the sharer's user folder
178
	 *
179
	 * @param string $path
180
	 *
181
	 * @return File|Folder
182
	 *
183
	 * @throws NotFoundEnvException
184
	 */
185
	public function getNodeFromUserFolder($path) {
186
		$folder = $this->userFolder;
187
		if ($folder === null) {
188
			throw new NotFoundEnvException("Could not access the user's folder");
189
		} else {
190
			try {
191
				$node = $folder->get($path);
192
			} catch (NotFoundException $exception) {
193
				$message = 'Could not find anything at: ' . $exception->getMessage();
194
				throw new NotFoundEnvException($message);
195
			}
196
		}
197
198
		return $node;
199
	}
200
201
	/**
202
	 * Returns the resource identified by the given ID
203
	 *
204
	 * @param int $resourceId
205
	 *
206
	 * @return Node
207
	 *
208
	 * @throws NotFoundEnvException
209
	 */
210
	public function getResourceFromId($resourceId) {
211
		if ($this->isTokenBasedEnv()) {
212
			if ($this->sharedNode->getType() === 'dir') {
213
				$resource = $this->getResourceFromFolderAndId($this->sharedNode, $resourceId);
214
			} else {
215
				$resource = $this->sharedNode;
216
			}
217
		} else {
218
			$resource = $this->getResourceFromFolderAndId($this->userFolder, $resourceId);
219
		}
220
221
		return $resource;
222
	}
223
224
	/**
225
	 * Returns the shared node
226
	 *
227
	 * @return File|Folder
228
	 */
229
	public function getSharedNode() {
230
		return $this->getResourceFromId($this->sharedNodeId);
231
	}
232
233
	/**
234
	 * Returns the virtual root where the user lands after logging in or when following a link
235
	 *
236
	 * @return Folder
237
	 * @throws NotFoundEnvException
238
	 */
239
	public function getVirtualRootFolder() {
240
		$rootFolder = $this->userFolder;
241
		if ($this->isTokenBasedEnv()) {
242
			$node = $this->getSharedNode();
243
			$nodeType = $node->getType();
244
			if ($nodeType === 'dir') {
245
				$rootFolder = $node;
246
			} else {
247
				throw new NotFoundEnvException($node->getPath() . ' is not a folder');
248
			}
249
		}
250
251
		return $rootFolder;
252
	}
253
254
	/**
255
	 * Returns the userId of the currently logged-in user or the sharer
256
	 *
257
	 * @return string
258
	 */
259
	public function getUserId() {
260
		return $this->userId;
261
	}
262
263
	/**
264
	 * Returns the name of the user sharing files publicly
265
	 *
266
	 * @return string
267
	 * @throws NotFoundEnvException
268
	 */
269
	public function getDisplayName() {
270
		$user = null;
271
		$userId = $this->userId;
272
273
		if (isset($userId)) {
274
			$user = $this->userManager->get($userId);
275
		}
276
		if ($user === null) {
277
			throw new NotFoundEnvException('Could not find user');
278
		}
279
280
		return $user->getDisplayName();
281
	}
282
283
	/**
284
	 * Returns the name of shared folder
285
	 *
286
	 * @return string
287
	 */
288
	public function getSharedFolderName() {
289
		return trim($this->folderName, '//');
290
	}
291
292
	/**
293
	 * Returns the password for the share, if there is one
294
	 *
295
	 * @return string|null
296
	 */
297
	public function getSharePassword() {
298
		return $this->sharePassword;
299
	}
300
301
	/**
302
	 * Returns the path which goes from the file, up to the user folder, based on a node:
303
	 * parent_folder/current_folder/my_file
304
	 *
305
	 * This is used for the preview system, which needs a full path
306
	 *
307
	 * getPath() on the file produces a path like:
308
	 * '/userId/files/my_folder/my_sub_folder/my_file'
309
	 *
310
	 * So we substract the path to the folder, giving us a relative path
311
	 * 'my_folder/my_sub_folder/my_file'
312
	 *
313
	 * @param Node $file
314
	 *
315
	 * @return string
316
	 */
317
	public function getPathFromUserFolder($file) {
318
		$path = $file->getPath();
319
320
		return $this->getRelativePath($path);
321
	}
322
323
	/**
324
	 * Returns the path which goes from the file, up to the root folder of the Gallery:
325
	 * current_folder/my_file
326
	 *
327
	 * That root folder changes when folders are shared publicly
328
	 *
329
	 * @param File|Folder|Node $node
330
	 *
331
	 * @return string
332
	 */
333
	public function getPathFromVirtualRoot($node) {
334
		$path = $node->getPath();
335
		$nodeType = $node->getType();
336
337
		// Needed because fromRootToFolder always ends with a slash
338
		if ($nodeType === 'dir') {
339
			$path .= '/';
340
		}
341
342
		$path = str_replace($this->fromRootToFolder, '', $path);
343
		$path = rtrim($path, '/');
344
345
		return $path;
346
	}
347
348
	/**
349
	 * Returns the resource found in a specific folder and identified by the given ID
350
	 *
351
	 * @param Folder $folder
352
	 * @param int $resourceId
353
	 *
354
	 * @return Node
355
	 * @throws NotFoundEnvException
356
	 */
357
	private function getResourceFromFolderAndId($folder, $resourceId) {
358
		$resourcesArray = $folder->getById($resourceId);
359
360
		if (!isset($resourcesArray[0])) {
361
			throw new NotFoundEnvException('Could not locate node linked to ID: ' . $resourceId);
362
		}
363
364
		return $resourcesArray[0];
365
	}
366
367
	/**
368
	 * Returns the path from the shared folder to the root folder in the original
369
	 * owner's filesystem: /userId/files/parent_folder/shared_folder
370
	 *
371
	 * This cannot be calculated with paths and IDs, the share's file source is required
372
	 *
373
	 * @param string $fileSource
374
	 *
375
	 * @return string
376
	 */
377
	private function buildFromRootToFolder($fileSource) {
378
		$resource = $this->getResourceFromId($fileSource);
0 ignored issues
show
Bug introduced by
$fileSource of type string is incompatible with the type integer expected by parameter $resourceId of OCA\Gallery\Environment\...nt::getResourceFromId(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

378
		$resource = $this->getResourceFromId(/** @scrutinizer ignore-type */ $fileSource);
Loading history...
379
		$fromRootToFolder = $resource->getPath() . '/';
380
381
		return $fromRootToFolder;
382
	}
383
384
	/**
385
	 * Returns the path which goes from the file, up to the user folder, based on a path:
386
	 * parent_folder/current_folder/my_file
387
	 *
388
	 * getPath() on the file produces a path like:
389
	 * '/userId/files/my_folder/my_sub_folder/my_file'
390
	 *
391
	 * So we substract the path to the user folder, giving us a relative path
392
	 * 'my_folder/my_sub_folder'
393
	 *
394
	 * @param string $fullPath
395
	 *
396
	 * @return string
397
	 */
398
	private function getRelativePath($fullPath) {
399
		$folderPath = $this->userFolder->getPath() . '/';
400
		$origShareRelPath = str_replace($folderPath, '', $fullPath);
401
402
		return $origShareRelPath;
403
	}
404
405
}
406