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

GroupsBackendService   C

Complexity

Total Complexity 54

Size/Duplication

Total Lines 395
Duplicated Lines 8.1 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 0
Metric Value
wmc 54
lcom 1
cbo 6
dl 32
loc 395
rs 6.4799
c 0
b 0
f 0

28 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 17 1
A onAppEnabled() 0 5 2
A onCircleCreation() 0 38 4
A onCircleDestruction() 0 11 2
A onMemberNew() 16 16 4
A onMemberInvited() 0 3 1
A onMemberRequesting() 0 3 1
A onMemberLeaving() 16 16 4
A onMemberLevel() 0 3 1
A onMemberOwner() 0 3 1
A onGroupLink() 0 3 1
A onGroupUnlink() 0 3 1
A onGroupLevel() 0 3 1
A onLinkRequestSent() 0 3 1
A onLinkRequestReceived() 0 3 1
A onLinkRequestRejected() 0 3 1
A onLinkRequestCanceled() 0 3 1
A onLinkRequestAccepted() 0 3 1
A onLinkRequestAccepting() 0 3 1
A onLinkUp() 0 3 1
A onLinkDown() 0 3 1
A onLinkRemove() 0 3 1
A onSettingsChange() 0 12 1
A onGroupPostAddUser() 0 16 4
B onGroupPostRemoveUser() 0 25 7
A onGroupPostDelete() 0 10 4
A getCircleGroupName() 0 10 2
A setCircleGroupName() 0 9 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like GroupsBackendService often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use GroupsBackendService, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * Circles - Bring cloud-users closer together.
5
 *
6
 * This file is licensed under the Affero General Public License version 3 or
7
 * later. See the COPYING file.
8
 *
9
 * @author Maxence Lange <[email protected]>
10
 * @copyright 2017
11
 * @license GNU AGPL version 3 or any later version
12
 *
13
 * This program is free software: you can redistribute it and/or modify
14
 * it under the terms of the GNU Affero General Public License as
15
 * published by the Free Software Foundation, either version 3 of the
16
 * License, or (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU Affero General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU Affero General Public License
24
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
25
 *
26
 */
27
28
namespace OCA\Circles\Service;
29
30
// use Exception;
31
use OCP\App\ManagerEvent;
32
use OCA\Circles\Db\CirclesRequest;
33
use OCA\Circles\Db\MembersRequest;
34
use OCA\Circles\Model\Circle;
35
use OCA\Circles\Model\Member;
36
use OCP\EventDispatcher\GenericEvent;
37
use Symfony\Component\EventDispatcher\GenericEvent as SymfonyGenericEvent;
38
use OCP\IGroup;
39
use OCP\IUser;
40
use OCP\IGroupManager;
41
use OCP\IUserManager;
42
43
/**
44
 * Class GroupsBackendService
45
 *
46
 * @package OCA\Circles\Service
47
 */
48
class GroupsBackendService {
49
50
	/** @var string */
51
	protected $userId;
52
53
	/** @var Circle */
54
	protected $circle;
55
56
	/** @var Member */
57
	protected $member;
58
59
	/** @var IGroup */
60
	protected $group;
61
62
	/** @var IUser */
63
	protected $user;
64
65
	/** @var ConfigService */
66
	protected $configService;
67
68
	/** @var MiscService */
69
	protected $miscService;
70
71
	/** @var CirclesRequest */
72
	protected $circlesRequest;
73
74
	/** @var MembersRequest */
75
	protected $membersRequest;
76
77
	/** @var IGroupManager */
78
	protected $groupManager;
79
80
	/** @var IUserManager */
81
	protected $userManager;
82
83
	/**
84
	 * GroupsBackendService constructor.
85
	 *
86
	 * @param string $userId
87
	 * @param CirclesRequest $circlesRequest
88
	 * @param MembersRequest $membersRequest
89
	 * @param IGroupManager $groupManager
90
	 * @param IUserManager $userManager
91
	 * @param ConfigService $configService
92
	 * @param MiscService $miscService
93
	 */
94
	public function __construct(
95
		$userId,
96
		CirclesRequest $circlesRequest,
97
		MembersRequest $membersRequest,
98
		IGroupManager $groupManager,
99
		IUserManager $userManager,
100
		ConfigService $configService,
101
		MiscService $miscService
102
	) {
103
		$this->userId = $userId;
104
		$this->circlesRequest = $circlesRequest;
105
		$this->membersRequest = $membersRequest;
106
		$this->groupManager = $groupManager;
107
		$this->userManager = $userManager;
108
		$this->configService = $configService;
109
		$this->miscService = $miscService;
110
	}
111
112
	/**
113
	 * @param ManagerEvent $event
114
	 */
115
	public function onAppEnabled(ManagerEvent $event) {
116
		if ($event->getAppID() !== 'circles') {
117
			return;
118
		}
119
	}
120
121
	/**
122
	 * @param GenericEvent $event
123
	 */
124
	public function onCircleCreation(GenericEvent $event) {
125
		$this->circle = $event->getArgument('circle');
126
		// '\OC\Group', 'postDelete'
127
		// '\OC\Group', 'postAddUser'
128
		// '\OC\Group', 'postRemoveUser'
129
		// $eventName ='\OC\Group::postCreate';
130
131
		// $listeners = $this->eventDispatcher->getSymfonyDispatcher()->getListeners($eventName);
132
		// $this->miscService->log('number of listeners: '. count($listeners), 1);
133
134
		// foreach ($listeners as $listener) {
135
		// 	$this->miscService->log('remove listener: '. json_encode($listener), 1);
136
		// 	$this->eventDispatcher->getSymfonyDispatcher()->removeListener($eventName, $listener);
137
		// }
138
139
		$this->group = $this->groupManager->createGroup($this->getCircleGroupName());
140
141
		// foreach ($listeners as $listener) {
142
		// 	$this->miscService->log('add listener: '. json_encode($listener), 1);
143
		// 	$this->eventDispatcher->getSymfonyDispatcher()->addListener($eventName, $listener);
144
		// }
145
146
		if ($this->group) {
147
			$this->member = $this->circle->getOwner();
148
149
			$this->circle->setGroupId($this->group->getGID());
150
			$this->circlesRequest->updateCircle($this->circle, $this->member->getUserId());
151
152
			if ($this->member->getType() === Member::TYPE_USER) {
153
				$this->user = $this->userManager->get($this->member->getUserId());
154
				if ($this->user) {
155
					$this->group->addUser($this->user);
156
				}
157
			}
158
		}
159
160
		$this->miscService->log('onCircleCreation: '. json_encode($this->circle), 1);
161
	}
162
163
	/**
164
	 * @param GenericEvent $event
165
	 */
166
	public function onCircleDestruction(GenericEvent $event) {
167
		$this->circle = $event->getArgument('circle');
168
		$gid = $this->circle->getGroupId();
169
		$this->group = $this->groupManager->get($gid);
170
171
		if ($this->group) {
172
			$this->group->delete();
173
		}
174
175
		$this->miscService->log('onCircleDestruction: '. json_encode($this->circle), 1);
176
	}
177
178
	/**
179
	 * @param GenericEvent $event
180
	 */
181 View Code Duplication
	public function onMemberNew(GenericEvent $event) {
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...
182
		$this->circle = $event->getArgument('circle');
183
		$this->member = $event->getArgument('member');
184
185
		if ($this->member->getType() === Member::TYPE_USER) {
186
			$gid = $this->circle->getGroupId();
187
			$this->group = $this->groupManager->get($gid);
188
			$this->user = $this->userManager->get($this->member->getUserId());
189
190
			if ($this->group && $this->user) {
191
				$this->group->addUser($this->user);
192
			}
193
		}
194
195
		$this->miscService->log('onMemberNew: '. json_encode($this->circle).json_encode($this->member), 1);
196
	}
197
198
	/**
199
	 * @param GenericEvent $event
200
	 */
201
	public function onMemberInvited(GenericEvent $event) {
202
		$this->miscService->log('onMemberInvited: '. json_encode($event), 1);
203
	}
204
205
	/**
206
	 * @param GenericEvent $event
207
	 */
208
	public function onMemberRequesting(GenericEvent $event) {
209
		$this->miscService->log('onMemberRequesting: '. json_encode($event), 1);
210
	}
211
212
	/**
213
	 * @param GenericEvent $event
214
	 */
215 View Code Duplication
	public function onMemberLeaving(GenericEvent $event) {
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...
216
		$this->circle = $event->getArgument('circle');
217
		$this->member = $event->getArgument('member');
218
219
		if ($this->member->getType() === Member::TYPE_USER) {
220
			$gid = $this->circle->getGroupId();
221
			$this->group = $this->groupManager->get($gid);
222
			$this->user = $this->userManager->get($this->member->getUserId());
223
224
			if ($this->group && $this->user) {
225
				$this->group->removeUser($this->user);
226
			}
227
		}
228
229
		$this->miscService->log('onMemberLeaving: '. json_encode($this->circle).json_encode($this->member), 1);
230
	}
231
232
	/**
233
	 * @param GenericEvent $event
234
	 */
235
	public function onMemberLevel(GenericEvent $event) {
236
		$this->miscService->log('onMemberLevel: '. json_encode($event), 1);
237
	}
238
239
	/**
240
	 * @param GenericEvent $event
241
	 */
242
	public function onMemberOwner(GenericEvent $event) {
243
		$this->miscService->log('onMemberOwner: '. json_encode($event), 1);
244
	}
245
246
	/**
247
	 * @param GenericEvent $event
248
	 */
249
	public function onGroupLink(GenericEvent $event) {
250
		$this->miscService->log('onGroupLink: '. json_encode($event), 1);
251
	}
252
253
	/**
254
	 * @param GenericEvent $event
255
	 */
256
	public function onGroupUnlink(GenericEvent $event) {
257
		$this->miscService->log('onGroupUnlink: '. json_encode($event), 1);
258
	}
259
260
	/**
261
	 * @param GenericEvent $event
262
	 */
263
	public function onGroupLevel(GenericEvent $event) {
264
		$this->miscService->log('onGroupLevel: '. json_encode($event), 1);
265
	}
266
267
	/**
268
	 * @param GenericEvent $event
269
	 */
270
	public function onLinkRequestSent(GenericEvent $event) {
271
		$this->miscService->log('onLinkRequestSent: '. json_encode($event), 1);
272
	}
273
274
	/**
275
	 * @param GenericEvent $event
276
	 */
277
	public function onLinkRequestReceived(GenericEvent $event) {
278
		$this->miscService->log('onLinkRequestReceived: '. json_encode($event), 1);
279
	}
280
281
	/**
282
	 * @param GenericEvent $event
283
	 */
284
	public function onLinkRequestRejected(GenericEvent $event) {
285
		$this->miscService->log('onLinkRequestRejected: '. json_encode($event), 1);
286
	}
287
288
	/**
289
	 * @param GenericEvent $event
290
	 */
291
	public function onLinkRequestCanceled(GenericEvent $event) {
292
		$this->miscService->log('onLinkRequestCanceled: '. json_encode($event), 1);
293
	}
294
295
	/**
296
	 * @param GenericEvent $event
297
	 */
298
	public function onLinkRequestAccepted(GenericEvent $event) {
299
		$this->miscService->log('onLinkRequestAccepted: '. json_encode($event), 1);
300
	}
301
302
	/**
303
	 * @param GenericEvent $event
304
	 */
305
	public function onLinkRequestAccepting(GenericEvent $event) {
306
		$this->miscService->log('onLinkRequestAccepting: '. json_encode($event), 1);
307
	}
308
309
	/**
310
	 * @param GenericEvent $event
311
	 */
312
	public function onLinkUp(GenericEvent $event) {
313
		$this->miscService->log('onLinkUp: '. json_encode($event), 1);
314
	}
315
316
	/**
317
	 * @param GenericEvent $event
318
	 */
319
	public function onLinkDown(GenericEvent $event) {
320
		$this->miscService->log('onLinkDown: '. json_encode($event), 1);
321
	}
322
323
	/**
324
	 * @param GenericEvent $event
325
	 */
326
	public function onLinkRemove(GenericEvent $event) {
327
		$this->miscService->log('onLinkRemove: '. json_encode($event), 1);
328
	}
329
330
	/**
331
	 * @param GenericEvent $event
332
	 */
333
	public function onSettingsChange(GenericEvent $event) {
334
		$this->circle = $event->getArgument('circle');
335
		$oldSettings = $event->getArgument('oldSettings');
336
337
		$this->circle = $event->getArgument('circle');
338
		$gid = $this->circle->getGroupId();
339
		$this->group = $this->groupManager->get($gid);
340
341
		$this->setCircleGroupName($this->getCircleGroupName());
342
343
		$this->miscService->log('onSettingsChange: '. json_encode($this->circle).json_encode($oldSettings), 1);
344
	}
345
346
	/**
347
	 * When a group add a user, add it as a member of the associate Circle
348
	 *
349
	 * @param SymfonyGenericEvent $event
350
	 */
351
	public function onGroupPostAddUser(SymfonyGenericEvent $event) {
352
		$this->group = $event->getSubject();
353
		$this->user = $event->getArgument('user');
354
355
		$this->miscService->log('onGroupPostAddUser: '.json_encode($event).json_encode($this->group).json_encode($this->user), 1);
356
		if ($this->group instanceof IGroup && $this->group->getGID()) {
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...
357
			$this->circle = $this->circlesRequest->forceGetCircleByGroupId($this->group->getGID());
358
			if ($this->circle) {
359
				$this->member = $this->membersRequest->getFreshNewMember(
360
					$this->circle->getUniqueId(), $this->user->getUID(), Member::TYPE_USER
361
				);
362
				$this->member->addMemberToCircle();
363
				$this->membersRequest->updateMember($this->member);
364
			}
365
		}
366
	}
367
368
	/**
369
	 * When a group remove a user, remove it as a member of the associate Circle
370
	 *
371
	 * @param SymfonyGenericEvent $event
372
	 */
373
	public function onGroupPostRemoveUser(SymfonyGenericEvent $event) {
374
		$this->group = $event->getSubject();
375
		$this->user = $event->getArgument('user');
376
377
		$this->miscService->log('onGroupPostRemoveUser: '.json_encode($event).json_encode($this->group).json_encode($this->user), 1);
378
		if ($this->group instanceof IGroup && $this->group->getGID()) {
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...
379
			$this->circle = $this->circlesRequest->forceGetCircleByGroupId($this->group->getGID());
380
			if ($this->circle) {
381
				try {
382
					$this->member = $this->membersRequest->forceGetMember(
383
						$this->circle->getUniqueId(), $this->user->getUID(), Member::TYPE_USER
384
					);
385
					$this->member->hasToBeMember();
386
					$this->member->cantBeOwner();
387
				} catch (MemberDoesNotExistException $e) {
0 ignored issues
show
Bug introduced by
The class OCA\Circles\Service\MemberDoesNotExistException 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...
388
					$this->member = null;
389
				} catch (MemberIsOwnerException $e) {
0 ignored issues
show
Bug introduced by
The class OCA\Circles\Service\MemberIsOwnerException 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...
390
					$this->member = null;
391
				}
392
				if ($this->member) {
393
					$this->membersRequest->removeMember($this->member);
394
				}
395
			}
396
		}
397
	}
398
399
	/**
400
	 * When a group is removed, remove its associated Circle, if any
401
	 *
402
	 * @param SymfonyGenericEvent $event
403
	 */
404
	public function onGroupPostDelete(SymfonyGenericEvent $event) {
405
		$this->group = $event->getSubject();
406
		$this->miscService->log('onGroupPostDelete: '.json_encode($event).json_encode($this->group), 1);
407
		if ($this->group instanceof IGroup && $this->group->getGID()) {
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...
408
			$circle = $this->circlesRequest->forceGetCircleByGroupId($this->group->getGID());
409
			if ($circle) {
410
				$this->circlesRequest->destroyCircle($circle->getUniqueId());
411
			}
412
		}
413
	}
414
415
	/**
416
	 * @return string|null
417
	 */
418
	protected function getCircleGroupName()
419
	{
420
		if ($this->circle instanceof Circle) {
421
			return $this->configService->getGroupBackendNamePrefix().
422
					$this->circle->getName().
423
					$this->configService->getGroupBackendNameSuffix();
424
		}
425
426
		return;
427
	}
428
429
	/**
430
	 * @param  string $displayName
431
	 * @return bool
432
	 */
433
	protected function setCircleGroupName($displayName)
434
	{
435
		if ($this->group && method_exists($this->group, 'setDisplayName')) {
436
			$this->miscService->log('setCircleGroupName: '. json_encode($displayName), 1);
437
			return $this->group->setDisplayName($displayName);
438
		}
439
440
		return false;
441
	}
442
}
443