ActivityManager::createEvent()   F
last analyzed

Complexity

Conditions 39
Paths 513

Size

Total Lines 111

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 111
rs 0.5411
c 0
b 0
f 0
cc 39
nc 513
nop 5

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @copyright Copyright (c) 2018 Julius Härtl <[email protected]>
4
 *
5
 * @copyright Copyright (c) 2019 Alexandru Puiu <[email protected]>
6
 *
7
 * @author Julius Härtl <[email protected]>
8
 *
9
 * @license GNU AGPL version 3 or any later version
10
 *
11
 * This program is free software: you can redistribute it and/or modify
12
 * it under the terms of the GNU Affero General Public License as
13
 * published by the Free Software Foundation, either version 3 of the
14
 * License, or (at your option) any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU Affero General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Affero General Public License
22
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23
 *
24
 */
25
26
namespace OCA\Deck\Activity;
27
28
use InvalidArgumentException;
29
use OCA\Deck\Db\Acl;
30
use OCA\Deck\Db\AclMapper;
31
use OCA\Deck\Db\AssignedUsers;
32
use OCA\Deck\Db\Attachment;
33
use OCA\Deck\Db\AttachmentMapper;
34
use OCA\Deck\Db\Board;
35
use OCA\Deck\Db\BoardMapper;
36
use OCA\Deck\Db\Card;
37
use OCA\Deck\Db\CardMapper;
38
use OCA\Deck\Db\Label;
39
use OCA\Deck\Db\Stack;
40
use OCA\Deck\Db\StackMapper;
41
use OCA\Deck\Service\PermissionService;
42
use OCP\Activity\IEvent;
43
use OCP\Activity\IManager;
44
use OCP\AppFramework\Db\DoesNotExistException;
45
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
46
use OCP\Comments\IComment;
47
use OCP\IL10N;
48
use OCP\IUser;
49
50
class ActivityManager {
51
52
	const DECK_NOAUTHOR_COMMENT_SYSTEM_ENFORCED = 'DECK_NOAUTHOR_COMMENT_SYSTEM_ENFORCED';
53
	private $manager;
54
	private $userId;
55
	private $permissionService;
56
	private $boardMapper;
57
	private $cardMapper;
58
	private $attachmentMapper;
59
	private $aclMapper;
60
	private $stackMapper;
61
	private $l10n;
62
63
	const DECK_OBJECT_BOARD = 'deck_board';
64
	const DECK_OBJECT_CARD = 'deck_card';
65
66
	const SUBJECT_BOARD_CREATE = 'board_create';
67
	const SUBJECT_BOARD_UPDATE = 'board_update';
68
	const SUBJECT_BOARD_UPDATE_TITLE = 'board_update_title';
69
	const SUBJECT_BOARD_UPDATE_ARCHIVED = 'board_update_archived';
70
	const SUBJECT_BOARD_DELETE = 'board_delete';
71
	const SUBJECT_BOARD_RESTORE = 'board_restore';
72
	const SUBJECT_BOARD_SHARE = 'board_share';
73
	const SUBJECT_BOARD_UNSHARE = 'board_unshare';
74
75
	const SUBJECT_STACK_CREATE = 'stack_create';
76
	const SUBJECT_STACK_UPDATE = 'stack_update';
77
	const SUBJECT_STACK_UPDATE_TITLE = 'stack_update_title';
78
	const SUBJECT_STACK_UPDATE_ORDER = 'stack_update_order';
79
	const SUBJECT_STACK_DELETE = 'stack_delete';
80
81
	const SUBJECT_CARD_CREATE = 'card_create';
82
	const SUBJECT_CARD_DELETE = 'card_delete';
83
	const SUBJECT_CARD_RESTORE = 'card_restore';
84
	const SUBJECT_CARD_UPDATE = 'card_update';
85
	const SUBJECT_CARD_UPDATE_TITLE = 'card_update_title';
86
	const SUBJECT_CARD_UPDATE_DESCRIPTION = 'card_update_description';
87
	const SUBJECT_CARD_UPDATE_DUEDATE = 'card_update_duedate';
88
	const SUBJECT_CARD_UPDATE_ARCHIVE = 'card_update_archive';
89
	const SUBJECT_CARD_UPDATE_UNARCHIVE = 'card_update_unarchive';
90
	const SUBJECT_CARD_UPDATE_STACKID = 'card_update_stackId';
91
	const SUBJECT_CARD_USER_ASSIGN = 'card_user_assign';
92
	const SUBJECT_CARD_USER_UNASSIGN = 'card_user_unassign';
93
94
	const SUBJECT_ATTACHMENT_CREATE = 'attachment_create';
95
	const SUBJECT_ATTACHMENT_UPDATE = 'attachment_update';
96
	const SUBJECT_ATTACHMENT_DELETE = 'attachment_delete';
97
	const SUBJECT_ATTACHMENT_RESTORE = 'attachment_restore';
98
99
	const SUBJECT_LABEL_CREATE = 'label_create';
100
	const SUBJECT_LABEL_UPDATE = 'label_update';
101
	const SUBJECT_LABEL_DELETE = 'label_delete';
102
	const SUBJECT_LABEL_ASSIGN = 'label_assign';
103
	const SUBJECT_LABEL_UNASSING = 'label_unassign';
104
105
	const SUBJECT_CARD_COMMENT_CREATE = 'card_comment_create';
106
107
	public function __construct(
108
		IManager $manager,
109
		PermissionService $permissionsService,
110
		BoardMapper $boardMapper,
111
		CardMapper $cardMapper,
112
		StackMapper $stackMapper,
113
		AttachmentMapper $attachmentMapper,
114
		AclMapper $aclMapper,
115
		IL10N $l10n,
116
		$userId
117
	) {
118
		$this->manager = $manager;
119
		$this->permissionService = $permissionsService;
120
		$this->boardMapper = $boardMapper;
121
		$this->cardMapper = $cardMapper;
122
		$this->stackMapper = $stackMapper;
123
		$this->attachmentMapper = $attachmentMapper;
124
		$this->aclMapper = $aclMapper;
125
		$this->l10n = $l10n;
126
		$this->userId = $userId;
127
	}
128
129
	/**
130
	 * @param $subjectIdentifier
131
	 * @param array $subjectParams
132
	 * @param bool $ownActivity
133
	 * @return string
134
	 */
135
	public function getActivityFormat($subjectIdentifier, $subjectParams = [], $ownActivity = false) {
136
		$subject = '';
137
		switch ($subjectIdentifier) {
138 View Code Duplication
			case self::SUBJECT_BOARD_CREATE:
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...
139
				$subject = $ownActivity ? $this->l10n->t('You have created a new board {board}'): $this->l10n->t('{user} has created a new board {board}');
140
				break;
141 View Code Duplication
			case self::SUBJECT_BOARD_DELETE:
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...
142
				$subject = $ownActivity ? $this->l10n->t('You have deleted the board {board}') : $this->l10n->t('{user} has deleted the board {board}');
143
				break;
144 View Code Duplication
			case self::SUBJECT_BOARD_RESTORE:
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...
145
				$subject = $ownActivity ? $this->l10n->t('You have restored the board {board}') : $this->l10n->t('{user} has restored the board {board}');
146
				break;
147 View Code Duplication
			case self::SUBJECT_BOARD_SHARE:
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...
148
				$subject = $ownActivity ? $this->l10n->t('You have shared the board {board} with {acl}') : $this->l10n->t('{user} has shared the board {board} with {acl}');
149
				break;
150 View Code Duplication
			case self::SUBJECT_BOARD_UNSHARE:
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...
151
				$subject = $ownActivity ? $this->l10n->t('You have removed {acl} from the board {board}') : $this->l10n->t('{user} has removed {acl} from the board {board}');
152
				break;
153 View Code Duplication
			case self::SUBJECT_BOARD_UPDATE_TITLE:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
154
				$subject = $ownActivity ? $this->l10n->t('You have renamed the board {before} to {board}') : $this->l10n->t('{user} has renamed the board {before} to {board}');
155
				break;
156 View Code Duplication
			case self::SUBJECT_BOARD_UPDATE_ARCHIVED:
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...
157
				if (isset($subjectParams['after']) && $subjectParams['after']) {
158
					$subject = $ownActivity ? $this->l10n->t('You have archived the board {board}') : $this->l10n->t('{user} has archived the board {before}');
159
				} else {
160
					$subject = $ownActivity ? $this->l10n->t('You have unarchived the board {board}') : $this->l10n->t('{user} has unarchived the board {before}');
161
				}
162
				break;
163 View Code Duplication
			case self::SUBJECT_STACK_CREATE:
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...
164
				$subject = $ownActivity ? $this->l10n->t('You have created a new stack {stack} on board {board}') : $this->l10n->t('{user} has created a new stack {stack} on board {board}');
165
				break;
166 View Code Duplication
			case self::SUBJECT_STACK_UPDATE:
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...
167
				$subject = $ownActivity ? $this->l10n->t('You have created a new stack {stack} on board {board}') : $this->l10n->t('{user} has created a new stack {stack} on board {board}');
168
				break;
169 View Code Duplication
			case self::SUBJECT_STACK_UPDATE_TITLE:
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...
170
				$subject = $ownActivity ? $this->l10n->t('You have renamed stack {before} to {stack} on board {board}') : $this->l10n->t('{user} has renamed stack {before} to {stack} on board {board}');
171
				break;
172 View Code Duplication
			case self::SUBJECT_STACK_DELETE:
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...
173
				$subject = $ownActivity ? $this->l10n->t('You have deleted stack {stack} on board {board}') : $this->l10n->t('{user} has deleted stack {stack} on board {board}');
174
				break;
175 View Code Duplication
			case self::SUBJECT_CARD_CREATE:
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...
176
				$subject = $ownActivity ? $this->l10n->t('You have created card {card} in stack {stack} on board {board}') : $this->l10n->t('{user} has created card {card} in stack {stack} on board {board}');
177
				break;
178 View Code Duplication
			case self::SUBJECT_CARD_DELETE:
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...
179
				$subject = $ownActivity ? $this->l10n->t('You have deleted card {card} in stack {stack} on board {board}') : $this->l10n->t('{user} has deleted card {card} in stack {stack} on board {board}');
180
				break;
181 View Code Duplication
			case self::SUBJECT_CARD_UPDATE_TITLE:
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...
182
				$subject = $ownActivity ? $this->l10n->t('You have renamed the card {before} to {card}') : $this->l10n->t('{user} has renamed the card {before} to {card}');
183
				break;
184 View Code Duplication
			case self::SUBJECT_CARD_UPDATE_DESCRIPTION:
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...
185
				if (!isset($subjectParams['before'])) {
186
					$subject = $ownActivity ? $this->l10n->t('You have added a description to card {card} in stack {stack} on board {board}') : $this->l10n->t('{user} has added a description to card {card} in stack {stack} on board {board}');
187
				} else {
188
					$subject = $ownActivity ? $this->l10n->t('You have updated the description of card {card} in stack {stack} on board {board}') : $this->l10n->t('{user} has updated the description of the card {card} in stack {stack} on board {board}');
189
				}
190
				break;
191 View Code Duplication
			case self::SUBJECT_CARD_UPDATE_ARCHIVE:
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...
192
				$subject = $ownActivity ? $this->l10n->t('You have archived card {card} in stack {stack} on board {board}') : $this->l10n->t('{user} has archived card {card} in stack {stack} on board {board}');
193
				break;
194 View Code Duplication
			case self::SUBJECT_CARD_UPDATE_UNARCHIVE:
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...
195
				$subject = $ownActivity ? $this->l10n->t('You have unarchived card {card} in stack {stack} on board {board}') : $this->l10n->t('{user} has unarchived card {card} in stack {stack} on board {board}');
196
				break;
197
			case self::SUBJECT_CARD_UPDATE_DUEDATE:
198
				if (!isset($subjectParams['after'])) {
199
					$subject = $ownActivity ? $this->l10n->t('You have removed the due date of card {card}') : $this->l10n->t('{user} has removed the due date of card {card}');
200
				} else if (!isset($subjectParams['before']) && isset($subjectParams['after'])) {
201
					$subject = $ownActivity ? $this->l10n->t('You have set the due date of card {card} to {after}') : $this->l10n->t('{user} has set the due date of card {card} to {after}');
202
				} else {
203
					$subject = $ownActivity ? $this->l10n->t('You have updated the due date of card {card} to {after}') : $this->l10n->t('{user} has updated the due date of card {card} to {after}');
204
				}
205
206
				break;
207 View Code Duplication
			case self::SUBJECT_LABEL_ASSIGN:
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...
208
				$subject = $ownActivity ? $this->l10n->t('You have added the tag {label} to card {card} in stack {stack} on board {board}') : $this->l10n->t('{user} has added the tag {label} to card {card} in stack {stack} on board {board}');
209
				break;
210 View Code Duplication
			case self::SUBJECT_LABEL_UNASSING:
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...
211
				$subject = $ownActivity ? $this->l10n->t('You have removed the tag {label} from card {card} in stack {stack} on board {board}') : $this->l10n->t('{user} has removed the tag {label} from card {card} in stack {stack} on board {board}');
212
				break;
213 View Code Duplication
			case self::SUBJECT_CARD_USER_ASSIGN:
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...
214
				$subject = $ownActivity ? $this->l10n->t('You have assigned {assigneduser} to card {card} on board {board}') : $this->l10n->t('{user} has assigned {assigneduser} to card {card} on board {board}');
215
				break;
216 View Code Duplication
			case self::SUBJECT_CARD_USER_UNASSIGN:
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...
217
				$subject = $ownActivity ? $this->l10n->t('You have unassigned {assigneduser} from card {card} on board {board}') : $this->l10n->t('{user} has unassigned {assigneduser} from card {card} on board {board}');
218
				break;
219 View Code Duplication
			case self::SUBJECT_CARD_UPDATE_STACKID:
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...
220
				$subject = $ownActivity ? $this->l10n->t('You have moved the card {card} from stack {stackBefore} to {stack}') : $this->l10n->t('{user} has moved the card {card} from stack {stackBefore} to {stack}');
221
				break;
222 View Code Duplication
			case self::SUBJECT_ATTACHMENT_CREATE:
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...
223
				$subject = $ownActivity ? $this->l10n->t('You have added the attachment {attachment} to card {card}') : $this->l10n->t('{user} has added the attachment {attachment} to card {card}');
224
				break;
225 View Code Duplication
			case self::SUBJECT_ATTACHMENT_UPDATE:
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...
226
				$subject = $ownActivity ? $this->l10n->t('You have updated the attachment {attachment} on card {card}') : $this->l10n->t('{user} has updated the attachment {attachment} on card {card}');
227
				break;
228 View Code Duplication
			case self::SUBJECT_ATTACHMENT_DELETE:
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...
229
				$subject = $ownActivity ? $this->l10n->t('You have deleted the attachment {attachment} from card {card}') : $this->l10n->t('{user} has deleted the attachment {attachment} from card {card}');
230
				break;
231 View Code Duplication
			case self::SUBJECT_ATTACHMENT_RESTORE:
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...
232
				$subject = $ownActivity ? $this->l10n->t('You have restored the attachment {attachment} to card {card}') : $this->l10n->t('{user} has restored the attachment {attachment} to card {card}');
233
				break;
234 View Code Duplication
			case self::SUBJECT_CARD_COMMENT_CREATE:
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...
235
				$subject = $ownActivity ? $this->l10n->t('You have commented on card {card}') : $this->l10n->t('{user} has commented on card {card}');
236
				break;
237
			default:
238
				break;
239
		}
240
		return $subject;
241
	}
242
243
	public function triggerEvent($objectType, $entity, $subject, $additionalParams = [], $author = null) {
244
		try {
245
			$event = $this->createEvent($objectType, $entity, $subject, $additionalParams, $author);
246
			if ($event !== null) {
247
				$this->sendToUsers($event);
248
			}
249
		} catch (\Exception $e) {
250
			// Ignore exception for undefined activities on update events
251
		}
252
	}
253
254
	/**
255
	 *
256
	 * @param $objectType
257
	 * @param ChangeSet $changeSet
258
	 * @param $subject
259
	 * @throws \Exception
260
	 */
261
	public function triggerUpdateEvents($objectType, ChangeSet $changeSet, $subject) {
262
		$previousEntity = $changeSet->getBefore();
263
		$entity = $changeSet->getAfter();
264
		$events = [];
265
		if ($previousEntity !== null) {
266
			foreach ($entity->getUpdatedFields() as $field => $value) {
267
				$getter = 'get' . ucfirst($field);
268
				$subjectComplete = $subject . '_' . $field;
269
				$changes = [
270
					'before' => $previousEntity->$getter(),
271
					'after' => $entity->$getter()
272
				];
273
				if ($changes['before'] !== $changes['after']) {
274
					try {
275
						$event = $this->createEvent($objectType, $entity, $subjectComplete, $changes);
276
						if ($event !== null) {
277
							$events[] = $event;
278
						}
279
					} catch (\Exception $e) {
280
						// Ignore exception for undefined activities on update events
281
					}
282
				}
283
			}
284
		} else {
285
			try {
286
				$events = [$this->createEvent($objectType, $entity, $subject)];
287
			} catch (\Exception $e) {
288
				// Ignore exception for undefined activities on update events
289
			}
290
		}
291
		foreach ($events as $event) {
292
			$this->sendToUsers($event);
293
		}
294
	}
295
296
	/**
297
	 * @param $objectType
298
	 * @param $entity
299
	 * @param $subject
300
	 * @param array $additionalParams
301
	 * @return IEvent|null
302
	 * @throws \Exception
303
	 */
304
	private function createEvent($objectType, $entity, $subject, $additionalParams = [], $author = null) {
305
		try {
306
			$object = $this->findObjectForEntity($objectType, $entity);
307
		} catch (DoesNotExistException $e) {
308
			\OC::$server->getLogger()->error('Could not create activity entry for ' . $subject . '. Entity not found.', (array)$entity);
309
			return null;
310
		} catch (MultipleObjectsReturnedException $e) {
311
			\OC::$server->getLogger()->error('Could not create activity entry for ' . $subject . '. Entity not found.', (array)$entity);
312
			return null;
313
		}
314
315
		/**
316
		 * Automatically fetch related details for subject parameters
317
		 * depending on the subject
318
		 */
319
		$eventType = 'deck';
320
		$subjectParams = [];
321
		$message = null;
322
		switch ($subject) {
323
			// No need to enhance parameters since entity already contains the required data
324
			case self::SUBJECT_BOARD_CREATE:
325
			case self::SUBJECT_BOARD_UPDATE_TITLE:
326
			case self::SUBJECT_BOARD_UPDATE_ARCHIVED:
327
			case self::SUBJECT_BOARD_DELETE:
328
			case self::SUBJECT_BOARD_RESTORE:
329
			// Not defined as there is no activity for
330
			// case self::SUBJECT_BOARD_UPDATE_COLOR
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% 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...
331
				break;
332
			case self::SUBJECT_CARD_COMMENT_CREATE:
333
				$eventType = 'deck_comment';
334
				$subjectParams = $this->findDetailsForCard($entity->getId());
335
				if (array_key_exists('comment', $additionalParams)) {
336
					/** @var IComment $entity */
337
					$comment = $additionalParams['comment'];
338
					$subjectParams['comment'] = $comment->getId();
339
					unset($additionalParams['comment']);
340
				}
341
				break;
342
			case self::SUBJECT_STACK_CREATE:
343
			case self::SUBJECT_STACK_UPDATE:
344
			case self::SUBJECT_STACK_UPDATE_TITLE:
345
			case self::SUBJECT_STACK_UPDATE_ORDER:
346
			case self::SUBJECT_STACK_DELETE:
347
				$subjectParams = $this->findDetailsForStack($entity->getId());
348
				break;
349
350
			case self::SUBJECT_CARD_CREATE:
351
			case self::SUBJECT_CARD_DELETE:
352
			case self::SUBJECT_CARD_UPDATE_ARCHIVE:
353
			case self::SUBJECT_CARD_UPDATE_UNARCHIVE:
354
			case self::SUBJECT_CARD_UPDATE_TITLE:
355
			case self::SUBJECT_CARD_UPDATE_DESCRIPTION:
356
			case self::SUBJECT_CARD_UPDATE_DUEDATE:
357
			case self::SUBJECT_CARD_UPDATE_STACKID:
358
			case self::SUBJECT_LABEL_ASSIGN:
359
			case self::SUBJECT_LABEL_UNASSING:
360
			case self::SUBJECT_CARD_USER_ASSIGN:
361
			case self::SUBJECT_CARD_USER_UNASSIGN:
362
				$subjectParams = $this->findDetailsForCard($entity->getId(), $subject);
363
				break;
364
			case self::SUBJECT_ATTACHMENT_CREATE:
365
			case self::SUBJECT_ATTACHMENT_UPDATE:
366
			case self::SUBJECT_ATTACHMENT_DELETE:
367
			case self::SUBJECT_ATTACHMENT_RESTORE:
368
				$subjectParams = $this->findDetailsForAttachment($entity->getId());
369
				break;
370
			case self::SUBJECT_BOARD_SHARE:
371
			case self::SUBJECT_BOARD_UNSHARE:
372
				$subjectParams = $this->findDetailsForAcl($entity->getId());
373
				break;
374
			default:
375
				throw new \Exception('Unknown subject for activity.');
376
				break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
377
		}
378
379
		if ($subject === self::SUBJECT_CARD_UPDATE_DESCRIPTION){
380
			$card = $subjectParams['card'];
381
			if ($card->getLastEditor() === $this->userId) {
382
				return null;
383
			}
384
			$subjectParams['diff'] = true;
385
			$eventType = 'deck_card_description';
386
		}
387
		if ($subject === self::SUBJECT_CARD_UPDATE_STACKID) {
388
			$subjectParams['stackBefore'] = $this->stackMapper->find($additionalParams['before']);
389
			$subjectParams['stack'] = $this->stackMapper->find($additionalParams['after']);
390
		}
391
392
		$subjectParams['author'] = $this->userId;
393
394
395
		$event = $this->manager->generateEvent();
396
		$event->setApp('deck')
397
			->setType($eventType)
398
			->setAuthor($author === null ? $this->userId : $author)
399
			->setObject($objectType, (int)$object->getId(), $object->getTitle())
400
			->setSubject($subject, array_merge($subjectParams, $additionalParams))
401
			->setTimestamp(time());
402
403
		if ($message !== null) {
404
			$event->setMessage($message);
405
		}
406
407
		// FIXME: We currently require activities for comments even if they are disabled though settings
408
		// Get rid of this once the frontend fetches comments/activity individually
409
		if ($eventType === 'deck_comment') {
410
			$event->setAuthor(self::DECK_NOAUTHOR_COMMENT_SYSTEM_ENFORCED);
411
		}
412
413
		return $event;
414
	}
415
416
	/**
417
	 * Publish activity to all users that are part of the board of a given object
418
	 *
419
	 * @param IEvent $event
420
	 */
421
	private function sendToUsers(IEvent $event) {
422
		switch ($event->getObjectType()) {
423
			case self::DECK_OBJECT_BOARD:
424
				$mapper = $this->boardMapper;
425
				break;
426
			case self::DECK_OBJECT_CARD:
427
				$mapper = $this->cardMapper;
428
				break;
429
		}
430
		$boardId = $mapper->findBoardId($event->getObjectId());
0 ignored issues
show
Bug introduced by
The variable $mapper does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
431
		/** @var IUser $user */
432
		foreach ($this->permissionService->findUsers($boardId) as $user) {
433
			$event->setAffectedUser($user->getUID());
434
			/** @noinspection DisconnectedForeachInstructionInspection */
435
			$this->manager->publish($event);
436
		}
437
	}
438
439
	/**
440
	 * @param $objectType
441
	 * @param $entity
442
	 * @return null|\OCA\Deck\Db\RelationalEntity|\OCP\AppFramework\Db\Entity
443
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
444
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
445
	 */
446
	private function findObjectForEntity($objectType, $entity) {
447
		$className = \get_class($entity);
448
		if ($entity instanceof IComment) {
449
			$className = IComment::class;
450
		}
451
		$objectId = null;
0 ignored issues
show
Unused Code introduced by
$objectId is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
452
		if ($objectType === self::DECK_OBJECT_CARD) {
453
			switch ($className) {
454
				case Card::class:
455
					$objectId = $entity->getId();
456
					break;
457
				case Attachment::class:
458
				case Label::class:
459
				case AssignedUsers::class:
460
					$objectId = $entity->getCardId();
461
					break;
462
				case IComment::class:
463
					$objectId = $entity->getObjectId();
464
					break;
465
				default:
466
					throw new InvalidArgumentException('No entity relation present for '. $className . ' to ' . $objectType);
467
			}
468
			return $this->cardMapper->find($objectId);
469
		}
470
		if ($objectType === self::DECK_OBJECT_BOARD) {
471
			switch ($className) {
472
				case Board::class:
473
					$objectId = $entity->getId();
474
					break;
475
				case Label::class:
476
				case Stack::class:
477
				case Acl::class:
478
					$objectId = $entity->getBoardId();
479
					break;
480
				default:
481
					throw new InvalidArgumentException('No entity relation present for '. $className . ' to ' . $objectType);
482
			}
483
			return $this->boardMapper->find($objectId);
484
		}
485
		throw new InvalidArgumentException('No entity relation present for '. $className . ' to ' . $objectType);
486
	}
487
488 View Code Duplication
	private function findDetailsForStack($stackId) {
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...
489
		$stack = $this->stackMapper->find($stackId);
490
		$board = $this->boardMapper->find($stack->getBoardId());
491
		return [
492
			'stack' => $stack,
493
			'board' => $board
494
		];
495
	}
496
497
	private function findDetailsForCard($cardId, $subject = null) {
498
		$card = $this->cardMapper->find($cardId);
499
		$stack = $this->stackMapper->find($card->getStackId());
500
		$board = $this->boardMapper->find($stack->getBoardId());
501
		if ($subject !== self::SUBJECT_CARD_UPDATE_DESCRIPTION) {
502
			$card = [
503
				'id' => $card->getId(),
504
				'title' => $card->getTitle(),
505
				'archived' => $card->getArchived()
506
			];
507
		}
508
		return [
509
			'card' => $card,
510
			'stack' => $stack,
511
			'board' => $board
512
		];
513
	}
514
515
	private function findDetailsForAttachment($attachmentId) {
516
		$attachment = $this->attachmentMapper->find($attachmentId);
517
		$data = $this->findDetailsForCard($attachment->getCardId());
518
		return array_merge($data, ['attachment' => $attachment]);
519
	}
520
521 View Code Duplication
	private function findDetailsForAcl($aclId) {
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...
522
		$acl = $this->aclMapper->find($aclId);
523
		$board = $this->boardMapper->find($acl->getBoardId());
524
		return [
525
			'acl' => $acl,
526
			'board' => $board
527
		];
528
	}
529
530
}
531