Passed
Push — master ( db5915...22087f )
by Julius
02:53
created

CardService::update()   D

Complexity

Conditions 18
Paths 23

Size

Total Lines 79

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 79
rs 4.8666
c 0
b 0
f 0
cc 18
nc 23
nop 10

How to fix   Long Method    Complexity    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * @copyright Copyright (c) 2016 Julius Härtl <[email protected]>
4
 *
5
 * @author Julius Härtl <[email protected]>
6
 * @author Maxence Lange <[email protected]>
7
 *
8
 * @license GNU AGPL version 3 or any later version
9
 *
10
 *  This program is free software: you can redistribute it and/or modify
11
 *  it under the terms of the GNU Affero General Public License as
12
 *  published by the Free Software Foundation, either version 3 of the
13
 *  License, or (at your option) any later version.
14
 *
15
 *  This program is distributed in the hope that it will be useful,
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *  GNU Affero General Public License for more details.
19
 *
20
 *  You should have received a copy of the GNU Affero General Public License
21
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
 *
23
 */
24
25
namespace OCA\Deck\Service;
26
27
use OCA\Deck\Activity\ActivityManager;
28
use OCA\Deck\Activity\ChangeSet;
29
use OCA\Deck\Db\AssignedUsers;
30
use OCA\Deck\Db\AssignedUsersMapper;
31
use OCA\Deck\Db\Card;
32
use OCA\Deck\Db\CardMapper;
33
use OCA\Deck\Db\Acl;
34
use OCA\Deck\Db\ChangeHelper;
35
use OCA\Deck\Db\StackMapper;
36
use OCA\Deck\Notification\NotificationHelper;
37
use OCA\Deck\Db\BoardMapper;
38
use OCA\Deck\Db\LabelMapper;
39
use OCA\Deck\NotFoundException;
40
use OCA\Deck\StatusException;
41
use OCA\Deck\BadRequestException;
42
use OCP\Comments\ICommentsManager;
43
use OCP\IUserManager;
44
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
45
use Symfony\Component\EventDispatcher\GenericEvent;
46
47
class CardService {
48
49
	private $cardMapper;
50
	private $stackMapper;
51
	private $boardMapper;
52
	private $labelMapper;
53
	private $permissionService;
54
	private $boardService;
55
	private $notificationHelper;
56
	private $assignedUsersMapper;
57
	private $attachmentService;
58
	private $currentUser;
59
	private $activityManager;
60
	private $commentsManager;
61
	private $changeHelper;
62
	/** @var EventDispatcherInterface */
63
	private $eventDispatcher;
64
	private $userManager;
65
66 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...
67
		CardMapper $cardMapper,
68
		StackMapper $stackMapper,
69
		BoardMapper $boardMapper,
70
		LabelMapper $labelMapper,
71
		PermissionService $permissionService,
72
		BoardService $boardService,
73
		NotificationHelper $notificationHelper,
74
		AssignedUsersMapper $assignedUsersMapper,
75
		AttachmentService $attachmentService,
76
		ActivityManager $activityManager,
77
		ICommentsManager $commentsManager,
78
		IUserManager $userManager,
79
		ChangeHelper $changeHelper,
80
		EventDispatcherInterface $eventDispatcher,
81
		$userId
82
	) {
83
		$this->cardMapper = $cardMapper;
84
		$this->stackMapper = $stackMapper;
85
		$this->boardMapper = $boardMapper;
86
		$this->labelMapper = $labelMapper;
87
		$this->permissionService = $permissionService;
88
		$this->boardService = $boardService;
89
		$this->notificationHelper = $notificationHelper;
90
		$this->assignedUsersMapper = $assignedUsersMapper;
91
		$this->attachmentService = $attachmentService;
92
		$this->activityManager = $activityManager;
93
		$this->commentsManager = $commentsManager;
94
		$this->userManager = $userManager;
95
		$this->changeHelper = $changeHelper;
96
		$this->eventDispatcher = $eventDispatcher;
97
		$this->currentUser = $userId;
98
	}
99
100
	public function enrich($card) {
101
		$cardId = $card->getId();
102
		$this->cardMapper->mapOwner($card);
103
		$card->setAssignedUsers($this->assignedUsersMapper->find($cardId));
104
		$card->setLabels($this->labelMapper->findAssignedLabelsForCard($cardId));
105
		$card->setAttachmentCount($this->attachmentService->count($cardId));
106
		$user = $this->userManager->get($this->currentUser);
107
		$lastRead = $this->commentsManager->getReadMark('deckCard', (string)$card->getId(), $user);
0 ignored issues
show
Bug introduced by
It seems like $user defined by $this->userManager->get($this->currentUser) on line 106 can be null; however, OCP\Comments\ICommentsManager::getReadMark() 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...
108
		$count = $this->commentsManager->getNumberOfCommentsForObject('deckCard', (string)$card->getId(), $lastRead);
109
		$card->setCommentsUnread($count);
110
	}
111
112
	public function fetchDeleted($boardId) {
113
		$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_READ);
114
		$cards = $this->cardMapper->findDeleted($boardId);
115
		foreach ($cards as $card) {
116
			$this->enrich($card);
117
		}
118
		return $cards;
119
	}
120
121
	/**
122
	 * @param $cardId
123
	 * @return \OCA\Deck\Db\RelationalEntity
124
	 * @throws \OCA\Deck\NoPermissionException
125
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
126
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
127
	 * @throws BadRequestException
128
	 */
129
	public function find($cardId) {
130
131
		if (is_numeric($cardId) === false) {
132
			throw new BadRequestException('card id must be a number');
133
		}
134
135
		$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
136
		$card = $this->cardMapper->find($cardId);
137
		$assignedUsers = $this->assignedUsersMapper->find($card->getId());
138
		$attachments = $this->attachmentService->findAll($cardId, true);
139
		$card->setAssignedUsers($assignedUsers);
140
		$card->setAttachments($attachments);
141
		$this->enrich($card);
142
		return $card;
143
	}
144
145
	/**
146
	 * @param $title
147
	 * @param $stackId
148
	 * @param $type
149
	 * @param integer $order
150
	 * @param $owner
151
	 * @return \OCP\AppFramework\Db\Entity
152
	 * @throws StatusException
153
	 * @throws \OCA\Deck\NoPermissionException
154
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
155
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
156
	 * @throws BadrequestException
157
	 */
158
	public function create($title, $stackId, $type, $order, $owner) {
159
160
		if ($title === 'false' || $title === null) {
161
			throw new BadRequestException('title must be provided');
162
		}
163
164
		if (is_numeric($stackId) === false) {
165
			throw new BadRequestException('stack id must be a number');
166
		}
167
168
		if ($type === 'false' || $type === null) {
169
			throw new BadRequestException('type must be provided');
170
		}
171
172
		if (is_numeric($order) === false) {
173
			throw new BadRequestException('order must be a number');
174
		}
175
176
		if ($owner === false || $owner === null) {
177
			throw new BadRequestException('owner must be provided');
178
		}
179
180
		$this->permissionService->checkPermission($this->stackMapper, $stackId, Acl::PERMISSION_EDIT);
181
		if ($this->boardService->isArchived($this->stackMapper, $stackId)) {
182
			throw new StatusException('Operation not allowed. This board is archived.');
183
		}
184
		$card = new Card();
185
		$card->setTitle($title);
186
		$card->setStackId($stackId);
187
		$card->setType($type);
188
		$card->setOrder($order);
189
		$card->setOwner($owner);
190
		$card = $this->cardMapper->insert($card);
191
		$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $card, ActivityManager::SUBJECT_CARD_CREATE);
192
		$this->changeHelper->cardChanged($card->getId(), false);
193
194
		$this->eventDispatcher->dispatch(
195
			'\OCA\Deck\Card::onCreate',
196
			new GenericEvent(
197
				null, ['id' => $card->getId(), 'card' => $card, 'userId' => $owner, 'stackId' => $stackId]
198
			)
199
		);
200
201
		return $card;
202
	}
203
204
	/**
205
	 * @param $id
206
	 * @return \OCP\AppFramework\Db\Entity
207
	 * @throws StatusException
208
	 * @throws \OCA\Deck\NoPermissionException
209
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
210
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
211
	 * @throws BadRequestException
212
	 */
213 View Code Duplication
	public function delete($id) {
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...
214
215
		if (is_numeric($id) === false) {
216
			throw new BadRequestException('card id must be a number');
217
		}
218
219
		$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
220
		if ($this->boardService->isArchived($this->cardMapper, $id)) {
221
			throw new StatusException('Operation not allowed. This board is archived.');
222
		}
223
		$card = $this->cardMapper->find($id);
224
		$card->setDeletedAt(time());
225
		$this->cardMapper->update($card);
226
		$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $card, ActivityManager::SUBJECT_CARD_DELETE);
227
		$this->changeHelper->cardChanged($card->getId(), false);
228
229
		$this->eventDispatcher->dispatch(
230
			'\OCA\Deck\Card::onDelete', new GenericEvent(null, ['id' => $id, 'card' => $card])
231
		);
232
233
		return $card;
234
	}
235
236
	/**
237
	 * @param $id
238
	 * @param $title
239
	 * @param $stackId
240
	 * @param $type
241
	 * @param $order
242
	 * @param $description
243
	 * @param $owner
244
	 * @param $duedate
245
	 * @return \OCP\AppFramework\Db\Entity
246
	 * @throws StatusException
247
	 * @throws \OCA\Deck\NoPermissionException
248
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
249
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
250
	 * @throws BadRequestException
251
	 */
252
	public function update($id, $title, $stackId, $type, $order = 0, $description = '', $owner, $duedate = null, $deletedAt = null, $archived = null) {
253
254
		if (is_numeric($id) === false) {
255
			throw new BadRequestException('card id must be a number');
256
		}
257
258
		if ($title === false || $title === null) {
259
			throw new BadRequestException('title must be provided');
260
		}
261
262
		if (is_numeric($stackId) === false) {
263
			throw new BadRequestException('stack id must be a number $$$');
264
		}
265
266
		if ($type === false || $type === null) {
267
			throw new BadRequestException('type must be provided');
268
		}
269
270
		if ($owner === false || $owner === null) {
271
			throw new BadRequestException('owner must be provided');
272
		}
273
274
		$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
275
		if ($this->boardService->isArchived($this->cardMapper, $id)) {
276
			throw new StatusException('Operation not allowed. This board is archived.');
277
		}
278
		$card = $this->cardMapper->find($id);
279
		if ($archived !== null && $card->getArchived() && $archived === true) {
280
			throw new StatusException('Operation not allowed. This card is archived.');
281
		}
282
		$changes = new ChangeSet($card);
283
		if ($card->getLastEditor() !== $this->currentUser && $card->getLastEditor() !== null) {
284
			$this->activityManager->triggerEvent(
285
				ActivityManager::DECK_OBJECT_CARD,
286
				$card,
287
				ActivityManager::SUBJECT_CARD_UPDATE_DESCRIPTION,
288
				[
289
					'before' => $card->getDescriptionPrev(),
290
					'after' => $card->getDescription()
291
				],
292
				$card->getLastEditor()
293
			);
294
295
			$card->setDescriptionPrev($card->getDescription());
296
			$card->setLastEditor($this->currentUser);
297
		}
298
		$card->setTitle($title);
299
		$card->setStackId($stackId);
300
		$card->setType($type);
301
		$card->setOrder($order);
302
		$card->setOwner($owner);
303
		$card->setDuedate($duedate);
304
		if ($deletedAt) {
305
			$card->setDeletedAt($deletedAt);
306
		}
307
		if ($archived !== null) {
308
			$card->setArchived($archived);
309
		}
310
311
312
		// Trigger update events before setting description as it is handled separately
313
		$changes->setAfter($card);
314
		$this->activityManager->triggerUpdateEvents(ActivityManager::DECK_OBJECT_CARD, $changes, ActivityManager::SUBJECT_CARD_UPDATE);
315
316
		if ($card->getDescriptionPrev() === null) {
317
			$card->setDescriptionPrev($card->getDescription());
318
		}
319
		$card->setDescription($description);
320
321
322
		$card = $this->cardMapper->update($card);
323
		$this->changeHelper->cardChanged($card->getId(), true);
324
325
		$this->eventDispatcher->dispatch(
326
			'\OCA\Deck\Card::onUpdate', new GenericEvent(null, ['id' => $id, 'card' => $card])
327
		);
328
329
		return $card;
330
	}
331
332
	/**
333
	 * @param $id
334
	 * @param $title
335
	 * @return \OCP\AppFramework\Db\Entity
336
	 * @throws StatusException
337
	 * @throws \OCA\Deck\NoPermissionException
338
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
339
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
340
	 * @throws BadRequestException
341
	 */
342
	public function rename($id, $title) {
343
344
		if (is_numeric($id) === false) {
345
			throw new BadRequestException('id must be a number');
346
		}
347
348
		if ($title === false || $title === null) {
349
			throw new BadRequestException('title must be provided');
350
		}
351
352
		$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
353
		if ($this->boardService->isArchived($this->cardMapper, $id)) {
354
			throw new StatusException('Operation not allowed. This board is archived.');
355
		}
356
		$card = $this->cardMapper->find($id);
357
		if ($card->getArchived()) {
358
			throw new StatusException('Operation not allowed. This card is archived.');
359
		}
360
		$card->setTitle($title);
361
		$this->changeHelper->cardChanged($card->getId(), false);
362
		$update = $this->cardMapper->update($card);
363
364
		$this->eventDispatcher->dispatch(
365
			'\OCA\Deck\Card::onUpdate', new GenericEvent(null, ['id' => $id, 'card' => $card])
366
		);
367
368
		return $update;
369
	}
370
371
	/**
372
	 * @param $id
373
	 * @param $stackId
374
	 * @param $order
375
	 * @return array
376
	 * @throws StatusException
377
	 * @throws \OCA\Deck\NoPermissionException
378
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
379
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
380
	 * @throws BadRequestException
381
	 */
382
	public function reorder($id, $stackId, $order) {
383
384
		if (is_numeric($id) === false) {
385
			throw new BadRequestException('card id must be a number');
386
		}
387
388
		if (is_numeric($stackId) === false) {
389
			throw new BadRequestException('stack id must be a number');
390
		}
391
392
		if (is_numeric($order) === false) {
393
			throw new BadRequestException('order must be a number');
394
		}
395
396
		$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
397
		if ($this->boardService->isArchived($this->cardMapper, $id)) {
398
			throw new StatusException('Operation not allowed. This board is archived.');
399
		}
400
		$cards = $this->cardMapper->findAll($stackId);
401
		$result = [];
402
		$i = 0;
403
		foreach ($cards as $card) {
404
			if ($card->getArchived()) {
405
				throw new StatusException('Operation not allowed. This card is archived.');
406
			}
407
			if ($card->id === $id) {
408
				$card->setOrder($order);
409
				$card->setLastModified(time());
410
			}
411
412
			if ($i === $order) {
413
				$i++;
414
			}
415
416
			if ($card->id !== $id) {
417
				$card->setOrder($i++);
418
			}
419
			$this->cardMapper->update($card);
420
			$result[$card->getOrder()] = $card;
421
		}
422
		$this->changeHelper->cardChanged($id, false);
423
		return $result;
424
	}
425
426
	/**
427
	 * @param $id
428
	 * @return \OCP\AppFramework\Db\Entity
429
	 * @throws StatusException
430
	 * @throws \OCA\Deck\NoPermissionException
431
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
432
	 * @throws \OCP\AppFramework\Db\
433
	 * @throws BadRequestException
434
	 */
435 View Code Duplication
	public function archive($id) {
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...
436
437
		if (is_numeric($id) === false) {
438
			throw new BadRequestException('id must be a number');
439
		}
440
441
		$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
442
		if ($this->boardService->isArchived($this->cardMapper, $id)) {
443
			throw new StatusException('Operation not allowed. This board is archived.');
444
		}
445
		$card = $this->cardMapper->find($id);
446
		$card->setArchived(true);
447
		$newCard = $this->cardMapper->update($card);
448
		$this->notificationHelper->markDuedateAsRead($card);
449
		$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $newCard, ActivityManager::SUBJECT_CARD_UPDATE_ARCHIVE);
450
		$this->changeHelper->cardChanged($id, false);
451
452
		$this->eventDispatcher->dispatch(
453
			'\OCA\Deck\Card::onUpdate', new GenericEvent(null, ['id' => $id, 'card' => $card])
454
		);
455
456
		return $newCard;
457
	}
458
459
	/**
460
	 * @param $id
461
	 * @return \OCP\AppFramework\Db\Entity
462
	 * @throws StatusException
463
	 * @throws \OCA\Deck\NoPermissionException
464
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
465
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
466
	 * @throws BadRequestException
467
	 */
468 View Code Duplication
	public function unarchive($id) {
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...
469
470
		if (is_numeric($id) === false) {
471
			throw new BadRequestException('id must be a number');
472
		}
473
474
		$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
475
		if ($this->boardService->isArchived($this->cardMapper, $id)) {
476
			throw new StatusException('Operation not allowed. This board is archived.');
477
		}
478
		$card = $this->cardMapper->find($id);
479
		$card->setArchived(false);
480
		$newCard = $this->cardMapper->update($card);
481
		$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $newCard, ActivityManager::SUBJECT_CARD_UPDATE_UNARCHIVE);
482
		$this->changeHelper->cardChanged($id, false);
483
484
		$this->eventDispatcher->dispatch(
485
			'\OCA\Deck\Card::onUpdate', new GenericEvent(null, ['id' => $id, 'card' => $card])
486
		);
487
488
		return $newCard;
489
	}
490
491
	/**
492
	 * @param $cardId
493
	 * @param $labelId
494
	 * @throws StatusException
495
	 * @throws \OCA\Deck\NoPermissionException
496
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
497
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
498
	 * @throws BadRequestException
499
	 */
500 View Code Duplication
	public function assignLabel($cardId, $labelId) {
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...
501
502
		if (is_numeric($cardId) === false) {
503
			throw new BadRequestException('card id must be a number');
504
		}
505
506
		if (is_numeric($labelId) === false) {
507
			throw new BadRequestException('label id must be a number');
508
		}
509
510
		$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
511
		if ($this->boardService->isArchived($this->cardMapper, $cardId)) {
512
			throw new StatusException('Operation not allowed. This board is archived.');
513
		}
514
		$card = $this->cardMapper->find($cardId);
515
		if ($card->getArchived()) {
516
			throw new StatusException('Operation not allowed. This card is archived.');
517
		}
518
		$label = $this->labelMapper->find($labelId);
519
		$this->cardMapper->assignLabel($cardId, $labelId);
520
		$this->changeHelper->cardChanged($cardId, false);
521
		$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $card, ActivityManager::SUBJECT_LABEL_ASSIGN, ['label' => $label]);
522
523
		$this->eventDispatcher->dispatch(
524
			'\OCA\Deck\Card::onUpdate', new GenericEvent(null, ['id' => $cardId, 'card' => $card])
525
		);
526
	}
527
528
	/**
529
	 * @param $cardId
530
	 * @param $labelId
531
	 * @throws StatusException
532
	 * @throws \OCA\Deck\NoPermissionException
533
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
534
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
535
	 * @throws BadRequestException
536
	 */
537 View Code Duplication
	public function removeLabel($cardId, $labelId) {
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...
538
539
		if (is_numeric($cardId) === false) {
540
			throw new BadRequestException('card id must be a number');
541
		}
542
543
		if (is_numeric($labelId) === false) {
544
			throw new BadRequestException('label id must be a number');
545
		}
546
547
		$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
548
		if ($this->boardService->isArchived($this->cardMapper, $cardId)) {
549
			throw new StatusException('Operation not allowed. This board is archived.');
550
		}
551
		$card = $this->cardMapper->find($cardId);
552
		if ($card->getArchived()) {
553
			throw new StatusException('Operation not allowed. This card is archived.');
554
		}
555
		$label = $this->labelMapper->find($labelId);
556
		$this->cardMapper->removeLabel($cardId, $labelId);
557
		$this->changeHelper->cardChanged($cardId, false);
558
		$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $card, ActivityManager::SUBJECT_LABEL_UNASSING, ['label' => $label]);
559
560
		$this->eventDispatcher->dispatch(
561
			'\OCA\Deck\Card::onUpdate', new GenericEvent(null, ['id' => $cardId, 'card' => $card])
562
		);
563
	}
564
565
	/**
566
	 * @param $cardId
567
	 * @param $userId
568
	 * @return bool|null|\OCP\AppFramework\Db\Entity
569
	 * @throws BadRequestException
570
	 * @throws \OCA\Deck\NoPermissionException
571
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
572
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
573
	 */
574
	public function assignUser($cardId, $userId) {
575
576
		if (is_numeric($cardId) === false) {
577
			throw new BadRequestException('card id must be a number');
578
		}
579
580
		if ($userId === false || $userId === null) {
581
			throw new BadRequestException('user id must be provided');
582
		}
583
584
		$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
585
		$assignments = $this->assignedUsersMapper->find($cardId);
586
		foreach ($assignments as $assignment) {
0 ignored issues
show
Bug introduced by
The expression $assignments of type array|object<OCP\AppFramework\Db\Entity> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
587
			if ($assignment->getParticipant() === $userId) {
588
				return false;
589
			}
590
		}
591
		$card = $this->cardMapper->find($cardId);
592
593
		if ($userId !== $this->currentUser) {
594
			/* Notifyuser about the card assignment */
595
			$this->notificationHelper->sendCardAssigned($card, $userId);
596
		}
597
598
		$assignment = new AssignedUsers();
599
		$assignment->setCardId($cardId);
600
		$assignment->setParticipant($userId);
601
		$assignment = $this->assignedUsersMapper->insert($assignment);
602
		$this->changeHelper->cardChanged($cardId, false);
603
		$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $card, ActivityManager::SUBJECT_CARD_USER_ASSIGN, ['assigneduser' => $userId]);
604
605
		$this->eventDispatcher->dispatch(
606
			'\OCA\Deck\Card::onUpdate', new GenericEvent(null, ['id' => $cardId, 'card' => $card])
607
		);
608
609
		return $assignment;
610
	}
611
612
	/**
613
	 * @param $cardId
614
	 * @param $userId
615
	 * @return \OCP\AppFramework\Db\Entity
616
	 * @throws BadRequestException
617
	 * @throws NotFoundException
618
	 * @throws \OCA\Deck\NoPermissionException
619
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
620
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
621
	 */
622
	public function unassignUser($cardId, $userId) {
623
		$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
624
625
		if (is_numeric($cardId) === false) {
626
			throw new BadRequestException('card id must be a number');
627
		}
628
629
		if ($userId === false || $userId === null) {
630
			throw new BadRequestException('user must be provided');
631
		}
632
633
		$assignments = $this->assignedUsersMapper->find($cardId);
634
		foreach ($assignments as $assignment) {
0 ignored issues
show
Bug introduced by
The expression $assignments of type array|object<OCP\AppFramework\Db\Entity> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
635
			if ($assignment->getParticipant() === $userId) {
636
				$assignment = $this->assignedUsersMapper->delete($assignment);
0 ignored issues
show
Deprecated Code introduced by
The method OCP\AppFramework\Db\Mapper::delete() has been deprecated with message: 14.0.0 Move over to QBMapper

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
637
				$card = $this->cardMapper->find($cardId);
638
				$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $card, ActivityManager::SUBJECT_CARD_USER_UNASSIGN, ['assigneduser' => $userId]);
639
				$this->changeHelper->cardChanged($cardId, false);
640
641
				$this->eventDispatcher->dispatch(
642
					'\OCA\Deck\Card::onUpdate', new GenericEvent(null, ['id' => $cardId, 'card' => $card])
643
				);
644
645
				return $assignment;
646
			}
647
		}
648
		throw new NotFoundException('No assignment for ' . $userId . 'found.');
649
	}
650
}
651