Completed
Pull Request — master (#384)
by Tortue
02:31
created

MembersService::addGroupMembers()   B

Complexity

Conditions 10
Paths 10

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 29
rs 7.6666
c 0
b 0
f 0
cc 10
nc 10
nop 2

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Circles - bring cloud-users closer
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;
32
use OC\User\NoUserException;
33
use OCA\Circles\Circles\FileSharingBroadcaster;
34
use OCA\Circles\Db\CirclesRequest;
35
use OCA\Circles\Db\MembersRequest;
36
use OCA\Circles\Db\SharesRequest;
37
use OCA\Circles\Db\TokensRequest;
38
use OCA\Circles\Exceptions\CircleDoesNotExistException;
39
use OCA\Circles\Exceptions\CircleTypeNotValidException;
40
use OCA\Circles\Exceptions\ConfigNoCircleAvailableException;
41
use OCA\Circles\Exceptions\EmailAccountInvalidFormatException;
42
use OCA\Circles\Exceptions\GroupDoesNotExistException;
43
use OCA\Circles\Exceptions\MemberAlreadyExistsException;
44
use OCA\Circles\Exceptions\MemberDoesNotExistException;
45
use OCA\Circles\Exceptions\MemberIsNotModeratorException;
46
use OCA\Circles\Exceptions\MemberIsOwnerException;
47
use OCA\Circles\Exceptions\MemberTypeCantEditLevelException;
48
use OCA\Circles\Exceptions\ModeratorIsNotHighEnoughException;
49
use OCA\Circles\Model\Circle;
50
use OCA\Circles\Model\Member;
51
use OCP\IGroup;
52
use OCP\IL10N;
53
use OCP\IUser;
54
use OCP\IUserManager;
55
56
57
/**
58
 * Class MembersService
59
 *
60
 * @package OCA\Circles\Service
61
 */
62
class MembersService {
63
64
	/** @var string */
65
	private $userId;
66
67
	/** @var IL10N */
68
	private $l10n;
69
70
	/** @var IUserManager */
71
	private $userManager;
72
73
	/** @var ConfigService */
74
	private $configService;
75
76
	/** @var CirclesRequest */
77
	private $circlesRequest;
78
79
	/** @var MembersRequest */
80
	private $membersRequest;
81
82
	/** @var SharesRequest */
83
	private $sharesRequest;
84
85
	/** @var TokensRequest */
86
	private $tokensRequest;
87
88
	/** @var CirclesService */
89
	private $circlesService;
90
91
	/** @var EventsService */
92
	private $eventsService;
93
94
	/** @var FileSharingBroadcaster */
95
	private $fileSharingBroadcaster;
96
97
	/** @var MiscService */
98
	private $miscService;
99
100
	/**
101
	 * MembersService constructor.
102
	 *
103
	 * @param string $userId
104
	 * @param IL10N $l10n
105
	 * @param IUserManager $userManager
106
	 * @param ConfigService $configService
107
	 * @param CirclesRequest $circlesRequest
108
	 * @param MembersRequest $membersRequest
109
	 * @param SharesRequest $sharesRequest
110
	 * @param TokensRequest $tokensRequest
111
	 * @param CirclesService $circlesService
112
	 * @param EventsService $eventsService
113
	 * @param FileSharingBroadcaster $fileSharingBroadcaster
114
	 * @param MiscService $miscService
115
	 */
116
	public function __construct(
117
		$userId, IL10N $l10n, IUserManager $userManager, ConfigService $configService,
118
		CirclesRequest $circlesRequest, MembersRequest $membersRequest, SharesRequest $sharesRequest,
119
		TokensRequest $tokensRequest, CirclesService $circlesService, EventsService $eventsService,
120
		FileSharingBroadcaster $fileSharingBroadcaster, MiscService $miscService
121
	) {
122
		$this->userId = $userId;
123
		$this->l10n = $l10n;
124
		$this->userManager = $userManager;
125
		$this->configService = $configService;
126
		$this->circlesRequest = $circlesRequest;
127
		$this->membersRequest = $membersRequest;
128
		$this->sharesRequest = $sharesRequest;
129
		$this->tokensRequest = $tokensRequest;
130
		$this->circlesService = $circlesService;
131
		$this->eventsService = $eventsService;
132
		$this->fileSharingBroadcaster = $fileSharingBroadcaster;
133
		$this->miscService = $miscService;
134
	}
135
136
137
	/**
138
	 * addMember();
139
	 *
140
	 * add a new member to a circle.
141
	 *
142
	 * @param string $circleUniqueId
143
	 * @param $ident
144
	 * @param int $type
145
	 *
146
	 * @param bool $force
147
	 *
148
	 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use Member[].

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...
149
	 * @throws Exception
150
	 */
151
	public function addMember($circleUniqueId, $ident, $type, bool $force = false) {
152
153 View Code Duplication
		if ($force === true) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
154
			$circle = $this->circlesRequest->forceGetCircle($circleUniqueId);
155
		} else {
156
			$circle = $this->circlesRequest->getCircle($circleUniqueId, $this->userId);
157
			$circle->getHigherViewer()
158
				   ->hasToBeModerator();
159
		}
160
161
		if (!$this->addMassiveMembers($circle, $ident, $type)) {
162
			$this->addSingleMember($circle, $ident, $type);
163
		}
164
165
		return $this->membersRequest->getMembers($circle->getUniqueId(), $circle->getHigherViewer(), $force);
166
	}
167
168
169
	/**
170
	 * add a single member to a circle.
171
	 *
172
	 * @param Circle $circle
173
	 * @param string $ident
174
	 * @param int $type
175
	 *
176
	 * @throws MemberAlreadyExistsException
177
	 * @throws Exception
178
	 */
179
	private function addSingleMember(Circle $circle, $ident, $type) {
180
		$this->verifyIdentBasedOnItsType($ident, $type);
181
		$this->verifyIdentWithGroupBackend($circle, $ident, $type);
182
183
		$member = $this->membersRequest->getFreshNewMember($circle->getUniqueId(), $ident, $type);
184
		$member->hasToBeInviteAble();
185
186
		$this->circlesService->checkThatCircleIsNotFull($circle);
187
188
		$this->addMemberBasedOnItsType($circle, $member);
189
190
		$this->membersRequest->updateMember($member);
191
		$this->fileSharingBroadcaster->sendMailAboutExistingShares($circle, $member);
192
		$this->eventsService->onMemberNew($circle, $member);
193
	}
194
195
196
	/**
197
	 * add a bunch of users to a circle based on the type of the 'bunch'
198
	 *
199
	 * @param Circle $circle
200
	 * @param string $ident
201
	 * @param int $type
202
	 *
203
	 * @return bool
204
	 * @throws Exception
205
	 */
206
	private function addMassiveMembers(Circle $circle, $ident, $type) {
207
208
		if ($type === Member::TYPE_GROUP) {
209
			return $this->addGroupMembers($circle, $ident);
210
		}
211
212
		if ($type === Member::TYPE_USER) {
213
			return $this->addMassiveMails($circle, $ident);
214
		}
215
216
		return false;
217
	}
218
219
220
	/**
221
	 * add a new member based on its type.
222
	 *
223
	 * @param Circle $circle
224
	 * @param Member $member
225
	 *
226
	 * @throws Exception
227
	 */
228
	private function addMemberBasedOnItsType(Circle $circle, Member &$member) {
229
		$this->addLocalMember($circle, $member);
230
		$this->addEmailAddress($member);
231
		$this->addContact($member);
232
	}
233
234
235
	/**
236
	 * @param Circle $circle
237
	 * @param Member $member
238
	 *
239
	 * @throws Exception
240
	 */
241
	private function addLocalMember(Circle $circle, Member $member) {
242
243
		if ($member->getType() !== Member::TYPE_USER) {
244
			return;
245
		}
246
247
		$member->inviteToCircle($circle->getType());
248
249
		if ($this->configService->isInvitationSkipped()) {
250
			$member->joinCircle($circle->getType());
251
		}
252
	}
253
254
255
	/**
256
	 * add mail address as contact.
257
	 *
258
	 * @param Member $member
259
	 *
260
	 * @throws Exception
261
	 */
262
	private function addEmailAddress(Member $member) {
263
264
		if ($member->getType() !== Member::TYPE_MAIL) {
265
			return;
266
		}
267
268
		$member->addMemberToCircle();
269
	}
270
271
272
	/**
273
	 * Add contact as member.
274
	 *
275
	 * @param Member $member
276
	 *
277
	 * @throws Exception
278
	 */
279
	private function addContact(Member $member) {
280
281
		if ($member->getType() !== Member::TYPE_CONTACT) {
282
			return;
283
		}
284
285
		$member->addMemberToCircle();
286
	}
287
288
289
	/**
290
	 * Verify the availability of an ident when Group Backend is enabled
291
	 *
292
	 * @param Circle $circle
293
	 * @param string $ident
294
	 * @param int $type
295
	 *
296
	 * @throws Exception
297
	 */
298
	private function verifyIdentWithGroupBackend(Circle $circle, $ident, $type) {
0 ignored issues
show
Unused Code introduced by
The parameter $ident is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
299
		if ($this->configService->isGroupsBackend() &&
300
			in_array($type, [Member::TYPE_MAIL, Member::TYPE_CONTACT], true) &&
301
			in_array($circle->getType(), [Circle::CIRCLES_CLOSED, Circle::CIRCLES_PUBLIC], true)
302
		) {
303
			if ($type === Member::TYPE_MAIL) {
304
				$errorMessage = 'You cannot add a mail address as member of your Circle';
305
			}
306
			if ($type === Member::TYPE_CONTACT) {
307
				$errorMessage = 'You cannot add a contact as member of your Circle';
308
			}
309
			throw new EmailAccountInvalidFormatException(
310
				$this->l10n->t($errorMessage)
311
			);
312
		}
313
	}
314
315
316
	/**
317
	 * Verify the availability of an ident, based on its type.
318
	 *
319
	 * @param string $ident
320
	 * @param int $type
321
	 *
322
	 * @throws Exception
323
	 */
324
	private function verifyIdentBasedOnItsType(&$ident, $type) {
325
		$this->verifyIdentLocalMember($ident, $type);
326
		$this->verifyIdentEmailAddress($ident, $type);
327
		$this->verifyIdentContact($ident, $type);
328
	}
329
330
331
	/**
332
	 * Verify if a local account is valid.
333
	 *
334
	 * @param $ident
335
	 * @param $type
336
	 *
337
	 * @throws NoUserException
338
	 */
339
	private function verifyIdentLocalMember(&$ident, $type) {
340
		if ($type !== Member::TYPE_USER) {
341
			return;
342
		}
343
344
		try {
345
			$ident = $this->miscService->getRealUserId($ident);
346
		} catch (NoUserException $e) {
0 ignored issues
show
Bug introduced by
The class OC\User\NoUserException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
347
			throw new NoUserException($this->l10n->t("This user does not exist"));
348
		}
349
	}
350
351
352
	/**
353
	 * Verify if a mail have a valid format.
354
	 *
355
	 * @param $ident
356
	 * @param $type
357
	 *
358
	 * @throws EmailAccountInvalidFormatException
359
	 */
360
	private function verifyIdentEmailAddress(&$ident, $type) {
361
362
		if ($type !== Member::TYPE_MAIL) {
363
			return;
364
		}
365
366
		if ($this->configService->isAccountOnly()) {
367
			throw new EmailAccountInvalidFormatException(
368
				$this->l10n->t('You cannot add a mail address as member of your Circle')
369
			);
370
		}
371
372
		if (!filter_var($ident, FILTER_VALIDATE_EMAIL)) {
373
			throw new EmailAccountInvalidFormatException(
374
				$this->l10n->t('Email format is not valid')
375
			);
376
		}
377
	}
378
379
380
	/**
381
	 * Verify if a contact exist in current user address books.
382
	 *
383
	 * @param $ident
384
	 * @param $type
385
	 *
386
	 * @throws NoUserException
387
	 * @throws EmailAccountInvalidFormatException
388
	 */
389
	private function verifyIdentContact(&$ident, $type) {
390
		if ($type !== Member::TYPE_CONTACT) {
391
			return;
392
		}
393
394
		if ($this->configService->isAccountOnly()) {
395
			throw new EmailAccountInvalidFormatException(
396
				$this->l10n->t('You cannot add a contact as member of your Circle')
397
			);
398
		}
399
400
		$tmpContact = $this->userId . ':' . $ident;
401
		$result = MiscService::getContactData($tmpContact);
402
		if (empty($result)) {
403
			throw new NoUserException($this->l10n->t("This contact is not available"));
404
		}
405
406
		$ident = $tmpContact;
407
	}
408
409
410
	/**
411
	 * @param Circle $circle
412
	 * @param string $groupId
413
	 *
414
	 * @return bool
415
	 * @throws Exception
416
	 */
417
	private function addGroupMembers(Circle $circle, $groupId) {
418
419
		$groupManager = OC::$server->getGroupManager();
420
		$group = $groupManager->get($groupId);
421
422
		$user = OC::$server->getUserSession()->getUser();
423
424
		if (!$this->configService->isAddingAnyGroupMembersAllowed() &&
425
			$group instanceof IGroup && $user instanceof IUser &&
0 ignored issues
show
Bug introduced by
The class OCP\IGroup does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
Bug introduced by
The class OCP\IUser does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
426
			!$group->inGroup($user) && !$groupManager->isAdmin($user->getUID())
427
		) {
428
			$group = null;
429
		}
430
431
		if ($group === null) {
432
			throw new GroupDoesNotExistException($this->l10n->t('This group does not exist'));
433
		}
434
435
		foreach ($group->getUsers() as $user) {
436
			try {
437
				$this->addSingleMember($circle, $user->getUID(), Member::TYPE_USER);
438
			} catch (MemberAlreadyExistsException $e) {
439
			} catch (Exception $e) {
440
				throw $e;
441
			}
442
		}
443
444
		return true;
445
	}
446
447
448
	/**
449
	 * @param Circle $circle
450
	 * @param string $mails
451
	 *
452
	 * @return bool
453
	 */
454
	private function addMassiveMails(Circle $circle, $mails) {
455
456
		$mails = trim($mails);
457
		if (substr($mails, 0, 6) !== 'mails:') {
458
			return false;
459
		}
460
461
		$mails = substr($mails, 6);
462
		foreach (explode(' ', $mails) as $mail) {
463
			if (!filter_var($mail, FILTER_VALIDATE_EMAIL)) {
464
				continue;
465
			}
466
467
			try {
468
				$this->addMember($circle->getUniqueId(), $mail, Member::TYPE_MAIL);
469
			} catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
470
			}
471
		}
472
473
		return true;
474
	}
475
476
477
	/**
478
	 * getMember();
479
	 *
480
	 * Will return any data of a user related to a circle (as a Member). User can be a 'non-member'
481
	 * Viewer needs to be at least Member of the Circle
482
	 *
483
	 * @param $circleId
484
	 * @param $userId
485
	 * @param $type
486
	 * @param bool $forceAll
487
	 *
488
	 * @return Member
489
	 * @throws CircleDoesNotExistException
490
	 * @throws ConfigNoCircleAvailableException
491
	 * @throws MemberDoesNotExistException
492
	 */
493
	public function getMember($circleId, $userId, $type, $forceAll = false) {
494
		if (!$forceAll) {
495
			$this->circlesRequest->getCircle($circleId, $this->userId)
496
								 ->getHigherViewer()
497
								 ->hasToBeMember();
498
		}
499
500
		$member = $this->membersRequest->forceGetMember($circleId, $userId, $type);
501
		$member->setNote('');
502
503
		return $member;
504
	}
505
506
507
	/**
508
	 * @param string $memberId
509
	 *
510
	 * @return Member
511
	 * @throws MemberDoesNotExistException
512
	 */
513
	public function getMemberById(string $memberId): Member {
514
		return $this->membersRequest->forceGetMemberById($memberId);
515
	}
516
517
518
	/**
519
	 * @param string $circleUniqueId
520
	 * @param string $name
521
	 * @param int $type
522
	 * @param int $level
523
	 * @param bool $force
524
	 *
525
	 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use Member[].

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...
526
	 * @throws CircleDoesNotExistException
527
	 * @throws CircleTypeNotValidException
528
	 * @throws ConfigNoCircleAvailableException
529
	 * @throws MemberDoesNotExistException
530
	 * @throws MemberTypeCantEditLevelException
531
	 * @throws Exception
532
	 */
533
	public function levelMember($circleUniqueId, $name, $type, $level, bool $force = false) {
534
535
		$level = (int)$level;
536
		if ($force === false) {
537
			$circle = $this->circlesRequest->getCircle($circleUniqueId, $this->userId);
538
		} else {
539
			$circle = $this->circlesRequest->forceGetCircle($circleUniqueId);
540
		}
541
542
		if ($circle->getType() === Circle::CIRCLES_PERSONAL) {
543
			throw new CircleTypeNotValidException(
544
				$this->l10n->t('You cannot edit level in a personal circle')
545
			);
546
		}
547
548
		$member = $this->membersRequest->forceGetMember($circle->getUniqueId(), $name, $type);
549
		$member->levelHasToBeEditable();
550
		$this->updateMemberLevel($circle, $member, $level, $force);
551
552 View Code Duplication
		if ($force === false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
553
			return $this->membersRequest->getMembers(
554
				$circle->getUniqueId(), $circle->getHigherViewer()
555
			);
556
		} else {
557
			return $this->membersRequest->forceGetMembers($circle->getUniqueId());
558
		}
559
560
	}
561
562
563
	/**
564
	 * @param Circle $circle
565
	 * @param Member $member
566
	 * @param $level
567
	 * @param bool $force
568
	 *
569
	 * @throws Exception
570
	 */
571
	private function updateMemberLevel(Circle $circle, Member $member, $level, bool $force = false) {
572
		if ($member->getLevel() === $level) {
573
			return;
574
		}
575
576
		if ($level === Member::LEVEL_OWNER) {
577
			$this->switchOwner($circle, $member, $force);
578
		} else {
579
			$this->editMemberLevel($circle, $member, $level, $force);
580
		}
581
582
		$this->eventsService->onMemberLevel($circle, $member);
583
	}
584
585
586
	/**
587
	 * @param Circle $circle
588
	 * @param Member $member
589
	 * @param $level
590
	 * @param bool $force
591
	 *
592
	 * @throws Exception
593
	 */
594
	private function editMemberLevel(Circle $circle, Member &$member, $level, bool $force = false) {
595
		if ($force === false) {
596
			$isMod = $circle->getHigherViewer();
597
			$isMod->hasToBeModerator();
598
			$isMod->hasToBeHigherLevel($level);
599
600
			$member->hasToBeMember();
601
			$isMod->hasToBeHigherLevel($member->getLevel());
602
		}
603
604
		$member->cantBeOwner();
605
606
		$member->setLevel($level);
607
		$this->membersRequest->updateMember($member);
608
	}
609
610
	/**
611
	 * @param Circle $circle
612
	 * @param Member $member
613
	 * @param bool $force
614
	 *
615
	 * @throws Exception
616
	 */
617
	private function switchOwner(Circle $circle, Member &$member, bool $force = false) {
618
		if ($force === false) {
619
			$isMod = $circle->getHigherViewer();
620
621
			// should already be possible from an NCAdmin, but not enabled in the frontend.
622
			$this->circlesService->hasToBeOwner($isMod);
623
		} else {
624
			$isMod = $circle->getOwner();
625
		}
626
627
		$member->hasToBeMember();
628
		$member->cantBeOwner();
629
630
		$member->setLevel(Member::LEVEL_OWNER);
631
		$this->membersRequest->updateMember($member);
632
633
		$isMod->setLevel(Member::LEVEL_ADMIN);
634
		$this->membersRequest->updateMember($isMod);
635
	}
636
637
638
	/**
639
	 * @param string $circleUniqueId
640
	 * @param string $name
641
	 * @param $type
642
	 * @param bool $force
643
	 *
644
	 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use Member[].

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...
645
	 * @throws CircleDoesNotExistException
646
	 * @throws ConfigNoCircleAvailableException
647
	 * @throws MemberDoesNotExistException
648
	 * @throws MemberIsNotModeratorException
649
	 * @throws MemberIsOwnerException
650
	 * @throws ModeratorIsNotHighEnoughException
651
	 */
652
	public function removeMember($circleUniqueId, $name, $type, bool $force = false) {
653
654 View Code Duplication
		if ($force === false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
655
			$circle = $this->circlesRequest->getCircle($circleUniqueId, $this->userId);
656
			$circle->getHigherViewer()
657
				   ->hasToBeModerator();
658
		} else {
659
			$circle = $this->circlesRequest->forceGetCircle($circleUniqueId);
660
		}
661
662
		$member = $this->membersRequest->forceGetMember($circleUniqueId, $name, $type);
663
		$member->hasToBeMemberOrAlmost();
664
		$member->cantBeOwner();
665
666
		if ($force === false) {
667
			$circle->getHigherViewer()
668
				   ->hasToBeHigherLevel($member->getLevel());
669
		}
670
671
		$this->eventsService->onMemberLeaving($circle, $member);
672
673
		$this->membersRequest->removeMember($member);
674
		$this->sharesRequest->removeSharesFromMember($member);
675
		$this->tokensRequest->removeTokensFromMember($member);
676
677 View Code Duplication
		if ($force === false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
678
			return $this->membersRequest->getMembers(
679
				$circle->getUniqueId(), $circle->getHigherViewer()
680
			);
681
		} else {
682
			return $this->membersRequest->forceGetMembers($circle->getUniqueId());
683
		}
684
	}
685
686
687
	/**
688
	 * When a user is removed, remove him from all Circles
689
	 *
690
	 * @param $userId
691
	 */
692
	public function onUserRemoved($userId) {
693
		$this->membersRequest->removeAllMembershipsFromUser($userId);
694
	}
695
696
697
}
698