Completed
Push — master ( e11197...b33ceb )
by Lukas
20:36 queued 08:07
created

Root   B

Complexity

Total Complexity 40

Size/Duplication

Total Lines 337
Duplicated Lines 3.56 %

Coupling/Cohesion

Components 3
Dependencies 14

Importance

Changes 0
Metric Value
dl 12
loc 337
rs 8.2608
c 0
b 0
f 0
wmc 40
lcom 3
cbo 14

34 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 15 1
A getUser() 0 3 1
A listen() 0 3 1
A removeListener() 0 3 1
A emit() 0 3 1
A mount() 0 4 1
A getMount() 0 3 1
A getMountsIn() 0 3 1
A getMountByStorageId() 0 3 1
A getMountByNumericStorageId() 0 3 1
A unMount() 0 3 1
A get() 0 14 3
A rename() 0 3 1
A delete() 0 3 1
A copy() 0 3 1
A touch() 0 3 1
A getStorage() 0 3 1
A getPath() 0 3 1
A getInternalPath() 0 3 1
A getId() 0 3 1
A stat() 0 3 1
A getMTime() 0 3 1
A getSize() 0 3 1
A getEtag() 0 3 1
A getPermissions() 0 3 1
A isReadable() 0 3 1
A isUpdateable() 0 3 1
A isDeletable() 0 3 1
A isShareable() 0 3 1
A getParent() 0 3 1
A getName() 0 3 1
B getUserFolder() 12 36 5
A clearCache() 0 3 1
A getUserMountCache() 0 3 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Root often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Root, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Bernhard Posselt <[email protected]>
6
 * @author Joas Schilling <[email protected]>
7
 * @author Jörn Friedrich Dreyer <[email protected]>
8
 * @author Morris Jobke <[email protected]>
9
 * @author Robin Appelman <[email protected]>
10
 * @author Roeland Jago Douma <[email protected]>
11
 * @author Stefan Weil <[email protected]>
12
 *
13
 * @license AGPL-3.0
14
 *
15
 * This code is free software: you can redistribute it and/or modify
16
 * it under the terms of the GNU Affero General Public License, version 3,
17
 * as published by the Free Software Foundation.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
 * GNU Affero General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU Affero General Public License, version 3,
25
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
26
 *
27
 */
28
29
namespace OC\Files\Node;
30
31
use OC\Cache\CappedMemoryCache;
32
use OC\Files\Mount\Manager;
33
use OC\Files\Mount\MountPoint;
34
use OCP\Files\Config\IUserMountCache;
35
use OCP\Files\NotFoundException;
36
use OCP\Files\NotPermittedException;
37
use OC\Hooks\PublicEmitter;
38
use OCP\Files\IRootFolder;
39
use OCP\ILogger;
40
use OCP\IUserManager;
41
42
/**
43
 * Class Root
44
 *
45
 * Hooks available in scope \OC\Files
46
 * - preWrite(\OCP\Files\Node $node)
47
 * - postWrite(\OCP\Files\Node $node)
48
 * - preCreate(\OCP\Files\Node $node)
49
 * - postCreate(\OCP\Files\Node $node)
50
 * - preDelete(\OCP\Files\Node $node)
51
 * - postDelete(\OCP\Files\Node $node)
52
 * - preTouch(\OC\FilesP\Node $node, int $mtime)
53
 * - postTouch(\OCP\Files\Node $node)
54
 * - preCopy(\OCP\Files\Node $source, \OCP\Files\Node $target)
55
 * - postCopy(\OCP\Files\Node $source, \OCP\Files\Node $target)
56
 * - preRename(\OCP\Files\Node $source, \OCP\Files\Node $target)
57
 * - postRename(\OCP\Files\Node $source, \OCP\Files\Node $target)
58
 *
59
 * @package OC\Files\Node
60
 */
61
class Root extends Folder implements IRootFolder {
62
	/** @var Manager */
63
	private $mountManager;
64
	/** @var PublicEmitter */
65
	private $emitter;
66
	/** @var null|\OC\User\User */
67
	private $user;
68
	/** @var CappedMemoryCache */
69
	private $userFolderCache;
70
	/** @var IUserMountCache */
71
	private $userMountCache;
72
	/** @var ILogger */
73
	private $logger;
74
	/** @var IUserManager */
75
	private $userManager;
76
77
	/**
78
	 * @param \OC\Files\Mount\Manager $manager
79
	 * @param \OC\Files\View $view
80
	 * @param \OC\User\User|null $user
81
	 * @param IUserMountCache $userMountCache
82
	 * @param ILogger $logger
83
	 * @param IUserManager $userManager
84
	 */
85
	public function __construct($manager,
86
								$view,
87
								$user,
88
								IUserMountCache $userMountCache,
89
								ILogger $logger,
90
								IUserManager $userManager) {
91
		parent::__construct($this, $view, '');
92
		$this->mountManager = $manager;
93
		$this->user = $user;
94
		$this->emitter = new PublicEmitter();
95
		$this->userFolderCache = new CappedMemoryCache();
96
		$this->userMountCache = $userMountCache;
97
		$this->logger = $logger;
98
		$this->userManager = $userManager;
99
	}
100
101
	/**
102
	 * Get the user for which the filesystem is setup
103
	 *
104
	 * @return \OC\User\User
105
	 */
106
	public function getUser() {
107
		return $this->user;
108
	}
109
110
	/**
111
	 * @param string $scope
112
	 * @param string $method
113
	 * @param callable $callback
114
	 */
115
	public function listen($scope, $method, callable $callback) {
116
		$this->emitter->listen($scope, $method, $callback);
117
	}
118
119
	/**
120
	 * @param string $scope optional
121
	 * @param string $method optional
122
	 * @param callable $callback optional
123
	 */
124
	public function removeListener($scope = null, $method = null, callable $callback = null) {
125
		$this->emitter->removeListener($scope, $method, $callback);
126
	}
127
128
	/**
129
	 * @param string $scope
130
	 * @param string $method
131
	 * @param Node[] $arguments
132
	 */
133
	public function emit($scope, $method, $arguments = array()) {
134
		$this->emitter->emit($scope, $method, $arguments);
135
	}
136
137
	/**
138
	 * @param \OC\Files\Storage\Storage $storage
139
	 * @param string $mountPoint
140
	 * @param array $arguments
141
	 */
142
	public function mount($storage, $mountPoint, $arguments = array()) {
143
		$mount = new MountPoint($storage, $mountPoint, $arguments);
144
		$this->mountManager->addMount($mount);
145
	}
146
147
	/**
148
	 * @param string $mountPoint
149
	 * @return \OC\Files\Mount\MountPoint
150
	 */
151
	public function getMount($mountPoint) {
152
		return $this->mountManager->find($mountPoint);
153
	}
154
155
	/**
156
	 * @param string $mountPoint
157
	 * @return \OC\Files\Mount\MountPoint[]
158
	 */
159
	public function getMountsIn($mountPoint) {
160
		return $this->mountManager->findIn($mountPoint);
161
	}
162
163
	/**
164
	 * @param string $storageId
165
	 * @return \OC\Files\Mount\MountPoint[]
166
	 */
167
	public function getMountByStorageId($storageId) {
168
		return $this->mountManager->findByStorageId($storageId);
169
	}
170
171
	/**
172
	 * @param int $numericId
173
	 * @return MountPoint[]
174
	 */
175
	public function getMountByNumericStorageId($numericId) {
176
		return $this->mountManager->findByNumericId($numericId);
177
	}
178
179
	/**
180
	 * @param \OC\Files\Mount\MountPoint $mount
181
	 */
182
	public function unMount($mount) {
183
		$this->mountManager->remove($mount);
0 ignored issues
show
Bug introduced by
The method remove() does not exist on OC\Files\Mount\Manager. Did you maybe mean removeMount()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
184
	}
185
186
	/**
187
	 * @param string $path
188
	 * @throws \OCP\Files\NotFoundException
189
	 * @throws \OCP\Files\NotPermittedException
190
	 * @return string
191
	 */
192
	public function get($path) {
193
		$path = $this->normalizePath($path);
194
		if ($this->isValidPath($path)) {
195
			$fullPath = $this->getFullPath($path);
196
			$fileInfo = $this->view->getFileInfo($fullPath);
197
			if ($fileInfo) {
198
				return $this->createNode($fullPath, $fileInfo);
199
			} else {
200
				throw new NotFoundException($path);
201
			}
202
		} else {
203
			throw new NotPermittedException();
204
		}
205
	}
206
207
	//most operations can't be done on the root
208
209
	/**
210
	 * @param string $targetPath
211
	 * @throws \OCP\Files\NotPermittedException
212
	 * @return \OC\Files\Node\Node
213
	 */
214
	public function rename($targetPath) {
0 ignored issues
show
Unused Code introduced by
The parameter $targetPath is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
215
		throw new NotPermittedException();
216
	}
217
218
	public function delete() {
219
		throw new NotPermittedException();
220
	}
221
222
	/**
223
	 * @param string $targetPath
224
	 * @throws \OCP\Files\NotPermittedException
225
	 * @return \OC\Files\Node\Node
226
	 */
227
	public function copy($targetPath) {
228
		throw new NotPermittedException();
229
	}
230
231
	/**
232
	 * @param int $mtime
233
	 * @throws \OCP\Files\NotPermittedException
234
	 */
235
	public function touch($mtime = null) {
236
		throw new NotPermittedException();
237
	}
238
239
	/**
240
	 * @return \OC\Files\Storage\Storage
241
	 * @throws \OCP\Files\NotFoundException
242
	 */
243
	public function getStorage() {
244
		throw new NotFoundException();
245
	}
246
247
	/**
248
	 * @return string
249
	 */
250
	public function getPath() {
251
		return '/';
252
	}
253
254
	/**
255
	 * @return string
256
	 */
257
	public function getInternalPath() {
258
		return '';
259
	}
260
261
	/**
262
	 * @return int
263
	 */
264
	public function getId() {
265
		return null;
266
	}
267
268
	/**
269
	 * @return array
270
	 */
271
	public function stat() {
272
		return null;
273
	}
274
275
	/**
276
	 * @return int
277
	 */
278
	public function getMTime() {
279
		return null;
280
	}
281
282
	/**
283
	 * @return int
284
	 */
285
	public function getSize() {
286
		return null;
287
	}
288
289
	/**
290
	 * @return string
291
	 */
292
	public function getEtag() {
293
		return null;
294
	}
295
296
	/**
297
	 * @return int
298
	 */
299
	public function getPermissions() {
300
		return \OCP\Constants::PERMISSION_CREATE;
301
	}
302
303
	/**
304
	 * @return bool
305
	 */
306
	public function isReadable() {
307
		return false;
308
	}
309
310
	/**
311
	 * @return bool
312
	 */
313
	public function isUpdateable() {
314
		return false;
315
	}
316
317
	/**
318
	 * @return bool
319
	 */
320
	public function isDeletable() {
321
		return false;
322
	}
323
324
	/**
325
	 * @return bool
326
	 */
327
	public function isShareable() {
328
		return false;
329
	}
330
331
	/**
332
	 * @return Node
333
	 * @throws \OCP\Files\NotFoundException
334
	 */
335
	public function getParent() {
336
		throw new NotFoundException();
337
	}
338
339
	/**
340
	 * @return string
341
	 */
342
	public function getName() {
343
		return '';
344
	}
345
346
	/**
347
	 * Returns a view to user's files folder
348
	 *
349
	 * @param String $userId user ID
350
	 * @return \OCP\Files\Folder
351
	 * @throws \OC\User\NoUserException
352
	 */
353
	public function getUserFolder($userId) {
354
		$userObject = $this->userManager->get($userId);
355
356 View Code Duplication
		if (is_null($userObject)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
357
			$this->logger->error(
358
				sprintf(
359
					'Backends provided no user object for %s',
360
					$userId
361
				),
362
				[
363
					'app' => 'files',
364
				]
365
			);
366
			throw new \OC\User\NoUserException('Backends provided no user object');
367
		}
368
369
		$userId = $userObject->getUID();
370
371
		if (!$this->userFolderCache->hasKey($userId)) {
372
			\OC\Files\Filesystem::initMountPoints($userId);
373
374
			try {
375
				$folder = $this->get('/' . $userId . '/files');
376
			} catch (NotFoundException $e) {
377
				if (!$this->nodeExists('/' . $userId)) {
378
					$this->newFolder('/' . $userId);
379
				}
380
				$folder = $this->newFolder('/' . $userId . '/files');
381
				\OC_Util::copySkeleton($userId, $folder);
382
			}
383
384
			$this->userFolderCache->set($userId, $folder);
385
		}
386
387
		return $this->userFolderCache->get($userId);
388
	}
389
390
	public function clearCache() {
391
		$this->userFolderCache = new CappedMemoryCache();
392
	}
393
394
	public function getUserMountCache() {
395
		return $this->userMountCache;
396
	}
397
}
398