Completed
Push — master ( f9c6c1...643034 )
by Maxence
02:36
created

Provider::generateParsedSubject()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 10
rs 9.4285
cc 2
eloc 7
nc 2
nop 1
1
<?php
2
3
4
namespace OCA\Circles\Activity;
5
6
7
use Exception;
8
use InvalidArgumentException;
9
use OCA\Circles\Api\v1\Circles;
10
use OCA\Circles\Model\Circle;
11
use OCA\Circles\Model\FederatedLink;
12
use OCA\Circles\Model\Member;
13
use OCA\Circles\Service\CirclesService;
14
use OCA\Circles\Service\MiscService;
15
use OCP\Activity\IEvent;
16
use OCP\Activity\IManager;
17
use OCP\Activity\IProvider;
18
use OCP\IL10N;
19
use OCP\IURLGenerator;
20
use OpenCloud\Common\Exceptions\InvalidArgumentError;
21
22
23
class Provider implements IProvider {
24
25
	/** @var MiscService */
26
	protected $miscService;
27
28
	/** @var IL10N */
29
	protected $l10n;
30
31
	/** @var IURLGenerator */
32
	protected $url;
33
34
	/** @var IManager */
35
	protected $activityManager;
36
37
	public function __construct(
38
		IURLGenerator $url, IManager $activityManager, IL10N $l10n, MiscService $miscService
39
	) {
40
		$this->url = $url;
41
		$this->activityManager = $activityManager;
42
		$this->l10n = $l10n;
43
		$this->miscService = $miscService;
44
	}
45
46
47
	/**
48
	 * @param string $lang
49
	 * @param IEvent $event
50
	 * @param IEvent|null $previousEvent
51
	 *
52
	 * @return IEvent
53
	 */
54
	public function parse($lang, IEvent $event, IEvent $previousEvent = null) {
55
56
		if ($event->getApp() !== 'circles') {
57
			throw new \InvalidArgumentException();
58
		}
59
60
		$params = $event->getSubjectParameters();
61
		$circle = Circle::fromJSON($this->l10n, $params['circle']);
62
		$event->setIcon(CirclesService::getCircleIcon($circle->getType()));
63
64
		$event = $this->parseAsMember($circle, $event, $params);
65
		$event = $this->parseAsModerator($circle, $event, $params);
66
67
		$this->generateParsedSubject($event);
68
69
		return $event;
70
	}
71
72
73
	/**
74
	 * @param Circle $circle
75
	 * @param IEvent $event
76
	 * @param array $params
77
	 *
78
	 * @return IEvent
79
	 */
80
	private function parseAsMember(Circle $circle, IEvent $event, $params) {
81
		if ($event->getType() !== 'circles_as_member') {
82
			return $event;
83
		}
84
85
		switch ($event->getSubject()) {
86
			case 'circle_create':
87
				return $this->parseCircleEvent(
88
					$circle, null, $event,
89
					$this->l10n->t('You created the circle {circle}'),
90
					$this->l10n->t('{author} created the circle {circle}')
91
				);
92
93
			case 'circle_delete':
94
				return $this->parseCircleEvent(
95
					$circle, null, $event,
96
					$this->l10n->t('You deleted {circle}'),
97
					$this->l10n->t('{author} deleted {circle}')
98
				);
99
		}
100
101
		if (key_exists('member', $params)) {
102
			$event = $this->parseMemberAsMember($circle, $event);
103
		}
104
105
		return $event;
106
	}
107
108
109
	/**
110
	 * @param Circle $circle
111
	 * @param IEvent $event
112
	 *
113
	 * @return IEvent
114
	 */
115
	private function parseMemberAsMember(Circle $circle, IEvent $event) {
116
		$params = $event->getSubjectParameters();
117
		$member = Member::fromJSON($this->l10n, $params['member']);
118
119
		switch ($event->getSubject()) {
120 View Code Duplication
			case 'member_join':
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...
121
				return $this->parseCircleMemberEvent(
122
					$circle, $member, $event,
123
					$this->l10n->t('You joined {circle}'),
124
					$this->l10n->t('{member} joined {circle}')
125
				);
126
127 View Code Duplication
			case 'member_add':
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...
128
				return $this->parseCircleMemberAdvancedEvent(
129
					$circle, $member, $event,
130
					$this->l10n->t('You added {member} as member to {circle}'),
131
					$this->l10n->t('You were added as member to {circle} by {author}'),
132
					$this->l10n->t('{member} was added as member to {circle} by {author}')
133
				);
134
135 View Code Duplication
			case 'member_left':
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...
136
				return $this->parseCircleMemberEvent(
137
					$circle, $member, $event,
138
					$this->l10n->t('You left {circle}'),
139
					$this->l10n->t('{member} left {circle}')
140
				);
141
142 View Code Duplication
			case 'member_remove':
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...
143
				return $this->parseCircleMemberAdvancedEvent(
144
					$circle, $member, $event,
145
					$this->l10n->t('You removed {member} from {circle}'),
146
					$this->l10n->t('You were removed from {circle} by {author}'),
147
					$this->l10n->t('{member} was removed from {circle} by {author}')
148
				);
149
		}
150
151
		return $event;
152
	}
153
154
155
	/**
156
	 * @param Circle $circle
157
	 * @param IEvent $event
158
	 * @param array $params
159
	 *
160
	 * @return IEvent
161
	 * @throws Exception
162
	 */
163
	private function parseAsModerator(Circle $circle, IEvent $event, $params) {
164
		if ($event->getType() !== 'circles_as_moderator') {
165
			return $event;
166
		}
167
168
		try {
169
			if (key_exists('member', $params)) {
170
				return $this->parseMemberAsModerator($circle, $event);
171
			}
172
173
			if (key_exists('link', $params)) {
174
				return $this->parseLinkAsModerator($circle, $event);
175
			}
176
177
			throw new InvalidArgumentError();
178
		} catch (Exception $e) {
179
			throw $e;
180
		}
181
182
	}
183
184
185
	/**
186
	 * @param Circle $circle
187
	 * @param IEvent $event
188
	 *
189
	 * @return IEvent
190
	 */
191
	private function parseMemberAsModerator(Circle $circle, IEvent $event) {
192
193
		$params = $event->getSubjectParameters();
194
		$member = Member::fromJSON($this->l10n, $params['member']);
195
196
		switch ($event->getSubject()) {
197 View Code Duplication
			case 'member_invited':
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...
198
				return $this->parseCircleMemberAdvancedEvent(
199
					$circle, $member, $event,
200
					$this->l10n->t('You invited {member} into {circle}'),
201
					$this->l10n->t('You have been invited into {circle} by {author}'),
202
					$this->l10n->t('{member} have been invited into {circle} by {author}')
203
				);
204
205
			case 'member_level':
206
				$level = [$this->l10n->t($member->getLevelString())];
207
208
				return $this->parseCircleMemberAdvancedEvent(
209
					$circle, $member, $event,
210
					$this->l10n->t('You changed {member}\'s level in {circle} to %1$s', $level),
211
					$this->l10n->t('{author} changed your level in {circle} to %1$s', $level),
212
					$this->l10n->t('{author} changed {member}\'s level in {circle} to %1$s', $level)
213
				);
214
215 View Code Duplication
			case 'member_request_invitation':
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...
216
				return $this->parseMemberEvent(
217
					$circle, $member, $event,
218
					$this->l10n->t('You requested an invitation to {circle}'),
219
					$this->l10n->t(
220
						'{member} has requested an invitation into {circle}'
221
					)
222
				);
223
224 View Code Duplication
			case 'member_owner':
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...
225
				return $this->parseMemberEvent(
226
					$circle, $member, $event,
227
					$this->l10n->t('You are the new owner of {circle}'),
228
					$this->l10n->t('{member} is the new owner of {circle}')
229
				);
230
		}
231
232
		throw new InvalidArgumentException();
233
	}
234
235
236
	/**
237
	 * @param Circle $circle
238
	 * @param IEvent $event
239
	 *
240
	 * @return IEvent
241
	 */
242
	private function parseLinkAsModerator(Circle $circle, IEvent $event) {
243
244
		$params = $event->getSubjectParameters();
245
		$link = FederatedLink::fromJSON($params['link']);
246
247
		switch ($event->getSubject()) {
248
			case 'link_request_sent':
249
				return $this->parseCircleEvent(
250
					$circle, $link, $event,
251
					$this->l10n->t('You sent a request to link {circle} with {link}'),
252
					$this->l10n->t('{author} sent a request to link {circle} with {link}')
253
				);
254
255
			case 'link_request_received';
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

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

Loading history...
256
				return $this->parseLinkEvent(
257
					$circle, $link, $event,
258
					$this->l10n->t('{link} requested a link with {circle}')
259
				);
260
261
			case 'link_request_rejected';
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

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

Loading history...
262
				return $this->parseLinkEvent(
263
					$circle, $link, $event, $this->l10n->t(
264
					'The request to link {circle} with {link} has been rejected'
265
				)
266
				);
267
268
			case 'link_request_canceled':
269
				return $this->parseLinkEvent(
270
					$circle, $link, $event,
271
					$this->l10n->t(
272
						'The request to link {link} with {circle} has been canceled remotely'
273
					)
274
				);
275
276
			case 'link_request_accepted':
277
				return $this->parseLinkEvent(
278
					$circle, $link, $event,
279
					$this->l10n->t('The request to link {circle} with {link} has been accepted')
280
				);
281
282
			case 'link_request_removed':
283
				return $this->parseCircleEvent(
284
					$circle, $link, $event,
285
					$this->l10n->t('You dismissed the request to link {link} with {circle}'),
286
					$this->l10n->t('{author} dismissed the request to link {link} with {circle}')
287
				);
288
289
			case 'link_request_canceling':
290
				return $this->parseCircleEvent(
291
					$circle, $link, $event,
292
					$this->l10n->t('You canceled the request to link {circle} with {link}'),
293
					$this->l10n->t('{author} canceled the request to link {circle} with {link}')
294
				);
295
296
			case 'link_request_accepting':
297
				return $this->parseCircleEvent(
298
					$circle, $link, $event,
299
					$this->l10n->t('You accepted the request to link {link} with {circle}'),
300
					$this->l10n->t('{author} accepted the request to link {link} with {circle}')
301
				);
302
303
			case 'link_up':
304
				return $this->parseLinkEvent(
305
					$circle, $link, $event,
306
					$this->l10n->t('A link between {circle} and {link} is now up and running')
307
				);
308
309
			case 'link_down':
310
				return $this->parseLinkEvent(
311
					$circle, $link, $event,
312
					$this->l10n->t(
313
						'The link between {circle} and {link} has been shutdown remotely'
314
					)
315
				);
316
317
			case 'link_remove':
318
				return $this->parseCircleEvent(
319
					$circle, $link, $event,
320
					$this->l10n->t('You closed the link between {circle} and {link}'),
321
					$this->l10n->t('{author} closed the link between {circle} and {link}')
322
				);
323
		}
324
325
		throw new InvalidArgumentException();
326
	}
327
328
329
	/**
330
	 * general function to generate Circle event.
331
	 *
332
	 * @param Circle $circle
333
	 * @param FederatedLink $link
334
	 * @param IEvent $event
335
	 * @param $ownEvent
336
	 * @param $othersEvent
337
	 *
338
	 * @return IEvent
339
	 */
340
	private function parseCircleEvent(Circle $circle, $link, IEvent $event, $ownEvent, $othersEvent
341
	) {
342
		$data = [
343
			'author' => $author = $this->generateUserParameter(
344
				$circle->getUser()
345
					   ->getUserId()
346
			),
347
			'circle' => $this->generateCircleParameter($circle),
348
			'link'   => ($link === null) ? '' : $this->generateLinkParameter($link)
349
		];
350
351
		if ($circle->getUser()
352
				   ->getUserId() === $this->activityManager->getCurrentUserId()
353
		) {
354
			return $event->setRichSubject($ownEvent, $data);
355
		}
356
357
		return $event->setRichSubject($othersEvent, $data);
358
	}
359
360
361
	/**
362
	 * general function to generate Member event.
363
	 *
364
	 * @param Circle $circle
365
	 * @param $member
366
	 * @param IEvent $event
367
	 * @param $ownEvent
368
	 * @param $othersEvent
369
	 *
370
	 * @return IEvent
371
	 */
372 View Code Duplication
	private function parseMemberEvent(
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...
373
		Circle $circle, Member $member, IEvent $event, $ownEvent, $othersEvent
374
	) {
375
		$data = [
376
			'circle' => $this->generateCircleParameter($circle),
377
			'member' => $this->generateMemberParameter($member)
378
		];
379
380
		if ($member->getUserId() === $this->activityManager->getCurrentUserId()
381
		) {
382
			return $event->setRichSubject($ownEvent, $data);
383
		}
384
385
		return $event->setRichSubject($othersEvent, $data);
386
	}
387
388
389
	/**
390
	 * general function to generate Link event.
391
	 *
392
	 * @param Circle $circle
393
	 * @param FederatedLink $link
394
	 * @param IEvent $event
395
	 * @param $line
396
	 *
397
	 * @return IEvent
398
	 */
399
	private function parseLinkEvent(Circle $circle, FederatedLink $link, IEvent $event, $line) {
400
		$data = [
401
			'circle' => $this->generateCircleParameter($circle),
402
			'link'   => $this->generateLinkParameter($link)
403
		];
404
405
		return $event->setRichSubject($line, $data);
406
	}
407
408
409
	/**
410
	 * general function to generate Circle+Member event.
411
	 *
412
	 * @param Circle $circle
413
	 * @param Member $member
414
	 * @param IEvent $event
415
	 * @param $ownEvent
416
	 * @param $othersEvent
417
	 *
418
	 * @return IEvent
419
	 */
420 View Code Duplication
	private function parseCircleMemberEvent(
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...
421
		Circle $circle, Member $member, IEvent $event, $ownEvent, $othersEvent
422
	) {
423
		$data = [
424
			'circle' => $this->generateCircleParameter($circle),
425
			'member' => $this->generateMemberParameter($member)
426
		];
427
428
		if ($circle->getUser()
429
				   ->getUserId() === $this->activityManager->getCurrentUserId()
430
		) {
431
			return $event->setRichSubject($ownEvent, $data);
432
		}
433
434
		return $event->setRichSubject($othersEvent, $data);
435
	}
436
437
438
	/**
439
	 * general function to generate Circle+Member advanced event.
440
	 *
441
	 * @param Circle $circle
442
	 * @param Member $member
443
	 * @param IEvent $event
444
	 *\
445
	 * @param $ownEvent
446
	 * @param $targetEvent
447
	 * @param $othersEvent
448
	 *
449
	 * @return IEvent
450
	 */
451
	private function parseCircleMemberAdvancedEvent(
452
		Circle $circle, Member $member, IEvent $event, $ownEvent, $targetEvent, $othersEvent
453
	) {
454
455
		$data = [
456
			'author' => $this->generateUserParameter(
457
				$circle->getUser()
458
					   ->getUserId()
459
			),
460
			'circle' => $this->generateCircleParameter($circle),
461
			'member' => $this->generateMemberParameter($member)
462
		];
463
464
		if ($circle->getUser()
465
				   ->getUserId() === $this->activityManager->getCurrentUserId()
466
		) {
467
			return $event->setRichSubject($ownEvent, $data);
468
		}
469
470
		if ($member->getUserId() === $this->activityManager->getCurrentUserId()) {
471
			return $event->setRichSubject($targetEvent, $data);
472
		}
473
474
		return $event->setRichSubject($othersEvent, $data);
475
	}
476
477
478
	/**
479
	 * @param IEvent $event
480
	 */
481
	private function generateParsedSubject(IEvent $event) {
482
		$subject = $event->getRichSubject();
483
		$params = $event->getRichSubjectParameters();
484
		$ak = array_keys($params);
485
		foreach ($ak as $k) {
486
			$subject = str_replace('{' . $k . '}', $params[$k]['parsed'], $subject);
487
		}
488
489
		$event->setParsedSubject($subject);
490
	}
491
492
	/**
493
	 * @param Member $member
494
	 *
495
	 * @return array
496
	 */
497
	private function generateMemberParameter(Member $member) {
498
		return $this->generateUserParameter($member->getUserId());
499
	}
500
501
502
	/**
503
	 * @param Circle $circle
504
	 *
505
	 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,string|integer>.

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

Loading history...
506
	 */
507
	private function generateCircleParameter(Circle $circle) {
508
		return [
509
			'type'   => 'circle',
510
			'id'     => $circle->getId(),
511
			'name'   => $circle->getName(),
512
			'parsed' => $circle->getName(),
513
			'link'   => Circles::generateLink($circle->getId())
514
		];
515
	}
516
517
518
	private function generateLinkParameter(FederatedLink $link) {
519
		return [
520
			'type'   => 'circle',
521
			'id'     => $link->getUniqueId(),
522
			'name'   => $link->getToken() . '@' . $link->getAddress(),
523
			'parsed' => $link->getToken() . '@' . $link->getAddress()
524
		];
525
//			'link' => Circles::generateRemoteLink($link)
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
526
	}
527
528
529
	/**
530
	 * @param $userId
531
	 *
532
	 * @return array
533
	 */
534
	private function generateUserParameter(
535
		$userId
536
	) {
537
		return [
538
			'type'   => 'user',
539
			'id'     => $userId,
540
			'name'   => \OC::$server->getUserManager()
541
									->get($userId)
542
									->getDisplayName(),
543
			'parsed' => \OC::$server->getUserManager()
544
									->get($userId)
545
									->getDisplayName()
546
		];
547
	}
548
}
549