Completed
Push — master ( c8832b...c655ce )
by Maxence
04:09
created

checkUpdateLinkFromRemoteLinkRequested()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 9
Ratio 100 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 9
loc 9
rs 9.6666
cc 2
eloc 5
nc 2
nop 2
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 OCA\Circles\Api\v1\Circles;
32
use OCA\Circles\AppInfo\Application;
33
use OCA\Circles\Db\CirclesRequest;
34
use OCA\Circles\Db\FederatedLinksRequest;
35
use OCA\Circles\Exceptions\CircleTypeNotValidException;
36
use OCA\Circles\Exceptions\FederatedCircleLinkFormatException;
37
use OCA\Circles\Exceptions\FederatedCircleNotAllowedException;
38
use OCA\Circles\Exceptions\FederatedCircleStatusUpdateException;
39
use OCA\Circles\Exceptions\FederatedLinkCreationException;
40
use OCA\Circles\Exceptions\FederatedLinkDoesNotExistException;
41
use OCA\Circles\Exceptions\FederatedLinkUpdateException;
42
use OCA\Circles\Exceptions\FederatedRemoteCircleDoesNotExistException;
43
use OCA\Circles\Exceptions\FederatedRemoteDoesNotAllowException;
44
use OCA\Circles\Exceptions\FederatedRemoteIsDownException;
45
use OCA\Circles\Exceptions\MemberIsNotAdminException;
46
use OCA\Circles\Model\Circle;
47
use OCA\Circles\Model\FederatedLink;
48
use OCP\Http\Client\IClientService;
49
use OCP\Http\Client\IResponse;
50
use OCP\IL10N;
51
52
class FederatedLinkService {
53
54
	/** @var string */
55
	private $userId;
56
57
	/** @var IL10N */
58
	private $l10n;
59
60
	/** @var CirclesRequest */
61
	private $circlesRequest;
62
63
	/** @var ConfigService */
64
	private $configService;
65
66
	/** @var CirclesService */
67
	private $circlesService;
68
69
	/** @var BroadcastService */
70
	private $broadcastService;
71
72
	/** @var FederatedLinksRequest */
73
	private $federatedLinksRequest;
74
75
	/** @var EventsService */
76
	private $eventsService;
77
78
	/** @var IClientService */
79
	private $clientService;
80
81
	/** @var MiscService */
82
	private $miscService;
83
84
85
	/**
86
	 * FederatedLinkService constructor.
87
	 *
88
	 * @param string $UserId
89
	 * @param IL10N $l10n
90
	 * @param CirclesRequest $circlesRequest
91
	 * @param ConfigService $configService
92
	 * @param CirclesService $circlesService
93
	 * @param BroadcastService $broadcastService
94
	 * @param FederatedLinksRequest $federatedLinksRequest
95
	 * @param EventsService $eventsService
96
	 * @param IClientService $clientService
97
	 * @param MiscService $miscService
98
	 */
99
	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...
100
		$UserId, IL10N $l10n, CirclesRequest $circlesRequest, ConfigService $configService,
101
		CirclesService $circlesService, BroadcastService $broadcastService,
102
		FederatedLinksRequest $federatedLinksRequest, EventsService $eventsService,
103
		IClientService $clientService, MiscService $miscService
104
	) {
105
		$this->userId = $UserId;
106
		$this->l10n = $l10n;
107
		$this->circlesRequest = $circlesRequest;
108
		$this->configService = $configService;
109
		$this->circlesService = $circlesService;
110
		$this->broadcastService = $broadcastService;
111
		$this->federatedLinksRequest = $federatedLinksRequest;
112
		$this->eventsService = $eventsService;
113
114
		$this->clientService = $clientService;
115
		$this->miscService = $miscService;
116
	}
117
118
119
	/**
120
	 * linkCircle();
121
	 *
122
	 * link to a circle.
123
	 * Function will check if settings allow Federated links between circles, and the format of
124
	 * the link ($remote). If no exception, a request to the remote circle will be initiated
125
	 * using requestLinkWithCircle()
126
	 *
127
	 * $remote format: <circle_name>@<remote_host>
128
	 *
129
	 * @param string $circleUniqueId
130
	 * @param string $remote
131
	 *
132
	 * @throws Exception
133
	 * @throws FederatedCircleLinkFormatException
134
	 * @throws CircleTypeNotValidException
135
	 *
136
	 * @return FederatedLink
137
	 */
138
	public function linkCircle($circleUniqueId, $remote) {
139
140
		if (!$this->configService->isFederatedCirclesAllowed()) {
141
			throw new FederatedCircleNotAllowedException(
142
				$this->l10n->t("Federated circles are not allowed on this Nextcloud")
143
			);
144
		}
145
146
		if (strpos($remote, '@') === false) {
147
			throw new FederatedCircleLinkFormatException(
148
				$this->l10n->t("Federated link does not have a valid format")
149
			);
150
		}
151
152
		try {
153
			return $this->requestLinkWithCircle($circleUniqueId, $remote);
154
		} catch (Exception $e) {
155
			throw $e;
156
		}
157
	}
158
159
160
	/**
161
	 * linkStatus()
162
	 *
163
	 * Update the status of a link.
164
	 * Function will check if user can edit the status, will update it and send the update to
165
	 * remote
166
	 *
167
	 * @param string $linkUniqueId
168
	 * @param int $status
169
	 *
170
	 * @throws Exception
171
	 * @throws FederatedCircleLinkFormatException
172
	 * @throws CircleTypeNotValidException
173
	 * @throws MemberIsNotAdminException
174
	 *
175
	 * @return FederatedLink[]
176
	 */
177
	public function linkStatus($linkUniqueId, $status) {
178
179
		$status = (int)$status;
180
		$link = null;
181
		try {
182
183
			$link = $this->federatedLinksRequest->getLinkFromId($linkUniqueId);
184
			$circle = $this->circlesRequest->getCircle($link->getCircleId(), $this->userId);
185
			$circle->hasToBeFederated();
186
			$circle->getHigherViewer()
187
				   ->hasToBeAdmin();
188
			$link->hasToBeValidStatusUpdate($status);
189
190
			if (!$this->eventOnLinkStatus($circle, $link, $status)) {
191
				return $this->federatedLinksRequest->getLinksFromCircle($circle->getUniqueId());
192
			}
193
194
		} catch (Exception $e) {
195
			throw $e;
196
		}
197
198
		$link->setStatus($status);
199
		$link->setCircleId($circle->getUniqueId(true));
200
201
		try {
202
			$this->updateLinkRemote($link);
203
		} catch (Exception $e) {
204
			if ($status !== FederatedLink::STATUS_LINK_REMOVE) {
205
				throw $e;
206
			}
207
		}
208
209
		$this->federatedLinksRequest->update($link);
210
211
		return $this->federatedLinksRequest->getLinksFromCircle($circle->getUniqueId());
212
	}
213
214
215
	/**
216
	 * eventOnLinkStatus();
217
	 *
218
	 * Called by linkStatus() to manage events when status is changing.
219
	 * If status does not need update, returns false;
220
	 *
221
	 * @param Circle $circle
222
	 * @param FederatedLink $link
223
	 * @param $status
224
	 *
225
	 * @return bool
226
	 */
227
	private function eventOnLinkStatus(Circle $circle, FederatedLink $link, $status) {
228
		if ($link->getStatus() === $status) {
229
			return false;
230
		}
231
232
		if ($status === FederatedLink::STATUS_LINK_REMOVE) {
233
			$this->eventsService->onLinkRemove($circle, $link);
234
		}
235
236
		if ($status === FederatedLink::STATUS_LINK_UP) {
237
			$this->eventsService->onLinkRequestAccepting($circle, $link);
238
			$this->eventsService->onLinkUp($circle, $link);
239
		}
240
241
		return true;
242
	}
243
244
245
	/**
246
	 * requestLinkWithCircle()
247
	 *
248
	 * Using CircleId, function will get more infos from the database.
249
	 * Will check if author is at least admin and initiate a FederatedLink, save it
250
	 * in the database and send a request to the remote circle using requestLink()
251
	 * If any issue, entry is removed from the database.
252
	 *
253
	 * @param string $circleUniqueId
254
	 * @param string $remote
255
	 *
256
	 * @return FederatedLink
257
	 * @throws Exception
258
	 */
259
	private function requestLinkWithCircle($circleUniqueId, $remote) {
260
261
		$link = null;
262
		try {
263
			$circle = $this->circlesService->detailsCircle($circleUniqueId);
264
			$circle->getHigherViewer()
265
				   ->hasToBeAdmin();
266
			$circle->hasToBeFederated();
267
			$circle->cantBePersonal();
268
269
			$link = $this->generateNewLinkWithRemoteCircle($circle->getUniqueId(), $remote);
270
			$this->requestLink($circle, $link);
271
		} catch (Exception $e) {
272
			$this->federatedLinksRequest->delete($link);
0 ignored issues
show
Bug introduced by
It seems like $link defined by null on line 261 can be null; however, OCA\Circles\Db\FederatedLinksRequest::delete() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
273
			throw $e;
274
		}
275
276
		return $link;
277
	}
278
279
280
	/**
281
	 * @param $circleUniqueId
282
	 * @param $remote
283
	 *
284
	 * @return FederatedLink
285
	 */
286
	private function generateNewLinkWithRemoteCircle($circleUniqueId, $remote) {
287
288
		$link = new FederatedLink();
289
		list($remoteCircle, $remoteAddress) = explode('@', $remote, 2);
290
291
		$link->setCircleId($circleUniqueId)
292
			 ->setLocalAddress($this->configService->getLocalAddress())
293
			 ->setAddress($remoteAddress)
294
			 ->setRemoteCircleName($remoteCircle)
295
			 ->setStatus(FederatedLink::STATUS_LINK_SETUP)
296
			 ->generateToken();
297
298
		$this->federatedLinksRequest->create($link);
299
300
		return $link;
301
	}
302
303
304
	/**
305
	 * @param string $remote
306
	 *
307
	 * @return string
308
	 */
309
	private function generateLinkRemoteURL($remote) {
310
		return $this->configService->generateRemoteHost($remote) . Application::REMOTE_URL_LINK;
311
	}
312
313
314
	/**
315
	 * requestLink()
316
	 *
317
	 *
318
	 * @param Circle $circle
319
	 * @param FederatedLink $link
320
	 *
321
	 * @return boolean
322
	 * @throws Exception
323
	 */
324
	private function requestLink(Circle $circle, FederatedLink &$link) {
325
		$args = array_merge(self::generateLinkData($link), ['sourceName' => $circle->getName()]);
326
327
		try {
328
			$client = $this->clientService->newClient();
329
			$body = self::generateClientBodyData($args);
330
			$response = $client->put($this->generateLinkRemoteURL($link->getAddress()), $body);
331
			$result = $this->parseRequestLinkResult($response);
332
333
			$reason = ((key_exists('reason', $result)) ? $result['reason'] : '');
334
			$this->eventOnRequestLink($circle, $link, $result['status'], $reason);
335
336
			$link->setUniqueId($result['uniqueId']);
337
			$this->federatedLinksRequest->update($link);
338
339
			return true;
340
		} catch (Exception $e) {
341
			throw $e;
342
		}
343
	}
344
345
346
	private function parseRequestLinkResult(IResponse $response) {
347
		$result = json_decode($response->getBody(), true);
348
		if ($result === null) {
349
			throw new FederatedRemoteIsDownException(
350
				$this->l10n->t('The remote host is down or the Circles app is not installed on it')
351
			);
352
		}
353
354
		return $result;
355
	}
356
357
358
	/**
359
	 * eventOnRequestLink();
360
	 *
361
	 * Called by requestLink() will update status and event
362
	 * Will also manage errors returned by the remote link
363
	 *
364
	 * @param Circle $circle
365
	 * @param FederatedLink $link
366
	 * @param int $status
367
	 * @param string $reason
368
	 *
369
	 * @throws Exception
370
	 */
371
	private function eventOnRequestLink(Circle $circle, FederatedLink &$link, $status, $reason) {
372
373
		switch ($status) {
374
			case FederatedLink::STATUS_LINK_UP:
375
				$link->setStatus(FederatedLink::STATUS_LINK_UP);
376
				$this->eventsService->onLinkUp($circle, $link);
377
				break;
378
379
			case  FederatedLink::STATUS_LINK_REQUESTED:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
380
				$link->setStatus(FederatedLink::STATUS_REQUEST_SENT);
381
				$this->eventsService->onLinkRequestSent($circle, $link);
382
				break;
383
384
			default:
385
				$this->parseRequestLinkError($reason);
386
		}
387
	}
388
389
390
	/**
391
	 * parseRequestLinkError();
392
	 *
393
	 * Will parse the error reason returned by requestLink() and throw an Exception
394
	 *
395
	 * @param $reason
396
	 *
397
	 * @throws Exception
398
	 * @throws FederatedRemoteCircleDoesNotExistException
399
	 * @throws FederatedRemoteDoesNotAllowException
400
	 */
401
	private function parseRequestLinkError($reason) {
402
403
		$convert = [
404
			'federated_not_allowed' => $this->l10n->t(
405
				'Federated circles are not allowed on the remote Nextcloud'
406
			),
407
			'circle_links_disable'  => $this->l10n->t('Remote circle does not accept federated links'),
408
			'duplicate_unique_id'   => $this->l10n->t('Trying to link a circle to itself'),
409
			'duplicate_link'        => $this->l10n->t('This link exists already'),
410
			'circle_does_not_exist' => $this->l10n->t('The requested remote circle does not exist')
411
		];
412
413
		if (key_exists($reason, $convert)) {
414
			throw new FederatedRemoteDoesNotAllowException($convert[$reason]);
415
		}
416
		throw new Exception($reason);
417
	}
418
419
420
	/**
421
	 * @param string $token
422
	 * @param string $uniqueId
423
	 * @param int $status
424
	 *
425
	 * @return FederatedLink
426
	 * @throws Exception
427
	 */
428
	public function updateLinkFromRemote($token, $uniqueId, $status) {
429
		try {
430
			$link = $this->federatedLinksRequest->getLinkFromToken($token, $uniqueId);
431
			$circle = $this->circlesRequest->forceGetCircle($link->getCircleId());
432
			$circle->hasToBeFederated();
433
434
			$this->checkUpdateLinkFromRemote($status);
435
			$this->checkUpdateLinkFromRemoteLinkUp($circle, $link, $status);
436
			$this->checkUpdateLinkFromRemoteLinkRemove($circle, $link, $status);
437
438
			if ($link->getStatus() !== $status) {
439
				$this->federatedLinksRequest->update($link);
440
			}
441
442
			return $link;
443
		} catch (Exception $e) {
444
			throw $e;
445
		}
446
	}
447
448
	/**
449
	 * checkUpdateLinkFromRemote();
450
	 *
451
	 * will throw exception is the status sent by remote is not correct
452
	 *
453
	 * @param int $status
454
	 *
455
	 * @throws FederatedCircleStatusUpdateException
456
	 */
457
	private function checkUpdateLinkFromRemote($status) {
458
		$status = (int)$status;
459
		if ($status !== FederatedLink::STATUS_LINK_UP
460
			&& $status !== FederatedLink::STATUS_LINK_REMOVE
461
		) {
462
			throw new FederatedCircleStatusUpdateException(
463
				$this->l10n->t('Cannot proceed with this status update')
464
			);
465
		}
466
	}
467
468
469
	/**
470
	 * checkUpdateLinkFromRemoteLinkUp()
471
	 *
472
	 * in case of a request of status update from remote for a link up, we check the current
473
	 * status of the link locally.
474
	 *
475
	 * @param Circle $circle
476
	 * @param FederatedLink $link
477
	 * @param int $status
478
	 *
479
	 * @throws FederatedCircleStatusUpdateException
480
	 */
481
	private function checkUpdateLinkFromRemoteLinkUp(Circle $circle, FederatedLink $link, $status) {
482
		if ((int)$status !== FederatedLink::STATUS_LINK_UP) {
483
			return;
484
		}
485
486
		if ($link->getStatus() !== FederatedLink::STATUS_REQUEST_SENT) {
487
			throw new FederatedCircleStatusUpdateException(
488
				$this->l10n->t('Cannot proceed with this status update')
489
			);
490
		}
491
492
		$this->eventsService->onLinkRequestAccepted($circle, $link);
493
		$this->eventsService->onLinkUp($circle, $link);
494
		$link->setStatus($status);
495
	}
496
497
498
	/**
499
	 * updateLinkRemote()
500
	 *
501
	 * Send a request to the remote of the link to update its status.
502
	 *
503
	 * @param FederatedLink $link
504
	 *
505
	 * @return bool
506
	 * @throws Exception
507
	 */
508
	public function updateLinkRemote(FederatedLink &$link) {
509
510
		try {
511
			$client = $this->clientService->newClient();
512
			$body = self::generateClientBodyData(self::generateLinkData($link));
513
			$response = $client->post($this->generateLinkRemoteURL($link->getAddress()), $body);
514
			$result = parseRequestLinkResult($response);
515
516
			if ($result['status'] === -1) {
517
				throw new FederatedLinkUpdateException($result['reason']);
518
			}
519
520
			return true;
521
		} catch (Exception $e) {
522
			throw $e;
523
		}
524
	}
525
526
527
	/**
528
	 * Create a new link into database and assign the correct status.
529
	 *
530
	 * @param Circle $circle
531
	 * @param FederatedLink $link
532
	 *
533
	 * @throws Exception
534
	 */
535
	public function initiateLink(Circle $circle, FederatedLink &$link) {
536
537
		try {
538
			$this->checkLinkRequestValidity($circle, $link);
539
			$link->setCircleId($circle->getUniqueId());
540
541
			if ($circle->getSetting('allow_links_auto') === 'true') {
542
				$link->setStatus(FederatedLink::STATUS_LINK_UP);
543
				$this->eventsService->onLinkUp($circle, $link);
544
			} else {
545
				$link->setStatus(FederatedLink::STATUS_LINK_REQUESTED);
546
				$this->eventsService->onLinkRequestReceived($circle, $link);
547
			}
548
549
			$this->federatedLinksRequest->create($link);
550
		} catch (Exception $e) {
551
			throw $e;
552
		}
553
	}
554
555
556
	/**
557
	 * @param Circle $circle
558
	 * @param FederatedLink $link
559
	 *
560
	 * @throws FederatedLinkCreationException
561
	 */
562
	private function checkLinkRequestValidity($circle, $link) {
563
		if ($circle->getUniqueId(true) === $link->getUniqueId(true)) {
564
			throw new FederatedLinkCreationException('duplicate_unique_id');
565
		}
566
567
		try {
568
			$this->federatedLinksRequest->getLinkFromCircle(
569
				$circle->getUniqueId(), $link->getUniqueId(true)
570
			);
571
			throw new FederatedLinkCreationException('duplicate_link');
572
		} catch (FederatedLinkDoesNotExistException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
573
		}
574
575
		if ($circle->getSetting('allow_links') !== 'true') {
576
			throw new FederatedLinkCreationException('circle_links_disable');
577
		}
578
	}
579
580
581
	/**
582
	 * checkUpdateLinkFromRemoteLinkRemove();
583
	 *
584
	 * in case of a request of status update from remote for a link down, we check the current
585
	 * status of the link locally
586
	 *
587
	 * @param Circle $circle
588
	 * @param FederatedLink $link
589
	 * @param int $status
590
	 *
591
	 * @throws FederatedCircleStatusUpdateException
592
	 */
593
	private function checkUpdateLinkFromRemoteLinkRemove(Circle $circle, FederatedLink $link, $status) {
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 101 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
594
595
		if ((int)$status !== FederatedLink::STATUS_LINK_REMOVE) {
596
			return;
597
		}
598
599
		$curStatus = $link->getStatus();
600
		$this->checkUpdateLinkFromRemoteLinkRequestSent($circle, $link);
601
		$this->checkUpdateLinkFromRemoteLinkRequested($circle, $link);
602
		$this->checkUpdateLinkFromRemoteLinkDown($circle, $link);
603
604
		if ($curStatus !== $link->getStatus()) {
605
			return;
606
		}
607
608
		throw new FederatedCircleStatusUpdateException(
609
			$this->l10n->t('Cannot proceed with this status update')
610
		);
611
	}
612
613
614
	/**
615
	 * @param Circle $circle
616
	 * @param FederatedLink $link
617
	 */
618 View Code Duplication
	private function checkUpdateLinkFromRemoteLinkRequestSent(Circle $circle, FederatedLink &$link) {
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...
619
620
		if ($link->getStatus() !== FederatedLink::STATUS_REQUEST_SENT) {
621
			return;
622
		}
623
624
		$link->setStatus(FederatedLink::STATUS_REQUEST_DECLINED);
625
		$this->eventsService->onLinkRequestRejected($circle, $link);
626
	}
627
628
629
	/**
630
	 * @param Circle $circle
631
	 * @param FederatedLink $link
632
	 */
633 View Code Duplication
	private function checkUpdateLinkFromRemoteLinkRequested(Circle $circle, FederatedLink &$link) {
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...
634
635
		if ($link->getStatus() !== FederatedLink::STATUS_LINK_REQUESTED) {
636
			return;
637
		}
638
639
		$link->setStatus(FederatedLink::STATUS_LINK_REMOVE);
640
		$this->eventsService->onLinkRequestCanceled($circle, $link);
641
	}
642
643
644
	/**
645
	 * @param Circle $circle
646
	 * @param FederatedLink $link
647
	 */
648 View Code Duplication
	private function checkUpdateLinkFromRemoteLinkDown(Circle $circle, FederatedLink &$link) {
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...
649
650
		if ($link->getStatus() < FederatedLink::STATUS_LINK_DOWN) {
651
			return;
652
		}
653
654
		$link->setStatus(FederatedLink::STATUS_LINK_DOWN);
655
		$this->eventsService->onLinkDown($circle, $link);
656
	}
657
658
659
	/**
660
	 * @param FederatedLink $link
661
	 *
662
	 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,integer[]|string|integer>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
663
	 */
664
	private static function generateLinkData(FederatedLink $link) {
665
		return [
666
			'apiVersion' => Circles::version(),
667
			'token'      => $link->getToken(true),
668
			'uniqueId'   => $link->getCircleId(true),
669
			'linkTo'     => $link->getRemoteCircleName(),
670
			'address'    => $link->getLocalAddress()
671
		];
672
	}
673
674
675
	/**
676
	 * @param array $args
677
	 *
678
	 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,array|integer>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
679
	 */
680
	private static function generateClientBodyData($args) {
681
		return [
682
			'body'            => $args,
683
			'timeout'         => 5,
684
			'connect_timeout' => 5,
685
		];
686
	}
687
688
689
}