Passed
Push — master ( a40db9...fb5987 )
by Julius
14:20 queued 12s
created

MountProviderCollection::addMountForUser()   B

Complexity

Conditions 6
Paths 18

Size

Total Lines 36
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 23
nc 18
nop 3
dl 0
loc 36
rs 8.9297
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Christoph Wurst <[email protected]>
6
 * @author Morris Jobke <[email protected]>
7
 * @author Robin Appelman <[email protected]>
8
 * @author Roeland Jago Douma <[email protected]>
9
 *
10
 * @license AGPL-3.0
11
 *
12
 * This code is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU Affero General Public License, version 3,
14
 * as published by the Free Software Foundation.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
 * GNU Affero General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Affero General Public License, version 3,
22
 * along with this program. If not, see <http://www.gnu.org/licenses/>
23
 *
24
 */
25
namespace OC\Files\Config;
26
27
use OC\Hooks\Emitter;
28
use OC\Hooks\EmitterTrait;
29
use OCP\Files\Config\IHomeMountProvider;
30
use OCP\Files\Config\IMountProvider;
31
use OCP\Files\Config\IMountProviderCollection;
32
use OCP\Files\Config\IRootMountProvider;
33
use OCP\Files\Config\IUserMountCache;
34
use OCP\Files\Mount\IMountManager;
35
use OCP\Files\Mount\IMountPoint;
36
use OCP\Files\Storage\IStorageFactory;
37
use OCP\IUser;
38
39
class MountProviderCollection implements IMountProviderCollection, Emitter {
0 ignored issues
show
Deprecated Code introduced by
The interface OC\Hooks\Emitter has been deprecated: 18.0.0 use events and the \OCP\EventDispatcher\IEventDispatcher service ( Ignorable by Annotation )

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

39
class MountProviderCollection implements IMountProviderCollection, /** @scrutinizer ignore-deprecated */ Emitter {

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

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

Loading history...
40
	use EmitterTrait;
0 ignored issues
show
Deprecated Code introduced by
The trait OC\Hooks\EmitterTrait has been deprecated: 18.0.0 use events and the \OCP\EventDispatcher\IEventDispatcher service ( Ignorable by Annotation )

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

40
	use /** @scrutinizer ignore-deprecated */ EmitterTrait;

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

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

Loading history...
41
42
	/**
43
	 * @var \OCP\Files\Config\IHomeMountProvider[]
44
	 */
45
	private $homeProviders = [];
46
47
	/**
48
	 * @var \OCP\Files\Config\IMountProvider[]
49
	 */
50
	private $providers = [];
51
52
	/** @var \OCP\Files\Config\IRootMountProvider[] */
53
	private $rootProviders = [];
54
55
	/**
56
	 * @var \OCP\Files\Storage\IStorageFactory
57
	 */
58
	private $loader;
59
60
	/**
61
	 * @var \OCP\Files\Config\IUserMountCache
62
	 */
63
	private $mountCache;
64
65
	/** @var callable[] */
66
	private $mountFilters = [];
67
68
	/**
69
	 * @param \OCP\Files\Storage\IStorageFactory $loader
70
	 * @param IUserMountCache $mountCache
71
	 */
72
	public function __construct(IStorageFactory $loader, IUserMountCache $mountCache) {
73
		$this->loader = $loader;
74
		$this->mountCache = $mountCache;
75
	}
76
77
	/**
78
	 * @param IUser $user
79
	 * @param IMountProvider[] $providers
80
	 * @return IMountPoint[]
81
	 */
82
	private function getUserMountsForProviders(IUser $user, array $providers): array {
83
		$loader = $this->loader;
84
		$mounts = array_map(function (IMountProvider $provider) use ($user, $loader) {
85
			return $provider->getMountsForUser($user, $loader);
86
		}, $providers);
87
		$mounts = array_filter($mounts, function ($result) {
88
			return is_array($result);
89
		});
90
		$mounts = array_reduce($mounts, function (array $mounts, array $providerMounts) {
91
			return array_merge($mounts, $providerMounts);
92
		}, []);
93
		return $this->filterMounts($user, $mounts);
94
	}
95
96
	public function getMountsForUser(IUser $user): array {
97
		return $this->getUserMountsForProviders($user, $this->providers);
98
	}
99
100
	public function getUserMountsForProviderClasses(IUser $user, array $mountProviderClasses): array {
101
		$providers = array_filter(
102
			$this->providers,
103
			fn (IMountProvider $mountProvider) => (in_array(get_class($mountProvider), $mountProviderClasses))
104
		);
105
		return $this->getUserMountsForProviders($user, $providers);
106
	}
107
108
	public function addMountForUser(IUser $user, IMountManager $mountManager, callable $providerFilter = null) {
109
		// shared mount provider gets to go last since it needs to know existing files
110
		// to check for name collisions
111
		$firstMounts = [];
112
		if ($providerFilter) {
113
			$providers = array_filter($this->providers, $providerFilter);
114
		} else {
115
			$providers = $this->providers;
116
		}
117
		$firstProviders = array_filter($providers, function (IMountProvider $provider) {
118
			return (get_class($provider) !== 'OCA\Files_Sharing\MountProvider');
119
		});
120
		$lastProviders = array_filter($providers, function (IMountProvider $provider) {
121
			return (get_class($provider) === 'OCA\Files_Sharing\MountProvider');
122
		});
123
		foreach ($firstProviders as $provider) {
124
			$mounts = $provider->getMountsForUser($user, $this->loader);
125
			if (is_array($mounts)) {
126
				$firstMounts = array_merge($firstMounts, $mounts);
127
			}
128
		}
129
		$firstMounts = $this->filterMounts($user, $firstMounts);
130
		array_walk($firstMounts, [$mountManager, 'addMount']);
131
132
		$lateMounts = [];
133
		foreach ($lastProviders as $provider) {
134
			$mounts = $provider->getMountsForUser($user, $this->loader);
135
			if (is_array($mounts)) {
136
				$lateMounts = array_merge($lateMounts, $mounts);
137
			}
138
		}
139
140
		$lateMounts = $this->filterMounts($user, $lateMounts);
141
		array_walk($lateMounts, [$mountManager, 'addMount']);
142
143
		return array_merge($lateMounts, $firstMounts);
144
	}
145
146
	/**
147
	 * Get the configured home mount for this user
148
	 *
149
	 * @param \OCP\IUser $user
150
	 * @return \OCP\Files\Mount\IMountPoint
151
	 * @since 9.1.0
152
	 */
153
	public function getHomeMountForUser(IUser $user) {
154
		/** @var \OCP\Files\Config\IHomeMountProvider[] $providers */
155
		$providers = array_reverse($this->homeProviders); // call the latest registered provider first to give apps an opportunity to overwrite builtin
156
		foreach ($providers as $homeProvider) {
157
			if ($mount = $homeProvider->getHomeMountForUser($user, $this->loader)) {
158
				$mount->setMountPoint('/' . $user->getUID()); //make sure the mountpoint is what we expect
159
				return $mount;
160
			}
161
		}
162
		throw new \Exception('No home storage configured for user ' . $user);
0 ignored issues
show
Bug introduced by
Are you sure $user of type OCP\IUser can be used in concatenation? Consider adding a __toString()-method. ( Ignorable by Annotation )

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

162
		throw new \Exception('No home storage configured for user ' . /** @scrutinizer ignore-type */ $user);
Loading history...
163
	}
164
165
	/**
166
	 * Add a provider for mount points
167
	 *
168
	 * @param \OCP\Files\Config\IMountProvider $provider
169
	 */
170
	public function registerProvider(IMountProvider $provider) {
171
		$this->providers[] = $provider;
172
173
		$this->emit('\OC\Files\Config', 'registerMountProvider', [$provider]);
174
	}
175
176
	public function registerMountFilter(callable $filter) {
177
		$this->mountFilters[] = $filter;
178
	}
179
180
	private function filterMounts(IUser $user, array $mountPoints) {
181
		return array_filter($mountPoints, function (IMountPoint $mountPoint) use ($user) {
182
			foreach ($this->mountFilters as $filter) {
183
				if ($filter($mountPoint, $user) === false) {
184
					return false;
185
				}
186
			}
187
			return true;
188
		});
189
	}
190
191
	/**
192
	 * Add a provider for home mount points
193
	 *
194
	 * @param \OCP\Files\Config\IHomeMountProvider $provider
195
	 * @since 9.1.0
196
	 */
197
	public function registerHomeProvider(IHomeMountProvider $provider) {
198
		$this->homeProviders[] = $provider;
199
		$this->emit('\OC\Files\Config', 'registerHomeMountProvider', [$provider]);
200
	}
201
202
	/**
203
	 * Get the mount cache which can be used to search for mounts without setting up the filesystem
204
	 *
205
	 * @return IUserMountCache
206
	 */
207
	public function getMountCache() {
208
		return $this->mountCache;
209
	}
210
211
	public function registerRootProvider(IRootMountProvider $provider) {
212
		$this->rootProviders[] = $provider;
213
	}
214
215
	/**
216
	 * Get all root mountpoints
217
	 *
218
	 * @return \OCP\Files\Mount\IMountPoint[]
219
	 * @since 20.0.0
220
	 */
221
	public function getRootMounts(): array {
222
		$loader = $this->loader;
223
		$mounts = array_map(function (IRootMountProvider $provider) use ($loader) {
224
			return $provider->getRootMounts($loader);
225
		}, $this->rootProviders);
226
		$mounts = array_reduce($mounts, function (array $mounts, array $providerMounts) {
227
			return array_merge($mounts, $providerMounts);
228
		}, []);
229
		return $mounts;
230
	}
231
232
	public function clearProviders() {
233
		$this->providers = [];
234
		$this->homeProviders = [];
235
		$this->rootProviders = [];
236
	}
237
238
	public function getProviders(): array {
239
		return $this->providers;
240
	}
241
}
242