Completed
Pull Request — master (#362)
by Maxence
01:44
created

CirclesService::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 27

Duplication

Lines 27
Ratio 100 %

Importance

Changes 0
Metric Value
dl 27
loc 27
rs 9.488
c 0
b 0
f 0
cc 1
nc 1
nop 12

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
 * @author Vinicius Cubas Brand <[email protected]>
10
 * @author Daniel Tygel <[email protected]>
11
 *
12
 * @copyright 2017
13
 * @license GNU AGPL version 3 or any later version
14
 *
15
 * This program is free software: you can redistribute it and/or modify
16
 * it under the terms of the GNU Affero General Public License as
17
 * published by the Free Software Foundation, either version 3 of the
18
 * License, or (at your option) any later version.
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
26
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
27
 *
28
 */
29
30
namespace OCA\Circles\Service;
31
32
33
use Exception;
34
use OC;
35
use OCA\Circles\AppInfo\Application;
36
use OCA\Circles\Db\CircleProviderRequest;
37
use OCA\Circles\Db\CirclesRequest;
38
use OCA\Circles\Db\FederatedLinksRequest;
39
use OCA\Circles\Db\MembersRequest;
40
use OCA\Circles\Db\SharesRequest;
41
use OCA\Circles\Exceptions\CircleAlreadyExistsException;
42
use OCA\Circles\Exceptions\CircleDoesNotExistException;
43
use OCA\Circles\Exceptions\CircleTypeDisabledException;
44
use OCA\Circles\Exceptions\FederatedCircleNotAllowedException;
45
use OCA\Circles\Exceptions\MemberDoesNotExistException;
46
use OCA\Circles\Exceptions\MemberIsNotModeratorException;
47
use OCA\Circles\Exceptions\MemberIsNotOwnerException;
48
use OCA\Circles\Exceptions\MembersLimitException;
49
use OCA\Circles\Model\Circle;
50
use OCA\Circles\Model\GlobalScale\GSEvent;
51
use OCA\Circles\Model\Member;
52
use OCP\IGroupManager;
53
use OCP\IL10N;
54
55
class CirclesService {
56
57
	/** @var string */
58
	private $userId;
59
60
	/** @var IL10N */
61
	private $l10n;
62
63
	/** @var IGroupManager */
64
	private $groupManager;
65
66
	/** @var ConfigService */
67
	private $configService;
68
69
	/** @var CirclesRequest */
70
	private $circlesRequest;
71
72
	/** @var MembersRequest */
73
	private $membersRequest;
74
75
	/** @var SharesRequest */
76
	private $sharesRequest;
77
78
	/** @var FederatedLinksRequest */
79
	private $federatedLinksRequest;
80
81
	/** @var GSUpstreamService */
82
	private $gsUpstreamService;
83
84
	/** @var EventsService */
85
	private $eventsService;
86
87
	/** @var CircleProviderRequest */
88
	private $circleProviderRequest;
89
90
	/** @var MiscService */
91
	private $miscService;
92
93
94
	/**
95
	 * CirclesService constructor.
96
	 *
97
	 * @param string $userId
98
	 * @param IL10N $l10n
99
	 * @param IGroupManager $groupManager
100
	 * @param ConfigService $configService
101
	 * @param CirclesRequest $circlesRequest
102
	 * @param MembersRequest $membersRequest
103
	 * @param SharesRequest $sharesRequest
104
	 * @param FederatedLinksRequest $federatedLinksRequest
105
	 * @param GSUpstreamService $gsUpstreamService
106
	 * @param EventsService $eventsService
107
	 * @param CircleProviderRequest $circleProviderRequest
108
	 * @param MiscService $miscService
109
	 */
110 View Code Duplication
	public function __construct(
111
		$userId,
112
		IL10N $l10n,
113
		IGroupManager $groupManager,
114
		ConfigService $configService,
115
		CirclesRequest $circlesRequest,
116
		MembersRequest $membersRequest,
117
		SharesRequest $sharesRequest,
118
		FederatedLinksRequest $federatedLinksRequest,
119
		GSUpstreamService $gsUpstreamService,
120
		EventsService $eventsService,
121
		CircleProviderRequest $circleProviderRequest,
122
		MiscService $miscService
123
	) {
124
		$this->userId = $userId;
125
		$this->l10n = $l10n;
126
		$this->groupManager = $groupManager;
127
		$this->configService = $configService;
128
		$this->circlesRequest = $circlesRequest;
129
		$this->membersRequest = $membersRequest;
130
		$this->sharesRequest = $sharesRequest;
131
		$this->federatedLinksRequest = $federatedLinksRequest;
132
		$this->gsUpstreamService = $gsUpstreamService;
133
		$this->eventsService = $eventsService;
134
		$this->circleProviderRequest = $circleProviderRequest;
135
		$this->miscService = $miscService;
136
	}
137
138
139
	/**
140
	 * Create circle using this->userId as owner
141
	 *
142
	 * @param int|string $type
143
	 * @param string $name
144
	 *
145
	 * @return Circle
146
	 * @throws CircleTypeDisabledException
147
	 * @throws Exception
148
	 */
149
	public function createCircle($type, $name) {
150
		$type = $this->convertTypeStringToBitValue($type);
151
		$type = (int)$type;
152
153
		if ($type === '') {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of $type (integer) and '' (string) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
154
			throw new CircleTypeDisabledException(
155
				$this->l10n->t('You need a specify a type of circle')
156
			);
157
		}
158
159
		if (!$this->configService->isCircleAllowed($type)) {
160
			throw new CircleTypeDisabledException(
161
				$this->l10n->t('You cannot create this type of circle')
162
			);
163
		}
164
165
		$circle = new Circle($type, $name);
166
167
//		try {
168
		$circle->generateUniqueId();
169
		// TODO: check uniqueness !!
170
		// TODO: check uniqueness !!
171
		// TODO: check uniqueness !!
172
		// TODO: check uniqueness !!
173
//		$this->circlesRequest->createCircle($circle, $this->userId);
174
175
		$owner = new Member($this->userId, Member::TYPE_USER);
176
		$owner->setCircleId($circle->getUniqueId())
177
			  ->setLevel(Member::LEVEL_OWNER)
178
			  ->setStatus(Member::STATUS_MEMBER);
179
		$circle->setOwner($owner)
180
			   ->setViewer($owner);
181
182
//			$this->membersRequest->createMember($circle->getOwner());
183
184
		$event = new GSevent(GSEvent::CIRCLE_CREATE, true);
185
		$event->setCircle($circle);
186
		$this->gsUpstreamService->newEvent($event);
187
188
//		} catch (CircleAlreadyExistsException $e) {
189
//			throw $e;
190
//		}
191
192
//		$this->eventsService->onCircleCreation($circle);
193
194
		return $circle;
195
	}
196
197
198
	/**
199
	 * list Circles depends on type (or all) and name (parts) and minimum level.
200
	 *
201
	 * @param string $userId
202
	 * @param mixed $type
203
	 * @param string $name
204
	 * @param int $level
205
	 *
206
	 * @param bool $forceAll
207
	 *
208
	 * @return Circle[]
209
	 * @throws CircleTypeDisabledException
210
	 * @throws Exception
211
	 */
212
	public function listCircles($userId, $type, $name = '', $level = 0, $forceAll = false) {
213
		$type = $this->convertTypeStringToBitValue($type);
214
215
		if ($userId === '') {
216
			throw new Exception('UserID cannot be null');
217
		}
218
219
		if (!$this->configService->isCircleAllowed((int)$type)) {
220
			throw new CircleTypeDisabledException(
221
				$this->l10n->t('You cannot display this type of circle')
222
			);
223
		}
224
225
		$data = [];
226
		$result = $this->circlesRequest->getCircles($userId, $type, $name, $level, $forceAll);
227
		foreach ($result as $item) {
228
			$data[] = $item;
229
		}
230
231
		return $data;
232
	}
233
234
235
	/**
236
	 * returns details on circle and its members if this->userId is a member itself.
237
	 *
238
	 * @param string $circleUniqueId
239
	 * @param bool $forceAll
240
	 *
241
	 * @return Circle
242
	 * @throws Exception
243
	 */
244
	public function detailsCircle($circleUniqueId, $forceAll = false) {
245
246
		try {
247
			$circle = $this->circlesRequest->getCircle($circleUniqueId, $this->userId, '', $forceAll);
248
			if ($this->viewerIsAdmin()
249
				|| $circle->getHigherViewer()
250
						  ->isLevel(Member::LEVEL_MEMBER)
251
				|| $forceAll === true
252
			) {
253
				$this->detailsCircleMembers($circle);
254
				$this->detailsCircleLinkedGroups($circle);
255
				$this->detailsCircleFederatedCircles($circle);
256
			}
257
		} catch (Exception $e) {
258
			throw $e;
259
		}
260
261
		return $circle;
262
	}
263
264
265
	/**
266
	 * get the Members list and add the result to the Circle.
267
	 *
268
	 * @param Circle $circle
269
	 *
270
	 * @throws Exception
271
	 */
272
	private function detailsCircleMembers(Circle &$circle) {
273
		if ($this->viewerIsAdmin()) {
274
			$members = $this->membersRequest->forceGetMembers($circle->getUniqueId(), 0);
275
		} else {
276
			$members = $this->membersRequest->getMembers(
277
				$circle->getUniqueId(), $circle->getHigherViewer()
278
			);
279
		}
280
281
		$circle->setMembers($members);
282
	}
283
284
285
	/**
286
	 * get the Linked Group list and add the result to the Circle.
287
	 *
288
	 * @param Circle $circle
289
	 *
290
	 * @throws MemberDoesNotExistException
291
	 */
292
	private function detailsCircleLinkedGroups(Circle &$circle) {
293
		$groups = [];
294
		if ($this->configService->isLinkedGroupsAllowed()) {
295
			$groups =
296
				$this->membersRequest->getGroupsFromCircle(
297
					$circle->getUniqueId(), $circle->getHigherViewer()
298
				);
299
		}
300
301
		$circle->setGroups($groups);
302
	}
303
304
305
	/**
306
	 * get the Federated Circles list and add the result to the Circle.
307
	 *
308
	 * @param Circle $circle
309
	 */
310
	private function detailsCircleFederatedCircles(Circle &$circle) {
311
		$links = [];
312
313
		try {
314
			if ($this->configService->isFederatedCirclesAllowed()) {
315
				$circle->hasToBeFederated();
316
				$links = $this->federatedLinksRequest->getLinksFromCircle($circle->getUniqueId());
317
			}
318
		} catch (FederatedCircleNotAllowedException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
319
		}
320
321
		$circle->setLinks($links);
322
	}
323
324
325
	/**
326
	 * save new settings if current user is admin.
327
	 *
328
	 * @param string $circleUniqueId
329
	 * @param array $settings
330
	 *
331
	 * @return Circle
332
	 * @throws Exception
333
	 */
334
	public function settingsCircle($circleUniqueId, $settings) {
335
336
		try {
337
			$circle = $this->circlesRequest->getCircle($circleUniqueId, $this->userId);
338
			$this->hasToBeOwner($circle->getHigherViewer());
339
340
			if (!$this->viewerIsAdmin()) {
341
				$settings['members_limit'] = $circle->getSetting('members_limit');
342
			}
343
344
			$ak = array_keys($settings);
345
			foreach ($ak AS $k) {
346
				$circle->setSetting($k, $settings[$k]);
347
			}
348
349
			$this->circlesRequest->updateCircle($circle, $this->userId);
350
351
			$this->eventsService->onSettingsChange($circle);
352
		} catch (Exception $e) {
353
			throw $e;
354
		}
355
356
		return $circle;
357
	}
358
359
360
	/**
361
	 * Join a circle.
362
	 *
363
	 * @param string $circleUniqueId
364
	 *
365
	 * @return null|Member
366
	 * @throws Exception
367
	 */
368
	public function joinCircle($circleUniqueId) {
369
		try {
370
			$circle = $this->circlesRequest->getCircle($circleUniqueId, $this->userId);
371
			$member = $this->membersRequest->getFreshNewMember(
372
				$circleUniqueId, $this->userId, Member::TYPE_USER, ''
373
			);
374
375
			$event = new GSevent(GSEvent::MEMBER_JOIN);
376
			$event->setCircle($circle);
377
			$event->setMember($member);
378
			$this->gsUpstreamService->newEvent($event);
379
		} catch (Exception $e) {
380
			throw $e;
381
		}
382
383
		return $member;
384
	}
385
386
387
	/**
388
	 * Leave a circle.
389
	 *
390
	 * @param string $circleUniqueId
391
	 *
392
	 * @return null|Member
393
	 * @throws Exception
394
	 */
395
	public function leaveCircle($circleUniqueId) {
396
397
		$circle = $this->circlesRequest->getCircle($circleUniqueId, $this->userId);
398
		$member = $circle->getViewer();
399
400
		$member->hasToBeMemberOrAlmost();
401
		$member->cantBeOwner();
402
403
		$this->eventsService->onMemberLeaving($circle, $member);
404
405
		$this->membersRequest->removeMember($member);
406
		$this->sharesRequest->removeSharesFromMember($member);
407
408
		return $member;
409
	}
410
411
412
	/**
413
	 * destroy a circle.
414
	 *
415
	 * @param string $circleUniqueId
416
	 *
417
	 * @throws CircleDoesNotExistException
418
	 * @throws MemberIsNotModeratorException
419
	 * @throws MemberIsNotOwnerException
420
	 */
421
	public function removeCircle($circleUniqueId) {
422
423
		$circle = $this->circlesRequest->getCircle($circleUniqueId, $this->userId);
424
425
		$this->hasToBeOwner($circle->getHigherViewer());
426
427
		$this->eventsService->onCircleDestruction($circle);
428
429
		$this->membersRequest->removeAllFromCircle($circleUniqueId);
430
		$this->circlesRequest->destroyCircle($circleUniqueId);
431
	}
432
433
434
	/**
435
	 * @param $circleName
436
	 *
437
	 * @return Circle|null
438
	 * @throws CircleDoesNotExistException
439
	 */
440
	public function infoCircleByName($circleName) {
441
		return $this->circlesRequest->forceGetCircleByName($circleName);
442
	}
443
444
445
	/**
446
	 * When a user is removed.
447
	 * Before deleting a user from the cloud, we assign a new owner to his Circles.
448
	 * Remove the Circle if it has no admin.
449
	 *
450
	 * @param string $userId
451
	 */
452
	public function onUserRemoved($userId) {
453
		$circles = $this->circlesRequest->getCircles($userId, 0, '', Member::LEVEL_OWNER);
454
455
		foreach ($circles as $circle) {
456
457
			$members =
458
				$this->membersRequest->forceGetMembers($circle->getUniqueId(), Member::LEVEL_ADMIN);
459
460
			if (sizeof($members) === 1) {
461
				$this->circlesRequest->destroyCircle($circle->getUniqueId());
462
				continue;
463
			}
464
465
			$this->switchOlderAdminToOwner($circle, $members);
466
		}
467
	}
468
469
470
	/**
471
	 * switchOlderAdminToOwner();
472
	 *
473
	 * @param Circle $circle
474
	 * @param Member[] $members
475
	 */
476
	private function switchOlderAdminToOwner(Circle $circle, $members) {
477
478
		foreach ($members as $member) {
479
			if ($member->getLevel() === Member::LEVEL_ADMIN) {
480
				$member->setLevel(Member::LEVEL_OWNER);
481
				$this->membersRequest->updateMember($member);
482
				$this->eventsService->onMemberOwner($circle, $member);
483
484
				return;
485
			}
486
		}
487
488
	}
489
490
491
	/**
492
	 * Convert a Type in String to its Bit Value
493
	 *
494
	 * @param string $type
495
	 *
496
	 * @return int|mixed
497
	 */
498
	public function convertTypeStringToBitValue($type) {
499
		$strings = [
500
			'personal' => Circle::CIRCLES_PERSONAL,
501
			'secret'   => Circle::CIRCLES_SECRET,
502
			'closed'   => Circle::CIRCLES_CLOSED,
503
			'public'   => Circle::CIRCLES_PUBLIC,
504
			'all'      => Circle::CIRCLES_ALL
505
		];
506
507
		if (!key_exists(strtolower($type), $strings)) {
508
			return $type;
509
		}
510
511
		return $strings[strtolower($type)];
512
	}
513
514
515
	/**
516
	 * getCircleIcon()
517
	 *
518
	 * Return the right imagePath for a type of circle.
519
	 *
520
	 * @param string $type
521
	 * @param bool $png
522
	 *
523
	 * @return string
524
	 */
525
	public static function getCircleIcon($type, $png = false) {
526
527
		$ext = '.svg';
528
		if ($png === true) {
529
			$ext = '.png';
530
		}
531
532
		$urlGen = OC::$server->getURLGenerator();
533
		switch ($type) {
534
			case Circle::CIRCLES_PERSONAL:
535
				return $urlGen->getAbsoluteURL(
536
					$urlGen->imagePath(Application::APP_NAME, 'personal' . $ext)
537
				);
538
			case Circle::CIRCLES_CLOSED:
539
				return $urlGen->getAbsoluteURL(
540
					$urlGen->imagePath(Application::APP_NAME, 'closed' . $ext)
541
				);
542
			case Circle::CIRCLES_SECRET:
543
				return $urlGen->getAbsoluteURL(
544
					$urlGen->imagePath(Application::APP_NAME, 'secret' . $ext)
545
				);
546
			case Circle::CIRCLES_PUBLIC:
547
				return $urlGen->getAbsoluteURL(
548
					$urlGen->imagePath(Application::APP_NAME, 'black_circle' . $ext)
549
				);
550
		}
551
552
		return $urlGen->getAbsoluteURL(
553
			$urlGen->imagePath(Application::APP_NAME, 'black_circle' . $ext)
554
		);
555
	}
556
557
558
	/**
559
	 * @param string $circleUniqueIds
560
	 * @param int $limit
561
	 * @param int $offset
562
	 *
563
	 * @return array
564
	 */
565
	public function getFilesForCircles($circleUniqueIds, $limit = -1, $offset = 0) {
566
		if (!is_array($circleUniqueIds)) {
567
			$circleUniqueIds = [$circleUniqueIds];
568
		}
569
570
		$objectIds = $this->circleProviderRequest->getFilesForCircles(
571
			$this->userId, $circleUniqueIds, $limit, $offset
572
		);
573
574
		return $objectIds;
575
	}
576
577
578
	/**
579
	 * @param Circle $circle
580
	 *
581
	 * @throws MembersLimitException
582
	 */
583
	public function checkThatCircleIsNotFull(Circle $circle) {
584
585
		$members = $this->membersRequest->forceGetMembers(
586
			$circle->getUniqueId(), Member::LEVEL_MEMBER, true
587
		);
588
589
		$limit = $circle->getSetting('members_limit');
590
		if ($limit === -1) {
591
			return;
592
		}
593
		if ($limit === 0 || $limit === '' || $limit === null) {
594
			$limit = $this->configService->getAppValue(ConfigService::CIRCLES_MEMBERS_LIMIT);
595
		}
596
597
		if (sizeof($members) >= $limit) {
598
			throw new MembersLimitException(
599
				'This circle already reach its limit on the number of members'
600
			);
601
		}
602
603
	}
604
605
	/**
606
	 * @return bool
607
	 */
608
	public function viewerIsAdmin() {
609
		if ($this->userId === '') {
610
			return false;
611
		}
612
613
		return ($this->groupManager->isAdmin($this->userId));
614
	}
615
616
617
	/**
618
	 * should be moved.
619
	 *
620
	 * @param Member $member
621
	 *
622
	 * @throws MemberIsNotOwnerException
623
	 */
624 View Code Duplication
	public function hasToBeOwner(Member $member) {
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...
625
		if (!$this->groupManager->isAdmin($this->userId)
626
			&& $member->getLevel() < Member::LEVEL_OWNER) {
627
			throw new MemberIsNotOwnerException(
628
				$this->l10n->t('This member is not the owner of the circle')
629
			);
630
		}
631
	}
632
633
634
	/**
635
	 * should be moved.
636
	 *
637
	 * @param Member $member
638
	 *
639
	 * @throws MemberIsNotOwnerException
640
	 */
641 View Code Duplication
	public function hasToBeAdmin(Member $member) {
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...
642
		if (!$this->groupManager->isAdmin($member->getUserId())
643
			&& $member->getLevel() < Member::LEVEL_ADMIN) {
644
			throw new MemberIsNotOwnerException(
645
				$this->l10n->t('This member is not an admin of the circle')
646
			);
647
		}
648
	}
649
}
650