ItemController::update()   A
last analyzed

Complexity

Conditions 3
Paths 6

Size

Total Lines 32
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 26
c 1
b 0
f 0
nc 6
nop 2
dl 0
loc 32
ccs 0
cts 31
cp 0
crap 12
rs 9.504
1
<?php
2
3
namespace App\Controller\Api;
4
5
use App\Command\CreateItemCommand;
6
use App\Command\UpdateItemCommand;
7
use App\Command\DeleteItemCommand;
8
use App\Error\ApiError;
9
use App\Repository\Exception\ItemNotFoundException;
10
use App\Repository\ItemRepository;
11
use App\Request\CreateItemRequest;
12
use App\Request\UpdateItemRequest;
13
use App\Traits\JsonErrorResponse;
14
use Psr\Log\LoggerInterface;
15
use Ramsey\Uuid\Uuid;
16
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
17
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
18
use Symfony\Component\HttpFoundation\JsonResponse;
19
use Symfony\Component\HttpFoundation\Request;
20
use Symfony\Component\HttpFoundation\Response;
21
use Symfony\Component\Messenger\MessageBusInterface;
22
use Symfony\Component\Routing\Annotation\Route;
23
use Symfony\Component\Validator\ConstraintViolationListInterface;
24
use Swagger\Annotations as SWG;
25
use App\CommandHandler\Exception\ItemNotDeletedException;
26
use App\Request\AddItemToCollectionRequest;
27
use App\Command\AddItemToCollectionCommand;
28
use App\Request\RemoveItemFromCollectionRequest;
29
use App\Command\RemoveItemFromCollectionCommand;
30
use Nelmio\ApiDocBundle\Annotation\Model;
31
32
class ItemController extends AbstractController
33
{
34
    use JsonErrorResponse;
35
36
    /**
37
     * @var MessageBusInterface
38
     */
39
    private $commandBus;
40
    /**
41
     * @var LoggerInterface
42
     */
43
    private $logger;
44
    /**
45
     * @var ItemRepository
46
     */
47
    private $repository;
48
49
    /**
50
     * @param MessageBusInterface $commandBus
51
     * @param LoggerInterface $logger
52
     * @param ItemRepository $repository
53
     */
54
    public function __construct(
55
        MessageBusInterface $commandBus,
56
        LoggerInterface $logger,
57
        ItemRepository $repository
58
    )
59
    {
60
        $this->commandBus = $commandBus;
61
        $this->logger = $logger;
62
        $this->repository = $repository;
63
    }
64
65
    /**
66
     * @Route("/api/items", name="item_create", methods={"POST"})
67
     *
68
     * @ParamConverter("request", converter="fos_rest.request_body")
69
     * 
70
     * @SWG\Tag(name="Items")
71
     * @SWG\Post(
72
     *     @SWG\Parameter(
73
     *          name="body",
74
     *          in="body",
75
     *          required=true,
76
     *          format="application/json",
77
     *          @SWG\Schema(
78
     *              required={"name"},
79
     *              @SWG\Property(property="name", type="string", maxLength=255),
80
     *              @SWG\Property(property="categoryId", type="string", format="UUID") ,
81
     *              @SWG\Property(property="year", type="integer"),
82
     *              @SWG\Property(property="format", type="string"),
83
     *              @SWG\Property(property="author", type="string"),
84
     *              @SWG\Property(property="publisher", type="string"),
85
     *              @SWG\Property(property="description", type="string"),
86
     *              @SWG\Property(property="store", type="string"),
87
     *              @SWG\Property(property="url", type="string"),
88
     *          )
89
     *     )
90
     * )
91
     * @SWG\Response(
92
     *     response=201,
93
     *     description="Returns ID of created Item",
94
     *     @SWG\Schema(
95
     *          @SWG\Property(property="id", type="string", format="UUID")
96
     *     )
97
     * )
98
     * @SWG\Response(
99
     *     response=422,
100
     *     description="Item was not created"
101
     * )
102
     * 
103
     * @param CreateItemRequest $request
104
     * @param ConstraintViolationListInterface $validationErrors
105
     * @return JsonResponse
106
     */
107
    public function create(CreateItemRequest $request, ConstraintViolationListInterface $validationErrors): JsonResponse
108
    {
109
        if ($validationErrors->count()) {
110
            return $this->jsonError(ApiError::ENTITY_VALIDATION_ERROR,
111
                'Validations errors for create Item',
112
                Response::HTTP_BAD_REQUEST,
113
                $this->parseFormErrors($validationErrors)
114
            );
115
        }
116
117
        try {
118
            $id = Uuid::uuid4();
119
            $command = new CreateItemCommand(
120
                $id,
121
                $request->getName(),
122
                $request->getCategoryId(),
123
                $request->getYear(),
124
                $request->getFormat(),
125
                $request->getAuthor(),
126
                $request->getPublisher(),
127
                $request->getDescription(),
128
                $request->getStore(),
129
                $request->getUrl(),
130
                null
131
            );
132
            $this->commandBus->dispatch($command);
133
            return $this->json(['id' => $id], Response::HTTP_CREATED);
134
        } catch (\Exception $e) {
135
            $this->logger->critical($e->getMessage());
136
            return $this->jsonError(ApiError::ENTITY_CREATE_ERROR,
137
                $e->getMessage(),
138
                Response::HTTP_UNPROCESSABLE_ENTITY
139
            );
140
        }
141
    }
142
143
    /**
144
     * @Route("/api/items/{id}", name="item_get", methods={"GET"})
145
     *
146
     * @SWG\Tag(name="Items")
147
     * @SWG\Get(
148
     *     @SWG\Parameter(name="id", in="path", type="string", format="UUID"),
149
     *     @SWG\Response(
150
     *          response="200", 
151
     *          description="Item details",
152
     *          @SWG\Schema(
153
     *              @SWG\Property(property="id", type="string", format="UUID") ,
154
     *              @SWG\Property(property="name", type="string"),
155
     *              @SWG\Property(property="categoryId", type="string", format="UUID") ,
156
     *              @SWG\Property(property="year", type="integer"),
157
     *              @SWG\Property(property="format", type="string"),
158
     *              @SWG\Property(property="author", type="string"),
159
     *              @SWG\Property(property="publisher", type="string"),
160
     *              @SWG\Property(property="description", type="string"),
161
     *              @SWG\Property(property="store", type="string"),
162
     *              @SWG\Property(property="url", type="string")
163
     *         )
164
     *     ),
165
     *     @SWG\Response(response="404", description="Item not found"),
166
     *     @SWG\Response(response="422", description="Validation failed")
167
     * )
168
     * 
169
     * @param string $id
170
     * @return JsonResponse
171
     */
172
    public function getItemAction(string $id): JsonResponse
173
    {
174
        try {
175
            $uuid = Uuid::fromString($id);
176
            return $this->json($this->repository->getItem($uuid));
177
        } catch (\Ramsey\Uuid\Exception\InvalidUuidStringException $e) {
178
            return $this->jsonError(ApiError::ENTITY_UUID_ERROR,
179
                $e->getMessage(),
180
                Response::HTTP_UNPROCESSABLE_ENTITY
181
            );
182
        } catch (ItemNotFoundException $e) {
183
            return $this->jsonError(ApiError::ENTITY_READ_ERROR,
184
                $e->getMessage(),
185
                Response::HTTP_NOT_FOUND
186
            );
187
        }
188
        catch (\Exception $e) {
189
            $this->logger->critical($e->getMessage());
190
            return $this->jsonError(ApiError::ENTITY_READ_ERROR,
191
                $e->getMessage(),
192
                Response::HTTP_NOT_FOUND
193
                );
194
        }
195
    }
196
    
197
    /**
198
     * @Route("/api/items", name="item_update", methods={"PATCH"})
199
     *
200
     * @ParamConverter("request", converter="fos_rest.request_body")
201
     *
202
     * @SWG\Tag(name="Items")
203
     * @SWG\Patch(
204
     *     @SWG\Parameter(
205
     *          name="body",
206
     *          in="body",
207
     *          required=true,
208
     *          format="application/json",
209
     *          @SWG\Schema(
210
     *              required={"id", "name"},
211
     *              @SWG\Property(property="id", type="string", format="UUID"),
212
     *              @SWG\Property(property="name", type="string", maxLength=255),
213
     *              @SWG\Property(property="categoryId", type="string", format="UUID") ,
214
     *              @SWG\Property(property="year", type="integer"),
215
     *              @SWG\Property(property="format", type="string"),
216
     *              @SWG\Property(property="author", type="string"),
217
     *              @SWG\Property(property="publisher", type="string"),
218
     *              @SWG\Property(property="description", type="string"),
219
     *              @SWG\Property(property="store", type="string"),
220
     *              @SWG\Property(property="url", type="string"),
221
     *          )
222
     *     )
223
     * )
224
     * @SWG\Response(
225
     *     response=200,
226
     *     description="Item has been updated",
227
     *     @SWG\Schema(
228
     *              @SWG\Property(property="id", type="string", format="UUID"),
229
     *              @SWG\Property(property="name", type="string", maxLength=255),
230
     *              @SWG\Property(property="categoryId", type="string", format="UUID") ,
231
     *              @SWG\Property(property="year", type="integer"),
232
     *              @SWG\Property(property="format", type="string"),
233
     *              @SWG\Property(property="author", type="string"),
234
     *              @SWG\Property(property="publisher", type="string"),
235
     *              @SWG\Property(property="description", type="string"),
236
     *              @SWG\Property(property="store", type="string"),
237
     *              @SWG\Property(property="url", type="string"),
238
     *     )
239
     * )
240
     * @SWG\Response(
241
     *     response=422,
242
     *     description="Item was not updated"
243
     * )
244
     *
245
     * @param UpdateItemRequest $request
246
     * @param ConstraintViolationListInterface $validationErrors
247
     * @return JsonResponse
248
     */
249
    public function update(UpdateItemRequest $request, ConstraintViolationListInterface $validationErrors): JsonResponse
250
    {
251
        if ($validationErrors->count()) {
252
            return $this->jsonError(ApiError::ENTITY_VALIDATION_ERROR,
253
                'Validations errors for update Item',
254
                Response::HTTP_BAD_REQUEST,
255
                $this->parseFormErrors($validationErrors)
256
                );
257
        }
258
        
259
        try {
260
            $command = new UpdateItemCommand(
261
                $request->getId(),
262
                $request->getName(),
263
                $request->getCategoryId(),
264
                $request->getYear(),
265
                $request->getFormat(),
266
                $request->getAuthor(),
267
                $request->getPublisher(),
268
                $request->getDescription(),
269
                $request->getStore(),
270
                $request->getUrl(),
271
                null
272
                );
273
            $this->commandBus->dispatch($command);
274
            $item = $this->repository->getItem($command->getId());
275
            return $this->json($item, Response::HTTP_OK);
276
        } catch (\Exception $e) {
277
            $this->logger->critical($e->getMessage());
278
            return $this->jsonError(ApiError::ENTITY_CREATE_ERROR,
279
                $e->getMessage(),
280
                Response::HTTP_UNPROCESSABLE_ENTITY
281
                );
282
        }
283
    }
284
285
    /**
286
     * Delete Item
287
     *
288
     * @SWG\Tag(name="Items")
289
     * @SWG\Response(
290
     *     response="204",
291
     *     description="Item was deleted"
292
     * )
293
     * @SWG\Response(
294
     *     response="404",
295
     *     description="Item not found",
296
     * )
297
     *
298
     * @SWG\Response(
299
     *     response="422",
300
     *     description="Item was not removed",
301
     * )
302
     *
303
     * @Route("/api/items/{id}", name="items-delete", methods={"DELETE"})
304
     * @param string $id
305
     * @return JsonResponse
306
     */
307
    public function delete(string $id): JsonResponse
308
    {
309
        try {
310
            $uuid = Uuid::fromString($id);
311
            $command = new DeleteItemCommand($uuid);
312
            $this->commandBus->dispatch($command);
313
            return $this->json(null, Response::HTTP_NO_CONTENT);
314
        } catch (\Ramsey\Uuid\Exception\InvalidUuidStringException $e) {
315
            return $this->jsonError(ApiError::ENTITY_UUID_ERROR,
316
                $e->getMessage(),
317
                Response::HTTP_UNPROCESSABLE_ENTITY
318
                );
319
        } catch (ItemNotFoundException $e) {
320
            return $this->jsonError(ApiError::ENTITY_READ_ERROR,
321
                $e->getMessage(),
322
                Response::HTTP_NOT_FOUND
323
                );
324
        } catch (ItemNotDeletedException $e) {
325
            return $this->jsonError(ApiError::ENTITY_DELETE_ERROR,
326
                $e->getMessage(),
327
                Response::HTTP_BAD_REQUEST
328
                );
329
        }
330
    }    
331
332
    /**
333
     * @Route("/api/item/collection", name="add_item_to_collection", methods={"POST"})
334
     *
335
     * @SWG\Tag(name="Items")
336
     * @SWG\Post(
337
     *     @SWG\Parameter(
338
     *          name="body",
339
     *          in="body",
340
     *          required=true,
341
     *          format="application/json",
342
     *          @SWG\Schema(
343
     *              required={"name"},
344
     *              @SWG\Property(property="itemId", type="string", format="UUID"),
345
     *              @SWG\Property(property="categoryId", type="string", format="UUID"),
346
     *          )
347
     *     )
348
     * )
349
     * @SWG\Response(
350
     *     response=201,
351
     *     description="Item added to collection"
352
     * )
353
     * @SWG\Response(
354
     *     response=422,
355
     *     description="Item was not added to collection"
356
     * )
357
     * @SWG\Response(
358
     *     response=404,
359
     *     description="Item or Collection nor found"
360
     * )
361
     *
362
     * @ParamConverter("request", converter="fos_rest.request_body")
363
     *
364
     * @param AddItemToCollectionRequest $request
365
     * @param ConstraintViolationListInterface $validationErrors
366
     * @return JsonResponse
367
     */
368
    public function addItemToCollection(AddItemToCollectionRequest $request, ConstraintViolationListInterface $validationErrors): JsonResponse
369
    {
370
        if ($validationErrors->count()) {
371
            return  $this->jsonError(ApiError::ENTITY_VALIDATION_ERROR,
372
                'Validations errors for create Item',
373
                Response::HTTP_BAD_REQUEST,
374
                $this->parseFormErrors($validationErrors)
375
                );
376
        }
377
        
378
        try {
379
            $command = new AddItemToCollectionCommand(
380
                $request->getItemId(),
381
                $request->getCollectionId()
382
                );
383
            $this->commandBus->dispatch($command);
384
            return $this->json(null, Response::HTTP_CREATED);
385
        } catch (\Exception $e) {
386
            $this->logger->critical($e->getMessage());
387
            return $this->jsonError(ApiError::ENTITY_CREATE_ERROR,
388
                $e->getMessage(),
389
                Response::HTTP_UNPROCESSABLE_ENTITY
390
                );
391
        }
392
    }
393
    
394
    /**
395
     * @Route("/api/item/collection", name="remove_item_from_collection", methods={"DELETE"})
396
     *
397
     * @SWG\Tag(name="Items")
398
     * @SWG\Delete(
399
     *     @SWG\Parameter(
400
     *          name="body",
401
     *          in="body",
402
     *          required=true,
403
     *          format="application/json",
404
     *          @SWG\Schema(
405
     *              required={"name"},
406
     *              @SWG\Property(property="itemId", type="string", format="UUID", format="UUID"),
407
     *              @SWG\Property(property="categoryId", type="string", format="UUID", format="UUID"),
408
     *          )
409
     *     )
410
     * )
411
     * @SWG\Response(
412
     *     response=204,
413
     *     description="Item removed from collection"
414
     * )
415
     * @SWG\Response(
416
     *     response=422,
417
     *     description="Item was not delete from collection"
418
     * )
419
     * @SWG\Response(
420
     *     response=404,
421
     *     description="Item or Collection not found"
422
     * )
423
     *
424
     * @ParamConverter("request", converter="fos_rest.request_body")
425
     *
426
     * @param RemoveItemFromCollectionRequest $request
427
     * @param ConstraintViolationListInterface $validationErrors
428
     * @return JsonResponse
429
     */
430
    public function removeItemFromCollection(RemoveItemFromCollectionRequest $request, ConstraintViolationListInterface $validationErrors): JsonResponse
431
    {
432
        if ($validationErrors->count()) {
433
            return  $this->jsonError(ApiError::ENTITY_VALIDATION_ERROR,
434
                'Validations errors for create Item',
435
                Response::HTTP_BAD_REQUEST,
436
                $this->parseFormErrors($validationErrors)
437
                );
438
        }
439
        
440
        try {
441
            $command = new RemoveItemFromCollectionCommand(
442
                $request->getItemId(),
443
                $request->getCollectionId()
444
                );
445
            $this->commandBus->dispatch($command);
446
            return $this->json(null, Response::HTTP_NO_CONTENT);
447
        } catch (\Exception $e) {
448
            $this->logger->critical($e->getMessage());
449
            return $this->jsonError(ApiError::ENTITY_CREATE_ERROR,
450
                $e->getMessage(),
451
                Response::HTTP_UNPROCESSABLE_ENTITY
452
                );
453
        }
454
    }
455
    
456
    /**
457
     * List items
458
     *
459
     * @SWG\Tag(name="Items")
460
     * @SWG\Response(
461
     *     response=200,
462
     *     description="List of all items",
463
     *     @SWG\Schema(
464
     *          type="array",
465
     *          @SWG\Items(ref=@Model(type=App\Entity\Item::class))
466
     *     )
467
     * )
468
     *
469
     * @param Request $request
470
     * @Route("/api/items", name="items-list", methods={"GET"})
471
     * @return JsonResponse
472
     */
473
    public function getItemsList(Request $request): JsonResponse
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

473
    public function getItemsList(/** @scrutinizer ignore-unused */ Request $request): JsonResponse

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
474
    {
475
        return $this->json($this->repository->listAllItemsForApi());
476
    }
477
    
478
    /**
479
     * List category items
480
     *
481
     * @SWG\Tag(name="Items")
482
     * @SWG\Response(
483
     *     response=200,
484
     *     description="List of category items",
485
     *     @SWG\Schema(
486
     *          type="array",
487
     *          @SWG\Items(ref=@Model(type=App\Entity\Item::class))
488
     *     )
489
     * )
490
     *
491
     * @param Request $request
492
     * @Route("/api/category/items/{categoryId}", name="items-in-category-list", methods={"GET"})
493
     * @return JsonResponse
494
     */
495
    public function getItemsInCategory(string $categoryId, Request $request): JsonResponse
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

495
    public function getItemsInCategory(string $categoryId, /** @scrutinizer ignore-unused */ Request $request): JsonResponse

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
496
    {
497
        try {
498
            $uuid = Uuid::fromString($categoryId);
499
            return $this->json($this->repository->getItemsInCategory($uuid));
500
        } catch (\Exception$e) {
501
            $this->logger->critical($e->getMessage());
502
            return $this->jsonError(ApiError::ENTITY_CREATE_ERROR,
503
                $e->getMessage(),
504
                Response::HTTP_UNPROCESSABLE_ENTITY
505
                );
506
        }
507
    }
508
    
509
    /**
510
     * List collection items
511
     *
512
     * @SWG\Tag(name="Items")
513
     * @SWG\Response(
514
     *     response=200,
515
     *     description="List of collection items",
516
     *     @SWG\Schema(
517
     *          type="array",
518
     *          @SWG\Items(ref=@Model(type=App\Entity\Item::class))
519
     *     )
520
     * )
521
     *
522
     * @param Request $request
523
     * @Route("/api/collection/items/{collectionId}", name="items-in-collection-list", methods={"GET"})
524
     * @return JsonResponse
525
     */
526
    public function getItemsInCollection(string $collectionId, Request $request): JsonResponse
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

526
    public function getItemsInCollection(string $collectionId, /** @scrutinizer ignore-unused */ Request $request): JsonResponse

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
527
    {
528
        try {
529
            $uuid = Uuid::fromString($collectionId);
530
            return $this->json($this->repository->getItemsInCollection($uuid));
531
        } catch (\Exception$e) {
532
            $this->logger->critical($e->getMessage());
533
            return $this->jsonError(ApiError::ENTITY_CREATE_ERROR,
534
                $e->getMessage(),
535
                Response::HTTP_UNPROCESSABLE_ENTITY
536
                );
537
        }
538
    }
539
}
540