Completed
Push — master ( 4153e1...9e2d1c )
by Morris
18:17
created

ProviderFactory::federatedShareProvider()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 46
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

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