Completed
Pull Request — master (#442)
by Maxence
01:59
created

EventsService::onMemberRequesting()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23

Duplication

Lines 23
Ratio 100 %

Importance

Changes 0
Metric Value
dl 23
loc 23
rs 9.552
c 0
b 0
f 0
cc 2
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
 * @author: Vinicius Cubas Brand <[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 OCA\Circles\AppInfo\Application;
31
use OCA\Circles\Db\CirclesRequest;
32
use OCA\Circles\Db\MembersRequest;
33
use OCA\Circles\Model\Circle;
34
use OCA\Circles\Model\FederatedLink;
35
use OCA\Circles\Model\Member;
36
use OCP\Activity\IEvent;
37
use OCP\Activity\IManager as IActivityManager;
38
use OCP\AppFramework\Utility\ITimeFactory;
39
use OCP\IURLGenerator;
40
use OCP\IUser;
41
use OCP\IUserManager;
42
use OCP\Notification\IManager as INotificationManager;
43
use OCP\Notification\INotification;
44
use Symfony\Component\EventDispatcher\EventDispatcher;
45
use Symfony\Component\EventDispatcher\GenericEvent;
46
47
class EventsService {
48
49
50
	/** @var string */
51
	private $userId;
52
53
	/** @var ITimeFactory */
54
	private $time;
55
56
	/** @var IActivityManager */
57
	private $activityManager;
58
59
	/** @var INotificationManager */
60
	private $notificationManager;
61
62
	/** @var IUserManager */
63
	private $userManager;
64
65
	/** @var IURLGenerator */
66
	private $urlGenerator;
67
68
	/** @var EventDispatcher */
69
	private $eventDispatcher;
70
71
	/** @var CirclesRequest */
72
	private $circlesRequest;
73
74
	/** @var MembersRequest */
75
	private $membersRequest;
76
77
	/** @var ConfigService */
78
	private $configService;
79
80
	/** @var MiscService */
81
	private $miscService;
82
83
84
	/**
85
	 * Events constructor.
86
	 *
87
	 * @param string $userId
88
	 * @param ITimeFactory $time
89
	 * @param IActivityManager $activityManager
90
	 * @param INotificationManager $notificationManager
91
	 * @param IUserManager $userManager
92
	 * @param IURLGenerator $urlGenerator
93
	 * @param EventDispatcher $eventDispatcher
94
	 * @param CirclesRequest $circlesRequest
95
	 * @param MembersRequest $membersRequest
96
	 * @param ConfigService $configService
97
	 * @param MiscService $miscService
98
	 */
99 View Code Duplication
	public function __construct(
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...
100
		$userId, ITimeFactory $time, IActivityManager $activityManager,
101
		INotificationManager $notificationManager, IUserManager $userManager, IURLGenerator $urlGenerator,
102
		EventDispatcher $eventDispatcher, CirclesRequest $circlesRequest, MembersRequest $membersRequest,
103
		ConfigService $configService, MiscService $miscService
104
	) {
105
		$this->userId = $userId;
106
		$this->time = $time;
107
		$this->activityManager = $activityManager;
108
		$this->notificationManager = $notificationManager;
109
		$this->userManager = $userManager;
110
		$this->urlGenerator = $urlGenerator;
111
		$this->eventDispatcher = $eventDispatcher;
112
		$this->circlesRequest = $circlesRequest;
113
		$this->membersRequest = $membersRequest;
114
		$this->configService = $configService;
115
		$this->miscService = $miscService;
116
	}
117
118
119
	/**
120
	 * onCircleCreation()
121
	 *
122
	 * Called when a circle is created.
123
	 * Broadcast an activity to the cloud
124
	 * We won't do anything if the circle is not PUBLIC or CLOSED
125
	 *
126
	 * @param Circle $circle
127
	 */
128
	public function onCircleCreation(Circle $circle) {
129
		if ($circle->getType() !== Circle::CIRCLES_PUBLIC
130
			&& $circle->getType() !== Circle::CIRCLES_CLOSED) {
131
			return;
132
		}
133
134
		if ($this->configService->getAppValue(ConfigService::CIRCLES_ACTIVITY_ON_CREATION) === '1') {
135
			$event = $this->generateEvent('circles_as_non_member');
136
			$event->setSubject('circle_create', ['circle' => json_encode($circle)]);
137
138
			$this->userManager->callForSeenUsers(
139
				function($user) use ($event) {
140
					/** @var IUser $user */
141
					$this->publishEvent($event, [$user]);
142
				}
143
			);
144
		}
145
146
		$this->dispatch('\OCA\Circles::onCircleCreation', ['circle' => $circle]);
147
	}
148
149
150
	/**
151
	 * onCircleDestruction()
152
	 *
153
	 * Called when a circle is destroyed.
154
	 * Broadcast an activity on its members.
155
	 * We won't do anything if the circle is PERSONAL
156
	 *
157
	 * @param Circle $circle
158
	 */
159
	public function onCircleDestruction(Circle $circle) {
160
		if ($circle->getType() === Circle::CIRCLES_PERSONAL) {
161
			return;
162
		}
163
164
		$event = $this->generateEvent('circles_as_member');
165
		$event->setSubject('circle_delete', ['circle' => json_encode($circle)]);
166
		$this->publishEvent(
167
			$event,
168
			$this->membersRequest->forceGetMembers($circle->getUniqueId(), Member::LEVEL_MEMBER, 0, true)
169
		);
170
171
		$this->dispatch('\OCA\Circles::onCircleDestruction', ['circle' => $circle]);
172
	}
173
174
175
	/**
176
	 * onMemberNew()
177
	 *
178
	 * Called when a member is added to a circle.
179
	 * Broadcast an activity to the new member and to the moderators of the circle.
180
	 * We won't do anything if the circle is PERSONAL
181
	 * If the level is still 0, we will redirect to onMemberAlmost and manage the
182
	 * invitation/request from there
183
	 * If the level is Owner, we ignore the event.
184
	 *
185
	 * @param Circle $circle
186
	 * @param Member $member
187
	 */
188
	public function onMemberNew(Circle $circle, Member $member) {
189
		if ($member->getLevel() === Member::LEVEL_OWNER
190
			|| $circle->getType() === Circle::CIRCLES_PERSONAL
191
		) {
192
			return;
193
		}
194
195
		if ($member->getLevel() === Member::LEVEL_NONE) {
196
			$this->onMemberAlmost($circle, $member);
197
198
			return;
199
		}
200
201
		$event = $this->generateEvent('circles_as_member');
202
		$event->setSubject(
203
			($this->userId === $member->getUserId()) ? 'member_join' : 'member_add',
204
			['circle' => json_encode($circle), 'member' => json_encode($member)]
205
		);
206
207
		$this->publishEvent(
208
			$event, array_merge(
209
					  [$member],
210
					  $this->membersRequest->forceGetMembers(
211
						  $circle->getUniqueId(), Member::LEVEL_MODERATOR, 0, true
212
					  )
213
				  )
214
		);
215
216
		$this->dispatch('\OCA\Circles::onMemberNew', ['circle' => $circle, 'member' => $member]);
217
218
		$this->notificationOnMemberNew($circle, $member);
219
	}
220
221
222
	/**
223
	 * onMemberAlmost()
224
	 *
225
	 * Called when a member is added to a circle with level=0
226
	 * Trigger onMemberInvitation() or onMemberInvitationRequest() based on Member Status
227
	 *
228
	 * @param Circle $circle
229
	 * @param Member $member
230
	 */
231
	private function onMemberAlmost(Circle $circle, Member $member) {
232
233
		switch ($member->getStatus()) {
234
			case Member::STATUS_INVITED:
235
				$this->onMemberInvited($circle, $member);
236
237
				return;
238
239
			case Member::STATUS_REQUEST:
240
				$this->onMemberRequesting($circle, $member);
241
242
				return;
243
		}
244
	}
245
246
247
	/**
248
	 * onMemberInvited()
249
	 *
250
	 * Called when a member is invited to a circle.
251
	 * Broadcast an activity to the invited member and to the moderators of the circle.
252
	 *
253
	 * @param Circle $circle
254
	 * @param Member $member
255
	 */
256 View Code Duplication
	private function onMemberInvited(Circle $circle, 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...
257
		if ($circle->getType() !== Circle::CIRCLES_CLOSED) {
258
			return;
259
		}
260
261
		$event = $this->generateEvent('circles_as_moderator');
262
		$event->setSubject(
263
			'member_invited', ['circle' => json_encode($circle), 'member' => json_encode($member)]
264
		);
265
266
		$this->publishEvent(
267
			$event, array_merge(
268
					  [$member],
269
					  $this->membersRequest->forceGetMembers(
270
						  $circle->getUniqueId(), Member::LEVEL_MODERATOR, 0, true
271
					  )
272
				  )
273
		);
274
		$this->dispatch('\OCA\Circles::onMemberInvited', ['circle' => $circle, 'member' => $member]);
275
276
		$this->notificationOnInvitation($circle, $member);
277
	}
278
279
280
	/**
281
	 * onMemberRequesting()
282
	 *
283
	 * Called when a member request an invitation to a private circle.
284
	 * Broadcast an activity to the requester and to the moderators of the circle.
285
	 *
286
	 * @param Circle $circle
287
	 * @param Member $member
288
	 */
289 View Code Duplication
	private function onMemberRequesting(Circle $circle, 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...
290
		if ($circle->getType() !== Circle::CIRCLES_CLOSED) {
291
			return;
292
		}
293
294
		$event = $this->generateEvent('circles_as_moderator');
295
		$event->setSubject(
296
			'member_request_invitation',
297
			['circle' => json_encode($circle), 'member' => json_encode($member)]
298
		);
299
300
		$this->publishEvent(
301
			$event, array_merge(
302
					  [$member],
303
					  $this->membersRequest->forceGetMembers(
304
						  $circle->getUniqueId(), Member::LEVEL_MODERATOR, 0, true
305
					  )
306
				  )
307
		);
308
		$this->dispatch('\OCA\Circles::onMemberRequesting', ['circle' => $circle, 'member' => $member]);
309
310
		$this->notificationOnRequest($circle, $member);
311
	}
312
313
314
	/**
315
	 * onMemberLeaving()
316
	 *
317
	 * Called when a member is removed from a circle.
318
	 * Broadcast an activity to the leaving member and to the moderators of the circle.
319
	 * We won't do anything if the circle is PERSONAL
320
	 *
321
	 * @param Circle $circle
322
	 * @param Member $member
323
	 */
324
	public function onMemberLeaving(Circle $circle, Member $member) {
325
		if ($circle->getType() === Circle::CIRCLES_PERSONAL) {
326
			return;
327
		}
328
329
		$event = $this->generateEvent('circles_as_member');
330
		$event->setSubject(
331
			($this->userId === $member->getUserId()) ? 'member_left' : 'member_remove',
332
			['circle' => json_encode($circle), 'member' => json_encode($member)]
333
		);
334
335
		$this->publishEvent(
336
			$event, array_merge(
337
					  [$member],
338
					  $this->membersRequest->forceGetMembers(
339
						  $circle->getUniqueId(), Member::LEVEL_MODERATOR, 0, true
340
					  )
341
				  )
342
		);
343
344
		$this->dispatch('\OCA\Circles::onMemberLeaving', ['circle' => $circle, 'member' => $member]);
345
346
		$this->deleteNotification('membership', $member->getMemberId());
347
		$this->deleteNotification('membership_request', $member->getMemberId());
348
	}
349
350
351
	/**
352
	 * onMemberLevel()
353
	 *
354
	 * Called when a member have his level changed.
355
	 * Broadcast an activity to all moderator of the circle, and the member if he is demoted.
356
	 * If the level is Owner, we identify the event as a Coup d'Etat and we broadcast all members.
357
	 *
358
	 * @param Circle $circle
359
	 * @param Member $member
360
	 */
361 View Code Duplication
	public function onMemberLevel(Circle $circle, 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...
362
		if ($member->getLevel() === Member::LEVEL_OWNER) {
363
			$this->onMemberOwner($circle, $member);
364
365
			return;
366
		}
367
368
		$event = $this->generateEvent('circles_as_moderator');
369
		$event->setSubject(
370
			'member_level',
371
			['circle' => json_encode($circle), 'member' => json_encode($member)]
372
		);
373
374
		$mods =
375
			$this->membersRequest->forceGetMembers($circle->getUniqueId(), Member::LEVEL_MODERATOR, 0, true);
376
		$this->membersRequest->avoidDuplicateMembers($mods, [$member]);
377
378
		$this->publishEvent($event, $mods);
379
		$this->dispatch('\OCA\Circles::onMemberLevel', ['circle' => $circle, 'member' => $member]);
380
	}
381
382
383
	/**
384
	 * onMemberOwner()
385
	 *
386
	 * Called when the owner rights of a circle have be given to another member.
387
	 *
388
	 * @param Circle $circle
389
	 * @param Member $member
390
	 */
391
	public function onMemberOwner(Circle $circle, Member $member) {
392
		$event = $this->generateEvent('circles_as_moderator');
393
		$event->setSubject(
394
			'member_owner',
395
			['circle' => json_encode($circle), 'member' => json_encode($member)]
396
		);
397
398
		$this->publishEvent(
399
			$event,
400
			$this->membersRequest->forceGetMembers($circle->getUniqueId(), Member::LEVEL_MEMBER, 0, true)
401
		);
402
403
		$this->dispatch('\OCA\Circles::onMemberOwner', ['circle' => $circle, 'member' => $member]);
404
	}
405
406
407
	/**
408
	 * onGroupLink()
409
	 *
410
	 * Called when a group is linked to a circle.
411
	 * Broadcast an activity to the member of the linked group and to the moderators of the circle.
412
	 * We won't do anything if the circle is PERSONAL
413
	 *
414
	 * @param Circle $circle
415
	 * @param Member $group
416
	 */
417 View Code Duplication
	public function onGroupLink(Circle $circle, Member $group) {
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...
418
		if ($circle->getType() === Circle::CIRCLES_PERSONAL) {
419
			return;
420
		}
421
422
		$event = $this->generateEvent('circles_as_moderator');
423
		$event->setSubject(
424
			'group_link',
425
			['circle' => json_encode($circle), 'group' => json_encode($group)]
426
		);
427
428
		$mods =
429
			$this->membersRequest->forceGetMembers($circle->getUniqueId(), Member::LEVEL_MODERATOR, 0, true);
430
		$this->membersRequest->avoidDuplicateMembers(
431
			$mods, $this->membersRequest->getGroupMemberMembers($group)
432
		);
433
434
		$this->publishEvent($event, $mods);
435
		$this->dispatch('\OCA\Circles::onGroupLink', ['circle' => $circle, 'group' => $group]);
436
	}
437
438
439
	/**
440
	 * onGroupUnlink()
441
	 *
442
	 * Called when a group is unlinked from a circle.
443
	 * Broadcast an activity to the member of the unlinked group and to the moderators of the
444
	 * circle. We won't do anything if the circle is PERSONAL
445
	 *
446
	 * @param Circle $circle
447
	 * @param Member $group
448
	 */
449 View Code Duplication
	public function onGroupUnlink(Circle $circle, Member $group) {
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...
450
		if ($circle->getType() === Circle::CIRCLES_PERSONAL) {
451
			return;
452
		}
453
454
		$event = $this->generateEvent('circles_as_moderator');
455
		$event->setSubject(
456
			'group_unlink',
457
			['circle' => json_encode($circle), 'group' => json_encode($group)]
458
		);
459
460
		$mods =
461
			$this->membersRequest->forceGetMembers($circle->getUniqueId(), Member::LEVEL_MODERATOR, 0, true);
462
		$this->membersRequest->avoidDuplicateMembers(
463
			$mods, $this->membersRequest->getGroupMemberMembers($group)
464
		);
465
466
		$this->publishEvent($event, $mods);
467
		$this->dispatch('\OCA\Circles::onGroupUnlink', ['circle' => $circle, 'group' => $group]);
468
	}
469
470
471
	/**
472
	 * onGroupLevel()
473
	 *
474
	 * Called when a linked group have his level changed.
475
	 * Broadcast an activity to all moderator of the circle, and the group members in case of
476
	 * demotion.
477
	 *
478
	 * @param Circle $circle
479
	 * @param Member $group
480
	 */
481 View Code Duplication
	public function onGroupLevel(Circle $circle, Member $group) {
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...
482
		if ($circle->getType() === Circle::CIRCLES_PERSONAL) {
483
			return;
484
		}
485
486
		$event = $this->generateEvent('circles_as_moderator');
487
		$event->setSubject(
488
			'group_level',
489
			['circle' => json_encode($circle), 'group' => json_encode($group)]
490
		);
491
492
		$mods =
493
			$this->membersRequest->forceGetMembers($circle->getUniqueId(), Member::LEVEL_MODERATOR, 0, true);
494
		$this->membersRequest->avoidDuplicateMembers(
495
			$mods, $this->membersRequest->getGroupMemberMembers($group)
496
		);
497
498
		$this->publishEvent($event, $mods);
499
		$this->dispatch('\OCA\Circles::onGroupLevel', ['circle' => $circle, 'group' => $group]);
500
	}
501
502
503
	/**
504
	 * onLinkRequestSent()
505
	 *
506
	 * Called when a request to generate a link with a remote circle is sent.
507
	 * Broadcast an activity to the moderators of the circle.
508
	 *
509
	 * @param Circle $circle
510
	 * @param FederatedLink $link
511
	 */
512 View Code Duplication
	public function onLinkRequestSent(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...
513
		$event = $this->generateEvent('circles_as_moderator');
514
		$event->setSubject(
515
			'link_request_sent',
516
			['circle' => $circle->getJson(false, true), 'link' => $link->getJson()]
517
		);
518
519
		$this->publishEvent(
520
			$event,
521
			$this->membersRequest->forceGetMembers($link->getCircleId(), Member::LEVEL_MODERATOR, 0, true)
522
		);
523
		$this->dispatch('\OCA\Circles::onLinkRequestSent', ['circle' => $circle, 'link' => $link]);
524
	}
525
526
527
	/**
528
	 * onLinkRequestReceived()
529
	 *
530
	 * Called when a request to generate a link from a remote host is received.
531
	 * Broadcast an activity to the moderators of the circle.
532
	 *
533
	 * @param Circle $circle
534
	 * @param FederatedLink $link
535
	 */
536 View Code Duplication
	public function onLinkRequestReceived(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...
537
		$event = $this->generateEvent('circles_as_moderator');
538
		$event->setSubject(
539
			'link_request_received',
540
			['circle' => $circle->getJson(false, true), 'link' => $link->getJson()]
541
		);
542
543
		$this->publishEvent(
544
			$event,
545
			$this->membersRequest->forceGetMembers($link->getCircleId(), Member::LEVEL_MODERATOR, 0, true)
546
		);
547
		$this->dispatch('\OCA\Circles::onLinkRequestReceived', ['circle' => $circle, 'link' => $link]);
548
	}
549
550
551
	/**
552
	 * onLinkRequestRejected()
553
	 *
554
	 * Called when a request to generate a link from a remote host is dismissed.
555
	 * Broadcast an activity to the moderators of the circle.
556
	 *
557
	 * @param Circle $circle
558
	 * @param FederatedLink $link
559
	 */
560 View Code Duplication
	public function onLinkRequestRejected(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...
561
		$event = $this->generateEvent('circles_as_moderator');
562
		$event->setSubject(
563
			'link_request_rejected',
564
			['circle' => $circle->getJson(false, true), 'link' => $link->getJson()]
565
		);
566
567
		$this->publishEvent(
568
			$event,
569
			$this->membersRequest->forceGetMembers($link->getCircleId(), Member::LEVEL_MODERATOR, 0, true)
570
		);
571
		$this->dispatch('\OCA\Circles::onLinkRequestRejected', ['circle' => $circle, 'link' => $link]);
572
	}
573
574
575
	/**
576
	 * onLinkRequestCanceled()
577
	 *
578
	 * Called when a request to generate a link from a remote host is dismissed.
579
	 * Broadcast an activity to the moderators of the circle.
580
	 *
581
	 * @param Circle $circle
582
	 * @param FederatedLink $link
583
	 */
584 View Code Duplication
	public function onLinkRequestCanceled(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...
585
		$event = $this->generateEvent('circles_as_moderator');
586
		$event->setSubject(
587
			'link_request_canceled',
588
			['circle' => $circle->getJson(false, true), 'link' => $link->getJson()]
589
		);
590
591
		$this->publishEvent(
592
			$event,
593
			$this->membersRequest->forceGetMembers($link->getCircleId(), Member::LEVEL_MODERATOR, 0, true)
594
		);
595
		$this->dispatch('\OCA\Circles::onLinkRequestCanceled', ['circle' => $circle, 'link' => $link]);
596
	}
597
598
599
	/**
600
	 * onLinkRequestAccepted()
601
	 *
602
	 * Called when a request to generate a link from a remote host is accepted.
603
	 * Broadcast an activity to the moderators of the circle.
604
	 *
605
	 * @param Circle $circle
606
	 * @param FederatedLink $link
607
	 */
608 View Code Duplication
	public function onLinkRequestAccepted(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...
609
		$event = $this->generateEvent('circles_as_moderator');
610
		$event->setSubject(
611
			'link_request_accepted',
612
			['circle' => $circle->getJson(false, true), 'link' => $link->getJson()]
613
		);
614
615
		$this->publishEvent(
616
			$event,
617
			$this->membersRequest->forceGetMembers($link->getCircleId(), Member::LEVEL_MODERATOR, 0, true)
618
		);
619
		$this->dispatch('\OCA\Circles::onLinkRequestAccepted', ['circle' => $circle, 'link' => $link]);
620
	}
621
622
623
	/**
624
	 * onLinkRequestAccepting()
625
	 *
626
	 * Called when a link is Up and Running.
627
	 * Broadcast an activity to the moderators of the circle.
628
	 *
629
	 * @param Circle $circle
630
	 * @param FederatedLink $link
631
	 */
632 View Code Duplication
	public function onLinkRequestAccepting(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...
633
		$event = $this->generateEvent('circles_as_moderator');
634
		$event->setSubject(
635
			'link_request_accepting',
636
			['circle' => $circle->getJson(false, true), 'link' => $link->getJson()]
637
		);
638
639
		$this->publishEvent(
640
			$event,
641
			$this->membersRequest->forceGetMembers($link->getCircleId(), Member::LEVEL_MODERATOR, 0, true)
642
		);
643
		$this->dispatch('\OCA\Circles::onLinkRequestAccepting', ['circle' => $circle, 'link' => $link]);
644
	}
645
646
647
	/**
648
	 * onLinkUp()
649
	 *
650
	 * Called when a link is Up and Running.
651
	 * Broadcast an activity to the moderators of the circle.
652
	 *
653
	 * @param Circle $circle
654
	 * @param FederatedLink $link
655
	 */
656 View Code Duplication
	public function onLinkUp(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...
657
		$event = $this->generateEvent('circles_as_moderator');
658
		$event->setSubject(
659
			'link_up',
660
			['circle' => $circle->getJson(false, true), 'link' => $link->getJson()]
661
		);
662
663
		$this->publishEvent(
664
			$event,
665
			$this->membersRequest->forceGetMembers($link->getCircleId(), Member::LEVEL_MODERATOR, 0, true)
666
		);
667
		$this->dispatch('\OCA\Circles::onLinkUp', ['circle' => $circle, 'link' => $link]);
668
	}
669
670
671
	/**
672
	 * onLinkDown()
673
	 *
674
	 * Called when a link is closed (usually by remote).
675
	 * Broadcast an activity to the moderators of the circle.
676
	 *
677
	 * @param Circle $circle
678
	 * @param FederatedLink $link
679
	 */
680 View Code Duplication
	public function onLinkDown(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...
681
		$event = $this->generateEvent('circles_as_moderator');
682
		$event->setSubject(
683
			'link_down',
684
			['circle' => $circle->getJson(false, true), 'link' => $link->getJson()]
685
		);
686
687
		$this->publishEvent(
688
			$event,
689
			$this->membersRequest->forceGetMembers($link->getCircleId(), Member::LEVEL_MODERATOR, 0, true)
690
		);
691
		$this->dispatch('\OCA\Circles::onLinkDown', ['circle' => $circle, 'link' => $link]);
692
	}
693
694
695
	/**
696
	 * onLinkRemove()
697
	 *
698
	 * Called when a link is removed.
699
	 * Subject is based on the current status of the Link.
700
	 * Broadcast an activity to the moderators of the circle.
701
	 *
702
	 * @param Circle $circle
703
	 * @param FederatedLink $link
704
	 */
705
	public function onLinkRemove(Circle $circle, FederatedLink $link) {
706
		$event = $this->generateEvent('circles_as_moderator');
707
708
		if ($link->getStatus() === FederatedLink::STATUS_LINK_DOWN) {
709
			return;
710
		}
711
712
		$subject = 'link_remove';
713
		if ($link->getStatus() === FederatedLink::STATUS_LINK_REQUESTED) {
714
			$subject = 'link_request_removed';
715
		} elseif ($link->getStatus() === FederatedLink::STATUS_REQUEST_SENT) {
716
			$subject = 'link_request_canceling';
717
		}
718
719
		$event->setSubject(
720
			$subject, ['circle' => $circle->getJson(false, true), 'link' => $link->getJson()]
721
		);
722
723
		$this->publishEvent(
724
			$event,
725
			$this->membersRequest->forceGetMembers($link->getCircleId(), Member::LEVEL_MODERATOR, 0, true)
726
		);
727
		$this->dispatch('\OCA\Circles::onLinkRemove', ['circle' => $circle, 'link' => $link]);
728
	}
729
730
	/**
731
	 * onSettingsChange()
732
	 *
733
	 * Called when the circle's settings are changed
734
	 *
735
	 * @param Circle $circle
736
	 * @param array $oldSettings
737
	 */
738
	public function onSettingsChange(Circle $circle, array $oldSettings = []) {
739
		$this->dispatch(
740
			'\OCA\Circles::onSettingsChange', ['circle' => $circle, 'oldSettings' => $oldSettings]
741
		);
742
	}
743
744
745
	/**
746
	 * generateEvent()
747
	 * Create an Activity Event with the basic settings for the app.
748
	 *
749
	 * @param $type
750
	 *
751
	 * @return \OCP\Activity\IEvent
752
	 */
753
	private function generateEvent($type) {
754
		$event = $this->activityManager->generateEvent();
755
		$event->setApp(Application::APP_NAME)
756
			  ->setType($type);
757
758
		//	if ($this->userId === null) {
759
		//	$event->setAuthor($this->userId);
760
		//	}
761
762
		return $event;
763
	}
764
765
766
	/**
767
	 * Publish the event to the users.
768
	 *
769
	 * @param IEvent $event
770
	 * @param array $users
771
	 */
772
	private function publishEvent(IEvent $event, array $users) {
773
		foreach ($users as $user) {
774
			if ($user instanceof IUser) {
775
				$userId = $user->getUID();
776
			} else if ($user instanceof Member) {
777
				$userId = $user->getUserId();
778
			} else {
779
				continue;
780
			}
781
782
			$event->setAffectedUser($userId);
783
			$this->activityManager->publish($event);
784
		}
785
	}
786
787
788
	/**
789
	 * @param Circle $circle
790
	 * @param Member $member
791
	 */
792
	private function notificationOnInvitation(Circle $circle, Member $member) {
793
		$this->deleteNotification('membership_request', $member->getMemberId());
794
		if ($member->getType() !== Member::TYPE_USER) {
795
			return;
796
		}
797
798
		$notification =
799
			$this->createNotification(
800
				$circle, $circle->getViewer(), $member->getUserId(), 'invitation', 'membership',
801
				$member->getMemberId()
802
			);
803
804
		$declineAction = $notification->createAction();
805
		$declineUrl =
806
			$this->urlGenerator->linkToRoute('circles.Circles.leave', ['uniqueId' => $circle->getUniqueId()]);
807
808
		$declineAction->setLabel('refuse')
809
					  ->setLink($this->urlGenerator->getAbsoluteURL($declineUrl), 'GET');
810
		$notification->addAction($declineAction);
811
812
		$acceptAction = $notification->createAction();
813
		$acceptUrl =
814
			$this->urlGenerator->linkToRoute('circles.Circles.join', ['uniqueId' => $circle->getUniqueId()]);
815
816
		$acceptAction->setLabel('accept')
817
					 ->setLink($this->urlGenerator->getAbsoluteURL($acceptUrl), 'GET');
818
		$notification->addAction($acceptAction);
819
820
		$this->notificationManager->notify($notification);
821
	}
822
823
	/**
824
	 * @param Circle $circle
825
	 * @param Member $author
826
	 */
827
	private function notificationOnRequest(Circle $circle, Member $author) {
828
		$members = $this->membersRequest->forceGetMembers($circle->getUniqueId(), Member::LEVEL_MODERATOR);
829
		foreach ($members as $member) {
830
			$notification = $this->createNotification(
831
				$circle, $author, $member->getUserId(), 'request_new', 'membership_request',
832
				$author->getMemberId()
833
			);
834
835
			$declineAction = $notification->createAction();
836
			$declineUrl = $this->urlGenerator->linkToRoute(
837
				'circles.Members.removeMemberById', ['memberId' => $author->getMemberId()]
838
			);
839
840
			$declineAction->setLabel('refuse')
841
						  ->setLink($this->urlGenerator->getAbsoluteURL($declineUrl), 'DELETE');
842
			$notification->addAction($declineAction);
843
844
			$acceptAction = $notification->createAction();
845
			$acceptUrl = $this->urlGenerator->linkToRoute(
846
				'circles.Members.addMemberById', ['memberId' => $author->getMemberId()]
847
			);
848
			$acceptAction->setLabel('accept')
849
						 ->setLink($this->urlGenerator->getAbsoluteURL($acceptUrl), 'PUT');
850
			$notification->addAction($acceptAction);
851
852
			$this->notificationManager->notify($notification);
853
		}
854
	}
855
856
857
	/**
858
	 * @param Circle $circle
859
	 * @param Member $member
860
	 */
861
	private function notificationOnMemberNew(Circle $circle, Member $member) {
862
		$this->deleteNotification('membership_request', $member->getMemberId());
863
		$this->deleteNotification('membership', $member->getMemberId());
864
		if ($this->userId === $member->getUserId()) {
865
			return;
866
		}
867
868
		$notification =
869
			$this->createNotification(
870
				$circle, $circle->getViewer(), $member->getUserId(), 'member_new', 'membership',
871
				$member->getMemberId()
872
			);
873
874
875
		$leave = $notification->createAction();
876
		$leaveUrl =
877
			$this->urlGenerator->linkToRoute('circles.Circles.leave', ['uniqueId' => $circle->getUniqueId()]);
878
		$leave->setLabel('leave')
879
			  ->setLink($this->urlGenerator->getAbsoluteURL($leaveUrl), 'GET');
880
881
		$notification->addAction($leave);
882
883
		$this->notificationManager->notify($notification);
884
	}
885
886
887
	/**
888
	 * @param string $object
889
	 * @param string $objectId
890
	 */
891
	public function deleteNotification(string $object, string $objectId) {
892
		if ($objectId === '') {
893
			return;
894
		}
895
896
		$notification = $this->notificationManager->createNotification();
897
		$notification->setApp('circles')
898
					 ->setObject($object, $objectId);
899
900
		$this->notificationManager->markProcessed($notification);
901
	}
902
903
904
	/**
905
	 * @param Circle $circle
906
	 * @param Member $author
907
	 * @param string $userId
908
	 * @param string $subject
909
	 * @param string $object
910
	 * @param string $objectId
911
	 *
912
	 * @return INotification
913
	 */
914
	private function createNotification(
915
		Circle $circle, Member $author, string $userId, string $subject, string $object, string $objectId
916
	) {
917
		$now = $this->time->getDateTime();
918
		$notification = $this->notificationManager->createNotification();
919
		$notification->setApp('circles')
920
					 ->setDateTime($now)
921
					 ->setUser($userId)
922
					 ->setObject($object, $objectId)
923
					 ->setSubject(
924
						 $subject, [$author->getUserId(), $circle->getName(), json_encode($circle)]
925
					 );
926
927
		return $notification;
928
	}
929
930
931
	/**
932
	 * @param string $context
933
	 * @param array $arguments
934
	 */
935
	private function dispatch($context, $arguments) {
936
		$this->eventDispatcher->dispatch($context, new GenericEvent(null, $arguments));
937
	}
938
939
}
940