Completed
Push — master ( a3a70f...f040df )
by Julius
11s
created

CardService::enrich()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016 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\Service;
25
26
use OCA\Deck\Db\AssignedUsers;
27
use OCA\Deck\Db\AssignedUsersMapper;
28
use OCA\Deck\Db\Card;
29
use OCA\Deck\Db\CardMapper;
30
use OCA\Deck\Db\Acl;
31
use OCA\Deck\Db\StackMapper;
32
use OCA\Deck\Notification\NotificationHelper;
33
use OCA\Deck\Db\BoardMapper;
34
use OCA\Deck\Db\LabelMapper;
35
use OCA\Deck\NotFoundException;
36
use OCA\Deck\StatusException;
37
use OCA\Deck\BadRequestException;
38
39
class CardService {
40
41
	private $cardMapper;
42
	private $stackMapper;
43
	private $boardMapper;
44
	private $labelMapper;
45
	private $permissionService;
46
	private $boardService;
47
	private $notificationHelper;
48
	private $assignedUsersMapper;
49
	private $attachmentService;
50
	private $currentUser;
51
52 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...
53
		CardMapper $cardMapper,
54
		StackMapper $stackMapper,
55
		BoardMapper $boardMapper,
56
		LabelMapper $labelMapper,
57
		PermissionService $permissionService, 
58
		BoardService $boardService,
59
		NotificationHelper $notificationHelper,
60
		AssignedUsersMapper $assignedUsersMapper, 
61
		AttachmentService $attachmentService,
62
		$userId
63
	) {
64
		$this->cardMapper = $cardMapper;
65
		$this->stackMapper = $stackMapper;
66
		$this->boardMapper = $boardMapper;
67
		$this->labelMapper = $labelMapper;
68
		$this->permissionService = $permissionService;
69
		$this->boardService = $boardService;
70
		$this->notificationHelper = $notificationHelper;
71
		$this->assignedUsersMapper = $assignedUsersMapper;
72
		$this->attachmentService = $attachmentService;
73
		$this->currentUser = $userId;
74
	}
75
76
	public function enrich($card) {
77
		$cardId = $card->getId();
78
		$card->setAssignedUsers($this->assignedUsersMapper->find($cardId));
79
		$card->setLabels($this->labelMapper->findAssignedLabelsForCard($cardId));
80
		$card->setAttachmentCount($this->attachmentService->count($cardId));
81
	}
82
83
	public function fetchDeleted($boardId) {
84
		$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_READ);
85
		$cards = $this->cardMapper->findDeleted($boardId);
86
		foreach ($cards as $card) {
87
			$this->enrich($card);
88
		}
89
		return $cards;
90
	}
91
92
	/**
93
	 * @param $cardId
94
	 * @return \OCA\Deck\Db\RelationalEntity
95
	 * @throws \OCA\Deck\NoPermissionException
96
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
97
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
98
	 * @throws BadRequestException
99
	 */
100
	public function find($cardId) {
101
102
		if (is_numeric($cardId) === false) {
103
			throw new BadRequestException('card id must be a number');
104
		}
105
106
		$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
107
		$card = $this->cardMapper->find($cardId);
108
		$assignedUsers = $this->assignedUsersMapper->find($card->getId());
109
		$attachments = $this->attachmentService->findAll($cardId, true);
110
		$card->setAssignedUsers($assignedUsers);
111
		$card->setAttachments($attachments);
112
		return $card;
113
	}
114
115
	/**
116
	 * @param $title
117
	 * @param $stackId
118
	 * @param $type
119
	 * @param integer $order
120
	 * @param $owner
121
	 * @return \OCP\AppFramework\Db\Entity
122
	 * @throws StatusException
123
	 * @throws \OCA\Deck\NoPermissionException
124
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
125
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
126
	 * @throws BadrequestException
127
	 */
128
	public function create($title, $stackId, $type, $order, $owner) {
129
130
		if ($title === 'false' || $title === null) {
131
			throw new BadRequestException('title must be provided');
132
		}
133
134
		if (is_numeric($stackId) === false) {
135
			throw new BadRequestException('stack id must be a number');
136
		}
137
138
		if ($type === 'false' || $type === null) {
139
			throw new BadRequestException('type must be provided');
140
		}
141
142
		if (is_numeric($order) === false) {
143
			throw new BadRequestException('order must be a number');
144
		}
145
146
		if ($owner === false || $owner === null) {
147
			throw new BadRequestException('owner must be provided');
148
		}
149
150
		$this->permissionService->checkPermission($this->stackMapper, $stackId, Acl::PERMISSION_EDIT);
151
		if ($this->boardService->isArchived($this->stackMapper, $stackId)) {
152
			throw new StatusException('Operation not allowed. This board is archived.');
153
		}
154
		$card = new Card();
155
		$card->setTitle($title);
156
		$card->setStackId($stackId);
157
		$card->setType($type);
158
		$card->setOrder($order);
159
		$card->setOwner($owner);
160
		return $this->cardMapper->insert($card);
161
	}
162
163
	/**
164
	 * @param $id
165
	 * @return \OCP\AppFramework\Db\Entity
166
	 * @throws StatusException
167
	 * @throws \OCA\Deck\NoPermissionException
168
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
169
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
170
	 * @throws BadRequestException
171
	 */
172 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...
173
174
		if (is_numeric($id) === false) {
175
			throw new BadRequestException('card id must be a number');
176
		}
177
178
		$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
179
		if ($this->boardService->isArchived($this->cardMapper, $id)) {
180
			throw new StatusException('Operation not allowed. This board is archived.');
181
		}
182
		$card = $this->cardMapper->find($id);
183
		$card->setDeletedAt(time());
184
		$this->cardMapper->update($card);
185
		return $card;
186
	}
187
188
	/**
189
	 * @param $id
190
	 * @param $title
191
	 * @param $stackId
192
	 * @param $type
193
	 * @param $order
194
	 * @param $description
195
	 * @param $owner
196
	 * @param $duedate
197
	 * @return \OCP\AppFramework\Db\Entity
198
	 * @throws StatusException
199
	 * @throws \OCA\Deck\NoPermissionException
200
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
201
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
202
	 * @throws BadRequestException
203
	 */
204
	public function update($id, $title, $stackId, $type, $order = 0, $description = '', $owner, $duedate = null, $deletedAt) {
205
206
		if (is_numeric($id) === false) {
207
			throw new BadRequestException('card id must be a number');			
208
		}
209
210
		if ($title === false || $title === null) {
211
			throw new BadRequestException('title must be provided');
212
		}
213
214
		if (is_numeric($stackId) === false) {
215
			throw new BadRequestException('stack id must be a number $$$');
216
		}
217
218
		if ($type === false || $type === null) {
219
			throw new BadRequestException('type must be provided');
220
		}
221
222
		if ($owner === false || $owner === null) {
223
			throw new BadRequestException('owner must be provided');
224
		}
225
226
		$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
227
		if ($this->boardService->isArchived($this->cardMapper, $id)) {
228
			throw new StatusException('Operation not allowed. This board is archived.');
229
		}
230
		$card = $this->cardMapper->find($id);
231
		if ($card->getArchived()) {
232
			throw new StatusException('Operation not allowed. This card is archived.');
233
		}
234
		$card->setTitle($title);
235
		$card->setStackId($stackId);
236
		$card->setType($type);
237
		$card->setOrder($order);
238
		$card->setOwner($owner);
239
		$card->setDescription($description);
240
		$card->setDuedate($duedate);
241
		$card->setDeletedAt($deletedAt);
242
		return $this->cardMapper->update($card);
243
	}
244
245
	/**
246
	 * @param $id
247
	 * @param $title
248
	 * @return \OCP\AppFramework\Db\Entity
249
	 * @throws StatusException
250
	 * @throws \OCA\Deck\NoPermissionException
251
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
252
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
253
	 * @throws BadRequestException
254
	 */
255
	public function rename($id, $title) {
256
257
		if (is_numeric($id) === false) {
258
			throw new BadRequestException('id must be a number');
259
		}
260
261
		if ($title === false || $title === null) {
262
			throw new BadRequestException('title must be provided');
263
		}
264
265
		$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
266
		if ($this->boardService->isArchived($this->cardMapper, $id)) {
267
			throw new StatusException('Operation not allowed. This board is archived.');
268
		}
269
		$card = $this->cardMapper->find($id);
270
		if ($card->getArchived()) {
271
			throw new StatusException('Operation not allowed. This card is archived.');
272
		}
273
		$card->setTitle($title);
274
		return $this->cardMapper->update($card);
275
	}
276
277
	/**
278
	 * @param $id
279
	 * @param $stackId
280
	 * @param $order
281
	 * @return array
282
	 * @throws StatusException
283
	 * @throws \OCA\Deck\NoPermissionException
284
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
285
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
286
	 * @throws BadRequestException
287
	 */
288
	public function reorder($id, $stackId, $order) {
289
290
		if (is_numeric($id) === false) {
291
			throw new BadRequestException('card id must be a number');
292
		}
293
294
		if (is_numeric($stackId) === false) {
295
			throw new BadRequestException('stack id must be a number');
296
		}
297
298
		if (is_numeric($order) === false) {
299
			throw new BadRequestException('order must be a number');
300
		}
301
302
		$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
303
		if ($this->boardService->isArchived($this->cardMapper, $id)) {
304
			throw new StatusException('Operation not allowed. This board is archived.');
305
		}
306
		$cards = $this->cardMapper->findAll($stackId);
307
		$result = [];
308
		$i = 0;
309
		foreach ($cards as $card) {
310
			if ($card->getArchived()) {
311
				throw new StatusException('Operation not allowed. This card is archived.');
312
			}
313
			if ($card->id === $id) {
314
				$card->setOrder($order);
315
				$card->setLastModified(time());
316
			}
317
318
			if ($i === $order) {
319
				$i++;
320
			}
321
322
			if ($card->id !== $id) {
323
				$card->setOrder($i++);
324
			}
325
			$this->cardMapper->update($card);
326
			$result[$card->getOrder()] = $card;
327
		}
328
329
		return $result;
330
	}
331
332
	/**
333
	 * @param $id
334
	 * @return \OCP\AppFramework\Db\Entity
335
	 * @throws StatusException
336
	 * @throws \OCA\Deck\NoPermissionException
337
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
338
	 * @throws \OCP\AppFramework\Db\
339
	 * @throws BadRequestException
340
	 */
341 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...
342
343
		if (is_numeric($id) === false) {
344
			throw new BadRequestException('id must be a number');
345
		}
346
347
		$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
348
		if ($this->boardService->isArchived($this->cardMapper, $id)) {
349
			throw new StatusException('Operation not allowed. This board is archived.');
350
		}
351
		$card = $this->cardMapper->find($id);
352
		$card->setArchived(true);
353
		return $this->cardMapper->update($card);
354
	}
355
356
	/**
357
	 * @param $id
358
	 * @return \OCP\AppFramework\Db\Entity
359
	 * @throws StatusException
360
	 * @throws \OCA\Deck\NoPermissionException
361
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
362
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
363
	 * @throws BadRequestException
364
	 */
365 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...
366
367
		if (is_numeric($id) === false) {
368
			throw new BadRequestException('id must be a number');
369
		}
370
371
		$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
372
		if ($this->boardService->isArchived($this->cardMapper, $id)) {
373
			throw new StatusException('Operation not allowed. This board is archived.');
374
		}
375
		$card = $this->cardMapper->find($id);
376
		$card->setArchived(false);
377
		return $this->cardMapper->update($card);
378
	}
379
380
	/**
381
	 * @param $cardId
382
	 * @param $labelId
383
	 * @throws StatusException
384
	 * @throws \OCA\Deck\NoPermissionException
385
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
386
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
387
	 * @throws BadRequestException
388
	 */
389 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...
390
391
		if (is_numeric($cardId) === false) {
392
			throw new BadRequestException('card id must be a number');
393
		}
394
395
		if (is_numeric($labelId) === false) {
396
			throw new BadRequestException('label id must be a number');
397
		}
398
399
		$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
400
		if ($this->boardService->isArchived($this->cardMapper, $cardId)) {
401
			throw new StatusException('Operation not allowed. This board is archived.');
402
		}
403
		$card = $this->cardMapper->find($cardId);
404
		if ($card->getArchived()) {
405
			throw new StatusException('Operation not allowed. This card is archived.');
406
		}
407
		$this->cardMapper->assignLabel($cardId, $labelId);
408
	}
409
410
	/**
411
	 * @param $cardId
412
	 * @param $labelId
413
	 * @throws StatusException
414
	 * @throws \OCA\Deck\NoPermissionException
415
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
416
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
417
	 * @throws BadRequestException
418
	 */
419 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...
420
421
		if (is_numeric($cardId) === false) {
422
			throw new BadRequestException('card id must be a number');
423
		}
424
425
		if (is_numeric($labelId) === false) {
426
			throw new BadRequestException('label id must be a number');
427
		}
428
429
		$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
430
		if ($this->boardService->isArchived($this->cardMapper, $cardId)) {
431
			throw new StatusException('Operation not allowed. This board is archived.');
432
		}
433
		$card = $this->cardMapper->find($cardId);
434
		if ($card->getArchived()) {
435
			throw new StatusException('Operation not allowed. This card is archived.');
436
		}
437
		$this->cardMapper->removeLabel($cardId, $labelId);
438
	}
439
440
	/**
441
	 * @param $cardId
442
	 * @param $userId
443
	 * @return bool|null|\OCP\AppFramework\Db\Entity
444
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
445
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
446
	 * @throws BadRequestException
447
	 */
448
	public function assignUser($cardId, $userId) {
449
450
		if (is_numeric($cardId) === false) {
451
			throw new BadRequestException('card id must be a number');
452
		}
453
454
		if ($userId === false || $userId === null) {
455
			throw new BadRequestException('user id must be provided');
456
		}
457
458
		$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
459
		$assignments = $this->assignedUsersMapper->find($cardId);
460
		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...
461
			if ($assignment->getParticipant() === $userId) {
462
				return false;
463
			}
464
		}
465
466
		if ($userId !== $this->currentUser) {
467
			/* Notifyuser about the card assignment */
468
			$card = $this->cardMapper->find($cardId);
469
			$this->notificationHelper->sendCardAssigned($card, $userId);
470
		}
471
472
		$assignment = new AssignedUsers();
473
		$assignment->setCardId($cardId);
474
		$assignment->setParticipant($userId);
475
		return $this->assignedUsersMapper->insert($assignment);
476
	}
477
478
	/**
479
	 * @param $cardId
480
	 * @param $userId
481
	 * @return \OCP\AppFramework\Db\Entity
482
	 * @throws NotFoundException
483
	 * @throws \OCP\AppFramework\Db\DoesNotExistException
484
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
485
	 * @throws BadRequestException
486
	 */
487
	public function unassignUser($cardId, $userId) {
488
		$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
489
490
		if (is_numeric($cardId) === false) {
491
			throw new BadRequestException('card id must be a number');
492
		}
493
494
		if ($userId === false || $userId === null) {
495
			throw new BadRequestException('user must be provided');
496
		}
497
498
		$assignments = $this->assignedUsersMapper->find($cardId);
499
		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...
500
			if ($assignment->getParticipant() === $userId) {
501
				return $this->assignedUsersMapper->delete($assignment);
502
			}
503
		}
504
		throw new NotFoundException('No assignment for ' . $userId . 'found.');
505
	}
506
}
507