Completed
Push — master ( 1fc0d2...96b2c0 )
by Maxence
03:09
created

SharingFrameService::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 19
rs 9.4285
cc 1
eloc 17
nc 1
nop 8

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * Circles - Bring cloud-users closer together.
4
 *
5
 * This file is licensed under the Affero General Public License version 3 or
6
 * later. See the COPYING file.
7
 *
8
 * @author Maxence Lange <[email protected]>
9
 * @copyright 2017
10
 * @license GNU AGPL version 3 or any later version
11
 *
12
 * This program is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU Affero General Public License as
14
 * published by the Free Software Foundation, either version 3 of the
15
 * License, or (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU Affero General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License
23
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24
 *
25
 */
26
27
namespace OCA\Circles\Service;
28
29
30
use Exception;
31
use OC\Http\Client\ClientService;
32
use OCA\Circles\Api\v1\Circles;
33
use OCA\Circles\AppInfo\Application;
34
use OCA\Circles\Db\CirclesRequest;
35
use OCA\Circles\Db\FederatedLinksRequest;
36
use OCA\Circles\Exceptions\CircleDoesNotExistException;
37
use OCA\Circles\Exceptions\MemberDoesNotExistException;
38
use OCA\Circles\Exceptions\PayloadDeliveryException;
39
use OCA\Circles\Exceptions\SharingFrameAlreadyDeliveredException;
40
use OCA\Circles\Exceptions\SharingFrameAlreadyExistException;
41
use OCA\Circles\Exceptions\SharingFrameDoesNotExistException;
42
use OCA\Circles\Model\Circle;
43
use OCA\Circles\Model\FederatedLink;
44
use OCA\Circles\Model\SharingFrame;
45
use OCP\Http\Client\IClientService;
46
47
48
class SharingFrameService {
49
50
	/** @var string */
51
	private $userId;
52
53
	/** @var ConfigService */
54
	private $configService;
55
56
	/** @var CirclesRequest */
57
	private $circlesRequest;
58
59
	/** @var FederatedLinksRequest */
60
	private $federatedLinksRequest;
61
62
	/** @var BroadcastService */
63
	private $broadcastService;
64
65
	/** @var FederatedLinkService */
66
	private $federatedLinkService;
67
68
	/** @var ClientService */
69
	private $clientService;
70
71
	/** @var MiscService */
72
	private $miscService;
73
74
75
	/**
76
	 * SharingFrameService constructor.
77
	 *
78
	 * @param string $UserId
79
	 * @param ConfigService $configService
80
	 * @param CirclesRequest $circlesRequest
81
	 * @param FederatedLinksRequest $federatedLinksRequest
82
	 * @param BroadcastService $broadcastService
83
	 * @param FederatedLinkService $federatedLinkService
84
	 * @param IClientService $clientService
85
	 * @param MiscService $miscService
86
	 */
87
	public function __construct(
0 ignored issues
show
Coding Style Naming introduced by
The parameter $UserId is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
88
		$UserId,
89
		ConfigService $configService,
90
		CirclesRequest $circlesRequest,
91
		FederatedLinksRequest $federatedLinksRequest,
92
		BroadcastService $broadcastService,
93
		FederatedLinkService $federatedLinkService,
94
		IClientService $clientService,
95
		MiscService $miscService
96
	) {
97
		$this->userId = $UserId;
98
		$this->configService = $configService;
99
		$this->circlesRequest = $circlesRequest;
100
		$this->federatedLinksRequest = $federatedLinksRequest;
101
		$this->broadcastService = $broadcastService;
102
		$this->federatedLinkService = $federatedLinkService;
103
		$this->clientService = $clientService;
0 ignored issues
show
Documentation Bug introduced by
It seems like $clientService of type object<OCP\Http\Client\IClientService> is incompatible with the declared type object<OC\Http\Client\ClientService> of property $clientService.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
104
		$this->miscService = $miscService;
105
	}
106
107
108
	/**
109
	 * createFrame()
110
	 *
111
	 * Save the Frame containing the Payload.
112
	 * The Payload will be shared locally, and spread it live if a Broadcaster is set.
113
	 * Function will also initiate the federated broadcast to linked circles.
114
	 *
115
	 * @param string $circleUniqueId
116
	 * @param SharingFrame $frame
117
	 * @param string|null $broadcast
118
	 *
119
	 * @throws Exception
120
	 * @throws MemberDoesNotExistException
121
	 */
122 View Code Duplication
	public function createFrame($circleUniqueId, SharingFrame $frame, $broadcast = null) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
123
124
		try {
125
			$circle = $this->circlesRequest->getCircle($circleUniqueId, $this->userId);
126
			$circle->getHigherViewer()
127
				   ->hasToBeMember();
128
129
			$frame->setCircle($circle);
130
131
			$this->generateHeaders($frame, $circle, $broadcast);
132
			$this->circlesRequest->saveFrame($frame);
133
134
			$this->initiateShare($circle->getUniqueId(), $frame->getUniqueId());
135
		} catch (Exception $e) {
136
			throw $e;
137
		}
138
	}
139
140
141
	/**
142
	 * Generate Headers and few more thing like UniqueId and Author.
143
	 * Check if the source is NOT Circles.
144
	 *
145
	 * @param SharingFrame $frame
146
	 * @param Circle $circle
147
	 * @param $broadcast
148
	 */
149
	private function generateHeaders(SharingFrame $frame, Circle $circle, $broadcast) {
150
151
		try {
152
			$frame->cannotBeFromCircles();
153
154
			$frame->setAuthor($this->userId);
155
			$frame->setHeader('author', $this->userId);
156
			$frame->setHeader('circleName', $circle->getName());
157
			$frame->setHeader('circleUniqueId', $circle->getUniqueId());
158
			$frame->setHeader('broadcast', (string)$broadcast);
159
			$frame->generateUniqueId();
160
161
		} catch (Exception $e) {
162
			throw new $e;
163
		}
164
	}
165
166
	/**
167
	 * @param string $circleUniqueId
168
	 * @param string $frameUniqueId
169
	 *
170
	 * @return null|SharingFrame
171
	 * @throws SharingFrameAlreadyDeliveredException
172
	 * @throws SharingFrameDoesNotExistException
173
	 */
174
	public function getFrameFromUniqueId($circleUniqueId, $frameUniqueId) {
175
		if ($frameUniqueId === '') {
176
			throw new SharingFrameDoesNotExistException('unknown_share');
177
		}
178
179
		try {
180
			$frame = $this->circlesRequest->getFrame($circleUniqueId, $frameUniqueId);
181
			if ($frame->getCloudId() !== null) {
182
				throw new SharingFrameAlreadyDeliveredException('share_already_delivered');
183
			}
184
		} catch (SharingFrameDoesNotExistException $e) {
185
			throw new SharingFrameDoesNotExistException('unknown_share');
186
		}
187
188
		return $frame;
189
	}
190
191
192
	/**
193
	 * @param string $token
194
	 * @param string $uniqueId
195
	 * @param SharingFrame $frame
196
	 *
197
	 * @return bool
198
	 * @throws Exception
199
	 */
200
	public function receiveFrame($token, $uniqueId, SharingFrame &$frame) {
201
		try {
202
			$link = $this->federatedLinksRequest->getLinkFromToken((string)$token, (string)$uniqueId);
203
			$circle = $this->circlesRequest->forceGetCircle($link->getCircleId());
204
		} catch (CircleDoesNotExistException $e) {
205
			throw new CircleDoesNotExistException('unknown_circle');
206
		} catch (Exception $e) {
207
			throw $e;
208
		}
209
210
		try {
211
			$this->circlesRequest->getFrame($link->getCircleId(), $frame->getUniqueId());
212
			throw new SharingFrameAlreadyExistException('shares_is_already_known');
213
		} catch (SharingFrameDoesNotExistException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
214
		}
215
216
		$frame->setCircle($circle);
217
		$this->circlesRequest->saveFrame($frame);
218
219
		return true;
220
	}
221
222
223
	/**
224
	 * @param string $circleUniqueId
225
	 * @param string $frameUniqueId
226
	 *
227
	 * @return bool
228
	 * @throws Exception
229
	 */
230
	public function initiateShare($circleUniqueId, $frameUniqueId) {
231
		$args = [
232
			'circleId' => $circleUniqueId,
233
			'frameId'  => $frameUniqueId
234
		];
235
236
		$client = $this->clientService->newClient();
237
		try {
238
			$client->post(
239
				$this->generatePayloadDeliveryURL($this->configService->getLocalAddress()), [
240
																							  'body'            => $args,
241
																							  'timeout'         => 10,
242
																							  'connect_timeout' => 10,
243
																						  ]
244
			);
245
246
			return true;
247
		} catch (Exception $e) {
248
			throw $e;
249
		}
250
	}
251
252
253
	/**
254
	 * @param string $remote
255
	 *
256
	 * @return string
257
	 */
258
	private function generatePayloadDeliveryURL($remote) {
259
		return $this->configService->generateRemoteHost($remote) . Application::REMOTE_URL_PAYLOAD;
260
	}
261
262
263
	/**
264
	 * @param SharingFrame $frame
265
	 *
266
	 * @throws Exception
267
	 */
268
	public function forwardSharingFrame(SharingFrame $frame) {
269
270
		try {
271
			$circle = $this->circlesRequest->forceGetCircle(
272
				$frame->getCircle()
273
					  ->getUniqueId()
274
			);
275
		} catch (CircleDoesNotExistException $e) {
276
			throw new CircleDoesNotExistException('unknown_circle');
277
		}
278
279
		$links = $this->federatedLinksRequest->getLinksFromCircle(
280
			$frame->getCircle()
281
				  ->getUniqueId(), FederatedLink::STATUS_LINK_UP
282
		);
283
284
		$this->forwardSharingFrameToFederatedLinks($circle, $frame, $links);
285
	}
286
287
288
	/**
289
	 * @param Circle $circle
290
	 * @param SharingFrame $frame
291
	 * @param FederatedLink[] $links
292
	 */
293
	private function forwardSharingFrameToFederatedLinks(Circle $circle, SharingFrame $frame, $links) {
294
295
		$args = [
296
			'apiVersion' => Circles::version(),
297
			'uniqueId'   => $circle->getUniqueId(true),
298
			'item'       => json_encode($frame)
299
		];
300
301
		foreach ($links AS $link) {
302
			$args['token'] = $link->getToken(true);
303
			$this->deliverSharingFrameToLink($link, $args);
304
		}
305
	}
306
307
308
	/**
309
	 * sendRemoteShareToLinks();
310
	 *
311
	 * @param FederatedLink $link
312
	 * @param array $args
313
	 */
314
	private function deliverSharingFrameToLink($link, $args) {
315
316
		$client = $this->clientService->newClient();
317
		try {
318
			$request = $client->put(
319
				$this->generatePayloadDeliveryURL($link->getAddress()), [
320
																		  'body'            => $args,
321
																		  'timeout'         => 10,
322
																		  'connect_timeout' => 10,
323
																	  ]
324
			);
325
326
			$result = json_decode($request->getBody(), true);
327
			if ($result['status'] === -1) {
328
				throw new PayloadDeliveryException($result['reason']);
329
			}
330
331
		} catch (Exception $e) {
332
			$this->miscService->log(
333
				'fail to send frame to ' . $link->getAddress() . ' - ' . $e->getMessage()
334
			);
335
		}
336
	}
337
338
339
	/**
340
	 * @param SharingFrame $frame
341
	 */
342
	public function updateFrameWithCloudId(SharingFrame $frame) {
343
		$frame->setCloudId($this->configService->getLocalAddress());
344
		$this->circlesRequest->updateFrame($frame);
345
	}
346
347
348
}