Passed
Pull Request — master (#632)
by Julius
04:14
created

ActivityManager::createEvent()   F

Complexity

Conditions 35
Paths 467

Size

Total Lines 93

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 93
rs 0.7402
c 0
b 0
f 0
cc 35
nc 467
nop 4

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
 * @author Julius Härtl <[email protected]>
6
 *
7
 * @license GNU AGPL version 3 or any later version
8
 *
9
 * This program is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU Affero General Public License as
11
 * published by the Free Software Foundation, either version 3 of the
12
 * License, or (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU Affero General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Affero General Public License
20
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21
 *
22
 */
23
24
namespace OCA\Deck\Activity;
25
26
use InvalidArgumentException;
27
use OCA\Deck\Db\Acl;
28
use OCA\Deck\Db\AclMapper;
29
use OCA\Deck\Db\AssignedUsers;
30
use OCA\Deck\Db\Attachment;
31
use OCA\Deck\Db\AttachmentMapper;
32
use OCA\Deck\Db\Board;
33
use OCA\Deck\Db\BoardMapper;
34
use OCA\Deck\Db\Card;
35
use OCA\Deck\Db\CardMapper;
36
use OCA\Deck\Db\Label;
37
use OCA\Deck\Db\Stack;
38
use OCA\Deck\Db\StackMapper;
39
use OCA\Deck\Service\PermissionService;
40
use OCP\Activity\IEvent;
41
use OCP\Activity\IManager;
42
use OCP\AppFramework\Db\DoesNotExistException;
43
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
44
use OCP\Comments\IComment;
45
use OCP\IL10N;
46
use OCP\IUser;
47
48
class ActivityManager {
49
50
	private $manager;
51
	private $userId;
52
	private $permissionService;
53
	private $boardMapper;
54
	private $cardMapper;
55
	private $attachmentMapper;
56
	private $aclMapper;
57
	private $stackMapper;
58
	private $l10n;
59
60
	const DECK_OBJECT_BOARD = 'deck_board';
61
	const DECK_OBJECT_CARD = 'deck_card';
62
63
	const SUBJECT_BOARD_CREATE = 'board_create';
64
	const SUBJECT_BOARD_UPDATE = 'board_update';
65
	const SUBJECT_BOARD_UPDATE_TITLE = 'board_update_title';
66
	const SUBJECT_BOARD_UPDATE_ARCHIVED = 'board_update_archived';
67
	const SUBJECT_BOARD_DELETE = 'board_delete';
68
	const SUBJECT_BOARD_RESTORE = 'board_restore';
69
	const SUBJECT_BOARD_SHARE = 'board_share';
70
	const SUBJECT_BOARD_UNSHARE = 'board_unshare';
71
72
	const SUBJECT_STACK_CREATE = 'stack_create';
73
	const SUBJECT_STACK_UPDATE = 'stack_update';
74
	const SUBJECT_STACK_UPDATE_TITLE = 'stack_update_title';
75
	const SUBJECT_STACK_UPDATE_ORDER = 'stack_update_order';
76
	const SUBJECT_STACK_DELETE = 'stack_delete';
77
78
	const SUBJECT_CARD_CREATE = 'card_create';
79
	const SUBJECT_CARD_DELETE = 'card_delete';
80
	const SUBJECT_CARD_RESTORE = 'card_restore';
81
	const SUBJECT_CARD_UPDATE = 'card_update';
82
	const SUBJECT_CARD_UPDATE_TITLE = 'card_update_title';
83
	const SUBJECT_CARD_UPDATE_DESCRIPTION = 'card_update_description';
84
	const SUBJECT_CARD_UPDATE_DUEDATE = 'card_update_duedate';
85
	const SUBJECT_CARD_UPDATE_ARCHIVE = 'card_update_archive';
86
	const SUBJECT_CARD_UPDATE_UNARCHIVE = 'card_update_unarchive';
87
	const SUBJECT_CARD_UPDATE_STACKID = 'card_update_stackId';
88
	const SUBJECT_CARD_USER_ASSIGN = 'card_user_assign';
89
	const SUBJECT_CARD_USER_UNASSIGN = 'card_user_unassign';
90
91
	const SUBJECT_ATTACHMENT_CREATE = 'attachment_create';
92
	const SUBJECT_ATTACHMENT_UPDATE = 'attachment_update';
93
	const SUBJECT_ATTACHMENT_DELETE = 'attachment_delete';
94
	const SUBJECT_ATTACHMENT_RESTORE = 'attachment_restore';
95
96
	const SUBJECT_LABEL_CREATE = 'label_create';
97
	const SUBJECT_LABEL_UPDATE = 'label_update';
98
	const SUBJECT_LABEL_DELETE = 'label_delete';
99
	const SUBJECT_LABEL_ASSIGN = 'label_assign';
100
	const SUBJECT_LABEL_UNASSING = 'label_unassign';
101
102
	const SUBJECT_CARD_COMMENT_CREATE = 'card_comment_create';
103
104 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...
105
		IManager $manager,
106
		PermissionService $permissionsService,
107
		BoardMapper $boardMapper,
108
		CardMapper $cardMapper,
109
		StackMapper $stackMapper,
110
		AttachmentMapper $attachmentMapper,
111
		AclMapper $aclMapper,
112
		IL10N $l10n,
113
		$userId
114
	) {
115
		$this->manager = $manager;
116
		$this->permissionService = $permissionsService;
117
		$this->boardMapper = $boardMapper;
118
		$this->cardMapper = $cardMapper;
119
		$this->stackMapper = $stackMapper;
120
		$this->attachmentMapper = $attachmentMapper;
121
		$this->aclMapper = $aclMapper;
122
		$this->l10n = $l10n;
123
		$this->userId = $userId;
124
	}
125
126
	/**
127
	 * @param $subjectIdentifier
128
	 * @param array $subjectParams
129
	 * @param bool $ownActivity
130
	 * @return string
131
	 */
132
	public function getActivityFormat($subjectIdentifier, $subjectParams = [], $ownActivity = false) {
133
		$subject = '';
134
		switch ($subjectIdentifier) {
135 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...
136
				$subject = $ownActivity ? $this->l10n->t('You have created a new board {board}'): $this->l10n->t('{user} has created a new board {board}');
137
				break;
138 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...
139
				$subject = $ownActivity ? $this->l10n->t('You have deleted the board {board}') : $this->l10n->t('{user} has deleted the board {board}');
140
				break;
141 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...
142
				$subject = $ownActivity ? $this->l10n->t('You have restored the board {board}') : $this->l10n->t('{user} has restored the board {board}');
143
				break;
144 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...
145
				$subject = $ownActivity ? $this->l10n->t('You have shared the board {board} with {acl}') : $this->l10n->t('{user} has shared the board {board} with {sharee}');
146
				break;
147 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...
148
				$subject = $ownActivity ? $this->l10n->t('You have removed {acl} from the board {board}') : $this->l10n->t('{user} has removed {acl} from the board {board}');
149
				break;
150
151 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...
152
				$subject = $ownActivity ? $this->l10n->t('You have renamed the board {before} to {board}') : $this->l10n->t('{user} has has renamed the board {before} to {board}');
153
				break;
154 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...
155
				if (isset($subjectParams['after']) && $subjectParams['after']) {
156
					$subject = $ownActivity ? $this->l10n->t('You have archived the board {board}') : $this->l10n->t('{user} has archived the board {before}');
157
				} else {
158
					$subject = $ownActivity ? $this->l10n->t('You have unarchived the board {board}') : $this->l10n->t('{user} has unarchived the board {before}');
159
				}
160
				break;
161
162 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...
163
				$subject = $ownActivity ? $this->l10n->t('You have created a new stack {stack} on {board}') : $this->l10n->t('{user} has created a new stack {stack} on {board}');
164
				break;
165 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...
166
				$subject = $ownActivity ? $this->l10n->t('You have created a new stack {stack} on {board}') : $this->l10n->t('{user} has created a new stack {stack} on {board}');
167
				break;
168 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...
169
				$subject = $ownActivity ? $this->l10n->t('You have renamed a new stack {before} to {stack} on {board}') : $this->l10n->t('{user} has renamed a new stack {before} to {stack} on {board}');
170
				break;
171 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...
172
				$subject = $ownActivity ? $this->l10n->t('You have deleted {stack} on {board}') : $this->l10n->t('{user} has deleted {stack} on {board}');
173
				break;
174 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...
175
				$subject = $ownActivity ? $this->l10n->t('You have created {card} in {stack} on {board}') : $this->l10n->t('{user} has created {card} in {stack} on {board}');
176
				break;
177 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...
178
				$subject = $ownActivity ? $this->l10n->t('You have deleted {card} in {stack} on {board}') : $this->l10n->t('{user} has deleted {card} in {stack} on {board}');
179
				break;
180 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...
181
				$subject = $ownActivity ? $this->l10n->t('You have renamed the card {before} to {card}') : $this->l10n->t('{user} has renamed the card {before} to {card}');
182
				break;
183 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...
184
				if (!isset($subjectParams['before'])) {
185
					$subject = $ownActivity ? $this->l10n->t('You have added a description to {card} in {stack} on {board}') : $this->l10n->t('{user} has added a description to {card} in {stack} on {board}');
186
				} else {
187
					$subject = $ownActivity ? $this->l10n->t('You have updated the description of {card} in {stack} on {board}') : $this->l10n->t('{user} has updated the description {card} in {stack} on {board}');
188
				}
189
				break;
190 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...
191
				$subject = $ownActivity ? $this->l10n->t('You have archived {card} in {stack} on {board}') : $this->l10n->t('{user} has archived {card} in {stack} on {board}');
192
				break;
193 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...
194
				$subject = $ownActivity ? $this->l10n->t('You have unarchived {card} in {stack} on {board}') : $this->l10n->t('{user} has unarchived {card} in {stack} on {board}');
195
				break;
196
			case self::SUBJECT_CARD_UPDATE_DUEDATE:
197
				if (!isset($subjectParams['after'])) {
198
					$subject = $ownActivity ? $this->l10n->t('You have removed the due date of {card}') : $this->l10n->t('{user} has removed the due date of {card}');
199
				} else if (isset($subjectParams['before']) && !isset($subjectParams['after'])) {
200
					$subject = $ownActivity ? $this->l10n->t('You have set the due date of {card} to {after}') : $this->l10n->t('{user} has set the due date of {card} to {after}');
201
				} else {
202
					$subject = $ownActivity ? $this->l10n->t('You have updated the due date of {card} to {after}') : $this->l10n->t('{user} has updated the due date of {card} to {after}');
203
				}
204
205
				break;
206 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...
207
				$subject = $ownActivity ? $this->l10n->t('You have added the label {label} to {card} in {stack} on {board}') : $this->l10n->t('{user} has added the label {label} to {card} in {stack} on {board}');
208
				break;
209 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...
210
				$subject = $ownActivity ? $this->l10n->t('You have removed the label {label} from {card} in {stack} on {board}') : $this->l10n->t('{user} has removed the label {label} from {card} in {stack} on {board}');
211
				break;
212 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...
213
				$subject = $ownActivity ? $this->l10n->t('You have assigned {assigneduser} to {card} on {board}') : $this->l10n->t('{user} has assigned {assigneduser} to {card} on {board}');
214
				break;
215 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...
216
				$subject = $ownActivity ? $this->l10n->t('You have unassigned {assigneduser} from {card} on {board}') : $this->l10n->t('{user} has unassigned {assigneduser} from {card} on {board}');
217
				break;
218 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...
219
				$subject = $ownActivity ? $this->l10n->t('You have moved the card {card} from {stackBefore} to {stack}') : $this->l10n->t('{user} has moved the card {card} from {stackBefore} to {stack}');
220
				break;
221 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...
222
				$subject = $ownActivity ? $this->l10n->t('You have added the attachment {attachment} to {card}') : $this->l10n->t('{user} has added the attachment {attachment} to {card}');
223
				break;
224 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...
225
				$subject = $ownActivity ? $this->l10n->t('You have updated the attachment {attachment} on {card}') : $this->l10n->t('{user} has updated the attachment {attachment} to {card}');
226
				break;
227 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...
228
				$subject = $ownActivity ? $this->l10n->t('You have deleted the attachment {attachment} from {card}') : $this->l10n->t('{user} has deleted the attachment {attachment} to {card}');
229
				break;
230 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...
231
				$subject = $ownActivity ? $this->l10n->t('You have restored the attachment {attachment} to {card}') : $this->l10n->t('{user} has restored the attachment {attachment} to {card}');
232
				break;
233
			case self::SUBJECT_CARD_COMMENT_CREATE:
234
				$subject = $ownActivity ? $this->l10n->t('You have commented on {card}') : $this->l10n->t('{user} has commented on {card}');
235
				break;
236
			default:
237
				break;
238
		}
239
		return $subject;
240
	}
241
242
	public function triggerEvent($objectType, $entity, $subject, $additionalParams = []) {
243
		try {
244
			$event = $this->createEvent($objectType, $entity, $subject, $additionalParams);
245
			$this->sendToUsers($event);
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->createEvent($obje...ect, $additionalParams) on line 244 can be null; however, OCA\Deck\Activity\ActivityManager::sendToUsers() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
246
		} catch (\Exception $e) {
247
			// Ignore exception for undefined activities on update events
248
		}
249
	}
250
251
	/**
252
	 *
253
	 * @param $objectType
254
	 * @param ChangeSet $changeSet
255
	 * @param $subject
256
	 * @throws \Exception
257
	 */
258
	public function triggerUpdateEvents($objectType, ChangeSet $changeSet, $subject) {
259
		$previousEntity = $changeSet->getBefore();
260
		$entity = $changeSet->getAfter();
261
		$events = [];
262
		if ($previousEntity !== null) {
263
			foreach ($entity->getUpdatedFields() as $field => $value) {
264
				$getter = 'get' . ucfirst($field);
265
				$subject = $subject . '_' . $field;
266
				$changes = [
267
					'before' => $previousEntity->$getter(),
268
					'after' => $entity->$getter()
269
				];
270
				if ($changes['before'] !== $changes['after']) {
271
					try {
272
						$event = $this->createEvent($objectType, $entity, $subject, $changes);
273
						$events[] = $event;
274
					} catch (\Exception $e) {
275
						// Ignore exception for undefined activities on update events
276
					}
277
				}
278
			}
279
		} else {
280
			try {
281
				$events = [$this->createEvent($objectType, $entity, $subject)];
282
			} catch (\Exception $e) {
283
				// Ignore exception for undefined activities on update events
284
			}
285
		}
286
		foreach ($events as $event) {
287
			$this->sendToUsers($event);
288
		}
289
	}
290
291
	/**
292
	 * @param $objectType
293
	 * @param $entity
294
	 * @param $subject
295
	 * @param array $additionalParams
296
	 * @return IEvent
297
	 * @throws \Exception
298
	 */
299
	private function createEvent($objectType, $entity, $subject, $additionalParams = []) {
300
		try {
301
			$object = $this->findObjectForEntity($objectType, $entity);
302
		} catch (DoesNotExistException $e) {
303
		} catch (MultipleObjectsReturnedException $e) {
304
			\OC::$server->getLogger()->error('Could not create activity entry for ' . $subject . '. Entity not found.', $entity);
305
			return null;
306
		}
307
308
		/**
309
		 * Automatically fetch related details for subject parameters
310
		 * depending on the subject
311
		 */
312
		$subjectParams = [];
313
		$message = null;
314
		switch ($subject) {
315
			// No need to enhance parameters since entity already contains the required data
316
			case self::SUBJECT_BOARD_CREATE:
317
			case self::SUBJECT_BOARD_UPDATE_TITLE:
318
			case self::SUBJECT_BOARD_UPDATE_ARCHIVED:
319
			case self::SUBJECT_BOARD_DELETE:
320
			case self::SUBJECT_BOARD_RESTORE:
321
			// Not defined as there is no activity for
322
			// case self::SUBJECT_BOARD_UPDATE_COLOR
323
				break;
324
			case self::SUBJECT_CARD_COMMENT_CREATE:
325
				/** @var IComment $entity */
326
				$subjectParams = [
327
					'comment' => $entity->getMessage()
328
				];
329
				$message = $entity->getMessage();
330
				break;
331
332
			case self::SUBJECT_STACK_CREATE:
333
			case self::SUBJECT_STACK_UPDATE:
334
			case self::SUBJECT_STACK_UPDATE_TITLE:
335
			case self::SUBJECT_STACK_UPDATE_ORDER:
336
			case self::SUBJECT_STACK_DELETE:
337
				$subjectParams = $this->findDetailsForStack($entity->getId());
338
				break;
339
340
			case self::SUBJECT_CARD_CREATE:
341
			case self::SUBJECT_CARD_DELETE:
342
			case self::SUBJECT_CARD_UPDATE_ARCHIVE:
343
			case self::SUBJECT_CARD_UPDATE_UNARCHIVE:
344
			case self::SUBJECT_CARD_UPDATE_TITLE:
345
			case self::SUBJECT_CARD_UPDATE_DESCRIPTION:
346
			case self::SUBJECT_CARD_UPDATE_DUEDATE:
347
			case self::SUBJECT_CARD_UPDATE_STACKID:
348
			case self::SUBJECT_LABEL_ASSIGN:
349
			case self::SUBJECT_LABEL_UNASSING:
350
			case self::SUBJECT_CARD_USER_ASSIGN:
351
			case self::SUBJECT_CARD_USER_UNASSIGN:
352
				$subjectParams = $this->findDetailsForCard($entity->getId());
353
				$object = $entity;
354
				break;
355
			case self::SUBJECT_ATTACHMENT_CREATE:
356
			case self::SUBJECT_ATTACHMENT_UPDATE:
357
			case self::SUBJECT_ATTACHMENT_DELETE:
358
			case self::SUBJECT_ATTACHMENT_RESTORE:
359
				$subjectParams = $this->findDetailsForAttachment($entity->getId());
360
				$object = $subjectParams['card'];
361
				break;
362
			case self::SUBJECT_BOARD_SHARE:
363
			case self::SUBJECT_BOARD_UNSHARE:
364
				$subjectParams = $this->findDetailsForAcl($entity->getId());
365
				break;
366
			default:
367
				throw new \Exception('Unknown subject for activity.');
368
				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...
369
		}
370
371
		if ($subject === self::SUBJECT_CARD_UPDATE_DESCRIPTION){
372
			$subjectParams['diff'] = true;
373
		}
374
		if ($subject === self::SUBJECT_CARD_UPDATE_STACKID) {
375
			$subjectParams['stackBefore'] = $this->stackMapper->find($additionalParams['before']);
376
		}
377
378
		$event = $this->manager->generateEvent();
379
		$event->setApp('deck')
380
			->setType('deck')
381
			->setAuthor($this->userId)
382
			->setObject($objectType, (int)$object->getId(), $object->getTitle())
383
			->setSubject($subject, array_merge($subjectParams, $additionalParams))
384
			->setTimestamp(time());
385
386
		if ($message !== null) {
387
			$event->setMessage($message);
388
		}
389
390
		return $event;
391
	}
392
393
	/**
394
	 * Publish activity to all users that are part of the board of a given object
395
	 *
396
	 * @param IEvent $event
397
	 */
398
	private function sendToUsers(IEvent $event) {
399
		switch ($event->getObjectType()) {
400
			case self::DECK_OBJECT_BOARD:
401
				$mapper = $this->boardMapper;
402
				break;
403
			case self::DECK_OBJECT_CARD:
404
				$mapper = $this->cardMapper;
405
				break;
406
		}
407
		$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...
408
		/** @var IUser $user */
409
		foreach ($this->permissionService->findUsers($boardId) as $user) {
410
			$event->setAffectedUser($user->getUID());
411
			/** @noinspection DisconnectedForeachInstructionInspection */
412
			$this->manager->publish($event);
413
		}
414
	}
415
416
	/**
417
	 * @param $objectType
418
	 * @param $entity
419
	 * @return null|\OCA\Deck\Db\RelationalEntity|\OCP\AppFramework\Db\Entity
420
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
421
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
422
	 */
423
	private function findObjectForEntity($objectType, $entity) {
424
		$className = \get_class($entity);
425
		if ($entity instanceof IComment) {
426
			$className = IComment::class;
427
		}
428
		$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...
429
		if ($objectType === self::DECK_OBJECT_CARD) {
430
			switch ($className) {
431
				case Card::class:
432
					$objectId = $entity->getId();
433
					break;
434
				case Attachment::class:
435
				case Label::class:
436
				case AssignedUsers::class:
437
					$objectId = $entity->getCardId();
438
					break;
439
				case IComment::class:
440
					$objectId = $entity->getObjectId();
441
					break;
442
				default:
443
					throw new InvalidArgumentException('No entity relation present for '. $className . ' to ' . $objectType);
444
			}
445
			return $this->cardMapper->find($objectId);
446
		}
447
		if ($objectType === self::DECK_OBJECT_BOARD) {
448
			switch ($className) {
449
				case Board::class:
450
					$objectId = $entity->getId();
451
					break;
452
				case Label::class:
453
				case Stack::class:
454
				case Acl::class:
455
					$objectId = $entity->getBoardId();
456
					break;
457
				default:
458
					throw new InvalidArgumentException('No entity relation present for '. $className . ' to ' . $objectType);
459
			}
460
			return $this->boardMapper->find($objectId);
461
		}
462
		throw new InvalidArgumentException('No entity relation present for '. $className . ' to ' . $objectType);
463
	}
464
465 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...
466
		$stack = $this->stackMapper->find($stackId);
467
		$board = $this->boardMapper->find($stack->getBoardId());
468
		return [
469
			'stack' => $stack,
470
			'board' => $board
471
		];
472
	}
473
474
	private function findDetailsForCard($cardId) {
475
		$card = $this->cardMapper->find($cardId);
476
		$stack = $this->stackMapper->find($card->getStackId());
477
		$board = $this->boardMapper->find($stack->getBoardId());
478
		return [
479
			'card' => $card,
480
			'stack' => $stack,
481
			'board' => $board
482
		];
483
	}
484
485
	private function findDetailsForAttachment($attachmentId) {
486
		$attachment = $this->attachmentMapper->find($attachmentId);
487
		$data = $this->findDetailsForCard($attachment->getCardId());
488
		return array_merge($data, ['attachment' => $attachment]);
489
	}
490
491 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...
492
		$acl = $this->aclMapper->find($aclId);
493
		$board = $this->boardMapper->find($acl->getBoardId());
494
		return [
495
			'acl' => $acl,
496
			'board' => $board
497
		];
498
	}
499
500
}
501