Passed
Push — master ( 692da9...451f70 )
by Robin
13:23 queued 15s
created

MountPoint::getMountProvider()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Arthur Schiwon <[email protected]>
6
 * @author Björn Schießle <[email protected]>
7
 * @author Christoph Wurst <[email protected]>
8
 * @author Georg Ehrke <[email protected]>
9
 * @author Jörn Friedrich Dreyer <[email protected]>
10
 * @author Morris Jobke <[email protected]>
11
 * @author Robin Appelman <[email protected]>
12
 * @author Robin McCorkell <[email protected]>
13
 * @author Roeland Jago Douma <[email protected]>
14
 * @author Vincent Petry <[email protected]>
15
 *
16
 * @license AGPL-3.0
17
 *
18
 * This code is free software: you can redistribute it and/or modify
19
 * it under the terms of the GNU Affero General Public License, version 3,
20
 * as published by the Free Software Foundation.
21
 *
22
 * This program is distributed in the hope that it will be useful,
23
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25
 * GNU Affero General Public License for more details.
26
 *
27
 * You should have received a copy of the GNU Affero General Public License, version 3,
28
 * along with this program. If not, see <http://www.gnu.org/licenses/>
29
 *
30
 */
31
namespace OC\Files\Mount;
32
33
use OC\Files\Filesystem;
34
use OC\Files\Storage\Storage;
35
use OC\Files\Storage\StorageFactory;
36
use OCP\Files\Mount\IMountPoint;
37
use OCP\Files\Storage\IStorageFactory;
38
use OCP\ILogger;
39
40
class MountPoint implements IMountPoint {
41
	/**
42
	 * @var \OC\Files\Storage\Storage|null $storage
43
	 */
44
	protected $storage = null;
45
	protected $class;
46
	protected $storageId;
47
	protected $rootId = null;
48
49
	/**
50
	 * Configuration options for the storage backend
51
	 *
52
	 * @var array
53
	 */
54
	protected $arguments = [];
55
	protected $mountPoint;
56
57
	/**
58
	 * Mount specific options
59
	 *
60
	 * @var array
61
	 */
62
	protected $mountOptions = [];
63
64
	/**
65
	 * @var \OC\Files\Storage\StorageFactory $loader
66
	 */
67
	private $loader;
68
69
	/**
70
	 * Specified whether the storage is invalid after failing to
71
	 * instantiate it.
72
	 *
73
	 * @var bool
74
	 */
75
	private $invalidStorage = false;
76
77
	/** @var int|null */
78
	protected $mountId;
79
80
	/** @var string */
81
	protected $mountProvider;
82
83
	/**
84
	 * @param string|\OC\Files\Storage\Storage $storage
85
	 * @param string $mountpoint
86
	 * @param array $arguments (optional) configuration for the storage backend
87
	 * @param \OCP\Files\Storage\IStorageFactory $loader
88
	 * @param array $mountOptions mount specific options
89
	 * @param int|null $mountId
90
	 * @param string|null $mountProvider
91
	 * @throws \Exception
92
	 */
93
	public function __construct(
94
		$storage,
95
		string $mountpoint,
96
		array $arguments = null,
97
		IStorageFactory $loader = null,
98
		array $mountOptions = null,
99
		int $mountId = null,
100
		string $mountProvider = null
101
	) {
102
		if (is_null($arguments)) {
103
			$arguments = [];
104
		}
105
		if (is_null($loader)) {
106
			$this->loader = new StorageFactory();
107
		} else {
108
			$this->loader = $loader;
0 ignored issues
show
Documentation Bug introduced by
$loader is of type OCP\Files\Storage\IStorageFactory, but the property $loader was declared to be of type OC\Files\Storage\StorageFactory. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
109
		}
110
111
		if (!is_null($mountOptions)) {
112
			$this->mountOptions = $mountOptions;
113
		}
114
115
		$mountpoint = $this->formatPath($mountpoint);
116
		$this->mountPoint = $mountpoint;
117
		$this->mountId = $mountId;
118
		if ($storage instanceof Storage) {
119
			$this->class = get_class($storage);
120
			$this->storage = $this->loader->wrap($this, $storage);
0 ignored issues
show
Bug introduced by
The method wrap() does not exist on OCP\Files\Storage\IStorageFactory. Since it exists in all sub-types, consider adding an abstract or default implementation to OCP\Files\Storage\IStorageFactory. ( Ignorable by Annotation )

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

120
			/** @scrutinizer ignore-call */ 
121
   $this->storage = $this->loader->wrap($this, $storage);
Loading history...
121
		} else {
122
			// Update old classes to new namespace
123
			if (strpos($storage, 'OC_Filestorage_') !== false) {
124
				$storage = '\OC\Files\Storage\\' . substr($storage, 15);
125
			}
126
			$this->class = $storage;
127
			$this->arguments = $arguments;
128
		}
129
		if ($mountProvider) {
130
			if (strlen($mountProvider) > 128) {
131
				throw new \Exception("Mount provider $mountProvider name exceeds the limit of 128 characters");
132
			}
133
		}
134
		$this->mountProvider = $mountProvider ?? '';
135
	}
136
137
	/**
138
	 * get complete path to the mount point, relative to data/
139
	 *
140
	 * @return string
141
	 */
142
	public function getMountPoint() {
143
		return $this->mountPoint;
144
	}
145
146
	/**
147
	 * Sets the mount point path, relative to data/
148
	 *
149
	 * @param string $mountPoint new mount point
150
	 */
151
	public function setMountPoint($mountPoint) {
152
		$this->mountPoint = $this->formatPath($mountPoint);
153
	}
154
155
	/**
156
	 * create the storage that is mounted
157
	 */
158
	private function createStorage() {
159
		if ($this->invalidStorage) {
160
			return;
161
		}
162
163
		if (class_exists($this->class)) {
164
			try {
165
				$class = $this->class;
166
				// prevent recursion by setting the storage before applying wrappers
167
				$this->storage = new $class($this->arguments);
168
				$this->storage = $this->loader->wrap($this, $this->storage);
169
			} catch (\Exception $exception) {
170
				$this->storage = null;
171
				$this->invalidStorage = true;
172
				if ($this->mountPoint === '/') {
173
					// the root storage could not be initialized, show the user!
174
					throw new \Exception('The root storage could not be initialized. Please contact your local administrator.', $exception->getCode(), $exception);
175
				} else {
176
					\OC::$server->getLogger()->logException($exception, ['level' => ILogger::ERROR]);
0 ignored issues
show
Deprecated Code introduced by
The constant OCP\ILogger::ERROR has been deprecated: 20.0.0 ( Ignorable by Annotation )

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

176
					\OC::$server->getLogger()->logException($exception, ['level' => /** @scrutinizer ignore-deprecated */ ILogger::ERROR]);

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
177
				}
178
				return;
179
			}
180
		} else {
181
			\OCP\Util::writeLog('core', 'storage backend ' . $this->class . ' not found', ILogger::ERROR);
0 ignored issues
show
Deprecated Code introduced by
The constant OCP\ILogger::ERROR has been deprecated: 20.0.0 ( Ignorable by Annotation )

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

181
			\OCP\Util::writeLog('core', 'storage backend ' . $this->class . ' not found', /** @scrutinizer ignore-deprecated */ ILogger::ERROR);

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
182
			$this->invalidStorage = true;
183
			return;
184
		}
185
	}
186
187
	/**
188
	 * @return \OC\Files\Storage\Storage|null
189
	 */
190
	public function getStorage() {
191
		if (is_null($this->storage)) {
192
			$this->createStorage();
193
		}
194
		return $this->storage;
195
	}
196
197
	/**
198
	 * @return string
199
	 */
200
	public function getStorageId() {
201
		if (!$this->storageId) {
202
			if (is_null($this->storage)) {
203
				$storage = $this->createStorage(); //FIXME: start using exceptions
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $storage is correct as $this->createStorage() targeting OC\Files\Mount\MountPoint::createStorage() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
204
				if (is_null($storage)) {
0 ignored issues
show
introduced by
The condition is_null($storage) is always true.
Loading history...
205
					return null;
206
				}
207
208
				$this->storage = $storage;
209
			}
210
			$this->storageId = $this->storage->getId();
211
			if (strlen($this->storageId) > 64) {
212
				$this->storageId = md5($this->storageId);
213
			}
214
		}
215
		return $this->storageId;
216
	}
217
218
	/**
219
	 * @return int
220
	 */
221
	public function getNumericStorageId() {
222
		return $this->getStorage()->getStorageCache()->getNumericId();
223
	}
224
225
	/**
226
	 * @param string $path
227
	 * @return string
228
	 */
229
	public function getInternalPath($path) {
230
		$path = Filesystem::normalizePath($path, true, false, true);
231
		if ($this->mountPoint === $path or $this->mountPoint . '/' === $path) {
232
			$internalPath = '';
233
		} else {
234
			$internalPath = substr($path, strlen($this->mountPoint));
235
		}
236
		// substr returns false instead of an empty string, we always want a string
237
		return (string)$internalPath;
238
	}
239
240
	/**
241
	 * @param string $path
242
	 * @return string
243
	 */
244
	private function formatPath($path) {
245
		$path = Filesystem::normalizePath($path);
246
		if (strlen($path) > 1) {
247
			$path .= '/';
248
		}
249
		return $path;
250
	}
251
252
	/**
253
	 * @param callable $wrapper
254
	 */
255
	public function wrapStorage($wrapper) {
256
		$storage = $this->getStorage();
257
		// storage can be null if it couldn't be initialized
258
		if ($storage != null) {
259
			$this->storage = $wrapper($this->mountPoint, $storage, $this);
260
		}
261
	}
262
263
	/**
264
	 * Get a mount option
265
	 *
266
	 * @param string $name Name of the mount option to get
267
	 * @param mixed $default Default value for the mount option
268
	 * @return mixed
269
	 */
270
	public function getOption($name, $default) {
271
		return isset($this->mountOptions[$name]) ? $this->mountOptions[$name] : $default;
272
	}
273
274
	/**
275
	 * Get all options for the mount
276
	 *
277
	 * @return array
278
	 */
279
	public function getOptions() {
280
		return $this->mountOptions;
281
	}
282
283
	/**
284
	 * Get the file id of the root of the storage
285
	 *
286
	 * @return int
287
	 */
288
	public function getStorageRootId() {
289
		if (is_null($this->rootId) || $this->rootId === -1) {
290
			$storage = $this->getStorage();
291
			// if we can't create the storage return -1 as root id, this is then handled the same as if the root isn't scanned yet
292
			if ($storage === null) {
293
				$this->rootId = -1;
294
			} else {
295
				$this->rootId = (int)$storage->getCache()->getId('');
296
			}
297
		}
298
		return $this->rootId;
299
	}
300
301
	public function getMountId() {
302
		return $this->mountId;
303
	}
304
305
	public function getMountType() {
306
		return '';
307
	}
308
309
	public function getMountProvider(): string {
310
		return $this->mountProvider;
311
	}
312
}
313