Completed
Push — master ( ca0f2f...6aa6d2 )
by Björn
33:52 queued 15:38
created

ProviderFactory::getProvider()   B

Complexity

Conditions 7
Paths 12

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
nc 12
nop 1
dl 0
loc 20
rs 8.6666
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Bjoern Schiessle <[email protected]>
6
 * @author Björn Schießle <[email protected]>
7
 * @author Joas Schilling <[email protected]>
8
 * @author Lukas Reschke <[email protected]>
9
 * @author Maxence Lange <[email protected]>
10
 * @author Maxence Lange <[email protected]>
11
 * @author Robin Appelman <[email protected]>
12
 * @author Roeland Jago Douma <[email protected]>
13
 *
14
 * @license AGPL-3.0
15
 *
16
 * This code is free software: you can redistribute it and/or modify
17
 * it under the terms of the GNU Affero General Public License, version 3,
18
 * as published by the Free Software Foundation.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
 * GNU Affero General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU Affero General Public License, version 3,
26
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
27
 *
28
 */
29
namespace OC\Share20;
30
31
use OC\CapabilitiesManager;
32
use OCA\FederatedFileSharing\AddressHandler;
33
use OCA\FederatedFileSharing\FederatedShareProvider;
34
use OCA\FederatedFileSharing\Notifications;
35
use OCA\FederatedFileSharing\OCM\CloudFederationProvider;
36
use OCA\FederatedFileSharing\TokenHandler;
37
use OCA\ShareByMail\Settings\SettingsManager;
38
use OCA\ShareByMail\ShareByMailProvider;
39
use OCP\Defaults;
40
use OCP\Share\IProviderFactory;
41
use OC\Share20\Exception\ProviderException;
42
use OCP\IServerContainer;
43
44
/**
45
 * Class ProviderFactory
46
 *
47
 * @package OC\Share20
48
 */
49
class ProviderFactory implements IProviderFactory {
50
51
	/** @var IServerContainer */
52
	private $serverContainer;
53
	/** @var DefaultShareProvider */
54
	private $defaultProvider = null;
55
	/** @var FederatedShareProvider */
56
	private $federatedProvider = null;
57
	/** @var  ShareByMailProvider */
58
	private $shareByMailProvider;
59
	/** @var  \OCA\Circles\ShareByCircleProvider */
60
	private $shareByCircleProvider = null;
61
	/** @var bool */
62
	private $circlesAreNotAvailable = false;
63
	/** @var \OCA\Spreed\Share\RoomShareProvider */
64
	private $roomShareProvider = null;
65
66
	/**
67
	 * IProviderFactory constructor.
68
	 *
69
	 * @param IServerContainer $serverContainer
70
	 */
71
	public function __construct(IServerContainer $serverContainer) {
72
		$this->serverContainer = $serverContainer;
73
	}
74
75
	/**
76
	 * Create the default share provider.
77
	 *
78
	 * @return DefaultShareProvider
79
	 */
80
	protected function defaultShareProvider() {
81 View Code Duplication
		if ($this->defaultProvider === null) {
82
			$this->defaultProvider = new DefaultShareProvider(
83
				$this->serverContainer->getDatabaseConnection(),
84
				$this->serverContainer->getUserManager(),
85
				$this->serverContainer->getGroupManager(),
86
				$this->serverContainer->getLazyRootFolder(),
87
				$this->serverContainer->getMailer(),
88
				$this->serverContainer->query(Defaults::class),
89
				$this->serverContainer->getL10N('sharing'),
90
				$this->serverContainer->getURLGenerator()
91
			);
92
		}
93
94
		return $this->defaultProvider;
95
	}
96
97
	/**
98
	 * Create the federated share provider
99
	 *
100
	 * @return FederatedShareProvider
101
	 */
102
	protected function federatedShareProvider() {
103
		if ($this->federatedProvider === null) {
104
			/*
105
			 * Check if the app is enabled
106
			 */
107
			$appManager = $this->serverContainer->getAppManager();
108
			if (!$appManager->isEnabledForUser('federatedfilesharing')) {
109
				return null;
110
			}
111
112
			/*
113
			 * TODO: add factory to federated sharing app
114
			 */
115
			$l = $this->serverContainer->getL10N('federatedfilessharing');
116
			$addressHandler = new AddressHandler(
117
				$this->serverContainer->getURLGenerator(),
118
				$l,
119
				$this->serverContainer->getCloudIdManager()
120
			);
121
			$notifications = new Notifications(
122
				$addressHandler,
123
				$this->serverContainer->getHTTPClientService(),
124
				$this->serverContainer->query(\OCP\OCS\IDiscoveryService::class),
125
				$this->serverContainer->getJobList(),
126
				\OC::$server->getCloudFederationProviderManager(),
127
				\OC::$server->getCloudFederationFactory()
128
			);
129
			$tokenHandler = new TokenHandler(
130
				$this->serverContainer->getSecureRandom()
131
			);
132
133
			$this->federatedProvider = new FederatedShareProvider(
134
				$this->serverContainer->getDatabaseConnection(),
135
				$addressHandler,
136
				$notifications,
137
				$tokenHandler,
138
				$l,
139
				$this->serverContainer->getLogger(),
140
				$this->serverContainer->getLazyRootFolder(),
141
				$this->serverContainer->getConfig(),
142
				$this->serverContainer->getUserManager(),
143
				$this->serverContainer->getCloudIdManager(),
144
				$this->serverContainer->getGlobalScaleConfig(),
145
				$this->serverContainer->getCloudFederationProviderManager()
146
			);
147
		}
148
149
		return $this->federatedProvider;
150
	}
151
152
	/**
153
	 * Create the federated share provider
154
	 *
155
	 * @return ShareByMailProvider
156
	 */
157
	protected function getShareByMailProvider() {
158
		if ($this->shareByMailProvider === null) {
159
			/*
160
			 * Check if the app is enabled
161
			 */
162
			$appManager = $this->serverContainer->getAppManager();
163
			if (!$appManager->isEnabledForUser('sharebymail')) {
164
				return null;
165
			}
166
167
			$settingsManager = new SettingsManager($this->serverContainer->getConfig());
168
169
			$this->shareByMailProvider = new ShareByMailProvider(
170
				$this->serverContainer->getDatabaseConnection(),
171
				$this->serverContainer->getSecureRandom(),
172
				$this->serverContainer->getUserManager(),
173
				$this->serverContainer->getLazyRootFolder(),
174
				$this->serverContainer->getL10N('sharebymail'),
175
				$this->serverContainer->getLogger(),
176
				$this->serverContainer->getMailer(),
177
				$this->serverContainer->getURLGenerator(),
178
				$this->serverContainer->getActivityManager(),
179
				$settingsManager,
180
				$this->serverContainer->query(Defaults::class),
181
				$this->serverContainer->getHasher(),
182
				$this->serverContainer->query(CapabilitiesManager::class)
183
			);
184
		}
185
186
		return $this->shareByMailProvider;
187
	}
188
189
190
	/**
191
	 * Create the circle share provider
192
	 *
193
	 * @return FederatedShareProvider
194
	 *
195
	 * @suppress PhanUndeclaredClassMethod
196
	 */
197
	protected function getShareByCircleProvider() {
198
199
		if ($this->circlesAreNotAvailable) {
200
			return null;
201
		}
202
203
		if (!$this->serverContainer->getAppManager()->isEnabledForUser('circles') ||
204
			!class_exists('\OCA\Circles\ShareByCircleProvider')
205
		) {
206
			$this->circlesAreNotAvailable = true;
207
			return null;
208
		}
209
210 View Code Duplication
		if ($this->shareByCircleProvider === null) {
211
212
			$this->shareByCircleProvider = new \OCA\Circles\ShareByCircleProvider(
213
				$this->serverContainer->getDatabaseConnection(),
214
				$this->serverContainer->getSecureRandom(),
215
				$this->serverContainer->getUserManager(),
216
				$this->serverContainer->getLazyRootFolder(),
217
				$this->serverContainer->getL10N('circles'),
218
				$this->serverContainer->getLogger(),
219
				$this->serverContainer->getURLGenerator()
220
			);
221
		}
222
223
		return $this->shareByCircleProvider;
224
	}
225
226
	/**
227
	 * Create the room share provider
228
	 *
229
	 * @return RoomShareProvider
230
	 */
231
	protected function getRoomShareProvider() {
232
		if ($this->roomShareProvider === null) {
233
			/*
234
			 * Check if the app is enabled
235
			 */
236
			$appManager = $this->serverContainer->getAppManager();
237
			if (!$appManager->isEnabledForUser('spreed')) {
238
				return null;
239
			}
240
241
			try {
242
				$this->roomShareProvider = $this->serverContainer->query('\OCA\Spreed\Share\RoomShareProvider');
243
			} catch (\OCP\AppFramework\QueryException $e) {
244
				return null;
245
			}
246
		}
247
248
		return $this->roomShareProvider;
249
	}
250
251
	/**
252
	 * @inheritdoc
253
	 */
254
	public function getProvider($id) {
255
		$provider = null;
256
		if ($id === 'ocinternal') {
257
			$provider = $this->defaultShareProvider();
258
		} else if ($id === 'ocFederatedSharing') {
259
			$provider = $this->federatedShareProvider();
260
		} else if ($id === 'ocMailShare') {
261
			$provider = $this->getShareByMailProvider();
262
		} else if ($id === 'ocCircleShare') {
263
			$provider = $this->getShareByCircleProvider();
264
		} else if ($id === 'ocRoomShare') {
265
			$provider = $this->getRoomShareProvider();
266
		}
267
268
		if ($provider === null) {
269
			throw new ProviderException('No provider with id .' . $id . ' found.');
270
		}
271
272
		return $provider;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $provider; (OCA\FederatedFileSharing...are20\RoomShareProvider) is incompatible with the return type declared by the interface OCP\Share\IProviderFactory::getProvider of type OCP\Share\IShareProvider.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
273
	}
274
275
	/**
276
	 * @inheritdoc
277
	 */
278
	public function getProviderForType($shareType) {
279
		$provider = null;
280
281
		if ($shareType === \OCP\Share::SHARE_TYPE_USER ||
282
			$shareType === \OCP\Share::SHARE_TYPE_GROUP ||
283
			$shareType === \OCP\Share::SHARE_TYPE_LINK
284
		) {
285
			$provider = $this->defaultShareProvider();
286
		} else if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE || $shareType === \OCP\Share::SHARE_TYPE_REMOTE_GROUP) {
287
			$provider = $this->federatedShareProvider();
288
		} else if ($shareType === \OCP\Share::SHARE_TYPE_EMAIL) {
289
			$provider = $this->getShareByMailProvider();
290
		} else if ($shareType === \OCP\Share::SHARE_TYPE_CIRCLE) {
291
			$provider = $this->getShareByCircleProvider();
292
		} else if ($shareType === \OCP\Share::SHARE_TYPE_ROOM) {
293
			$provider = $this->getRoomShareProvider();
294
		}
295
296
297
		if ($provider === null) {
298
			throw new ProviderException('No share provider for share type ' . $shareType);
299
		}
300
301
		return $provider;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $provider; (OCA\FederatedFileSharing...are20\RoomShareProvider) is incompatible with the return type declared by the interface OCP\Share\IProviderFactory::getProviderForType of type OCP\Share\IShareProvider.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
302
	}
303
304
	public function getAllProviders() {
305
		$shares = [$this->defaultShareProvider(), $this->federatedShareProvider()];
306
		$shareByMail = $this->getShareByMailProvider();
307
		if ($shareByMail !== null) {
308
			$shares[] = $shareByMail;
309
		}
310
		$shareByCircle = $this->getShareByCircleProvider();
311
		if ($shareByCircle !== null) {
312
			$shares[] = $shareByCircle;
313
		}
314
		$roomShare = $this->getRoomShareProvider();
315
		if ($roomShare !== null) {
316
			$shares[] = $roomShare;
317
		}
318
319
		return $shares;
0 ignored issues
show
Best Practice introduced by
The expression return $shares; seems to be an array, but some of its elements' types (null|OCA\Circles\ShareBy...are20\RoomShareProvider) are incompatible with the return type declared by the interface OCP\Share\IProviderFactory::getAllProviders of type OCP\Share\IShareProvider[].

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
320
	}
321
}
322