Test Failed
Push — master ( 47b850...9fe266 )
by Petr
04:02
created

EventController::findLikeAction()   B

Complexity

Conditions 4
Paths 2

Size

Total Lines 23
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 23
ccs 9
cts 9
cp 1
rs 8.7972
c 0
b 0
f 0
cc 4
eloc 15
nc 2
nop 3
crap 4
1
<?php
2
3
namespace AppBundle\Controller;
4
5
use AppBundle\Controller\Infrastructure\RestController;
6
use AppBundle\Entity\DTO\CreateEventDTO;
7
use AppBundle\Entity\Event;
8
use AppBundle\Entity\Repository\EventRepository;
9
use AppBundle\Entity\Repository\ImageRepository;
10
use AppBundle\Exception\UnsupportedTypeException;
11
use AppBundle\Response\ApiError;
12
use AppBundle\Response\CollectionApiResponse;
13
use AppBundle\Response\CreatedApiResponse;
14
use AppBundle\Response\EmptyApiResponse;
15
use AppBundle\Response\LocationApiResponse;
16
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
17
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
18
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
19
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
20
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
21
use Symfony\Component\Form\Extension\Core\Type\DateType;
22
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
23
use Symfony\Component\Form\Extension\Core\Type\TextType;
24
use Symfony\Component\Form\FormBuilder;
25
use Symfony\Component\Form\FormError;
26
use Symfony\Component\Form\FormInterface;
27
use Symfony\Component\HttpFoundation\Request;
28
use Symfony\Component\HttpFoundation\Response;
29
use AppBundle\Response\ApiResponse;
30
31
/**
32
 * @Route("event")
33
 * @author Vehsamrak
34
 */
35
class EventController extends RestController
36
{
37
38
    /**
39
     * Find events by name part
40
     * @Route("s/like/{searchString}/{limit}/{offset}", name="events_find_like")
41
     * @Method("GET")
42
     * @ApiDoc(
43
     *     section="Event",
44
     *     statusCodes={
45
     *         200="OK",
46
     *     }
47
     * )
48
     * @param string $searchString Search string
49 4
     * @param int $limit Limit results. Default is 50
50
     * @param int $offset Starting serial number of result collection. Default is 0
51 4
     */
52 4
    public function findLikeAction($searchString = null, $limit = null, $offset = null)
53 4
    {
54
        $eventRepository = $this->get('rockparade.event_repository');
55 4
        $events = $eventRepository->findLike($searchString);
56 4
        $total = $events->count();
57
58 4
        $limit = (int) filter_var($limit, FILTER_VALIDATE_INT);
59 2
        $offset = (int) filter_var($offset, FILTER_VALIDATE_INT);
60
61
        if ($limit || $offset) {
62 4
            $events = $events->slice($offset, $limit ?: null);
63
        }
64 4
65
        $response = new CollectionApiResponse(
66
            $events,
67
            Response::HTTP_OK,
68
            $total,
69
            $limit,
70 4
            $offset
71
        );
72
73
        return $this->respond($response);
74
    }
75
76
    /**
77
     * List all events
78
     * @Route("s/{limit}/{offset}", name="events_list")
79
     * @Method("GET")
80
     * @ApiDoc(
81
     *     section="Event",
82
     *     statusCodes={
83
     *         200="OK",
84
     *     }
85
     * )
86 1
     * @param int $limit Limit results. Default is 50
87
     * @param int $offset Starting serial number of result collection. Default is 0
88 1
     */
89 1
    public function listAction($limit = null, $offset = null): Response
90 1
    {
91
        return $this->respond(
92
            $this->createCollectionResponse(
93
                $this->get('rockparade.event_repository'),
94
                $limit,
95
                $offset
96
            )
97
        );
98
    }
99
100
    /**
101
     * View event by id
102
     * @Route("/{eventId}", name="event_view")
103
     * @Method("GET")
104
     * @ApiDoc(
105
     *     section="Event",
106
     *     statusCodes={
107
     *         200="Event was found",
108
     *         404="Event with given id was not found",
109
     *     }
110 3
     * )
111
     * @param string $eventId event id
112
     */
113 3 View Code Duplication
    public function viewAction(string $eventId): Response
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...
114 3
    {
115
        /** @var EventRepository $eventRepository */
116 3
        $eventRepository = $this->get('rockparade.event_repository');
117 2
        $event = $eventRepository->findOneById($eventId);
118
119 1
        if ($event) {
120
            $response = new ApiResponse($event, Response::HTTP_OK);
121
        } else {
122 3
            $response = $this->createEventNotFoundErrorResult($eventId);
123
        }
124
125
        return $this->respond($response);
126
    }
127
128
    /**
129
     * Create new event
130
     * @Route("")
131
     * @Method("POST")
132
     * @Security("has_role('ROLE_USER')")
133
     * @ApiDoc(
134
     *     section="Event",
135
     *     requirements={
136
     *         {
137
     *             "name"="name",
138
     *             "dataType"="string",
139
     *             "requirement"="true",
140
     *             "description"="event name"
141
     *         },
142
     *         {
143
     *             "name"="date",
144
     *             "dataType"="date (dd-MM-yyyy HH:mm)",
145
     *             "requirement"="true",
146
     *             "description"="event date"
147
     *         },
148
     *         {
149
     *             "name"="description",
150
     *             "dataType"="text",
151
     *             "requirement"="true",
152
     *             "description"="event description"
153
     *         },
154
     *     },
155
     *     statusCodes={
156
     *         201="New event was created. Link to new resource in header 'Location'",
157
     *         400="Validation error",
158 2
     *     }
159
     * )
160 2
     */
161 2
    public function createAction(Request $request): Response
162
    {
163 2
        $form = $this->createEventCreationForm();
164 1
        $this->processForm($request, $form);
165
166
        if ($form->isValid()) {
167 1
            $newEvent = $this->createEventByForm($form);
168 1
169
            /** @var EventRepository $eventRepository */
170
            $eventRepository = $this->get('rockparade.event_repository');
171 1
            $eventRepository->persist($newEvent);
172 1
173
            try {
174
                $eventRepository->flush();
175 1
                $response = new CreatedApiResponse($this->createLocationById($newEvent->getId()));
176
            } catch (UniqueConstraintViolationException $exception) {
177
                $form->addError(new FormError('Event must have unique name and date.'));
178
                $response = new ApiError($this->getFormErrors($form), Response::HTTP_BAD_REQUEST);
179 1
            }
180
181
        } else {
182 2
            $response = new ApiError($this->getFormErrors($form), Response::HTTP_BAD_REQUEST);
183
        }
184
185
        return $this->respond($response);
186
    }
187
188
    /**
189
     * Edit event
190
     * @Route("/{eventId}", name="event_edit")
191
     * @Method("PUT")
192
     * @Security("has_role('ROLE_USER')")
193
     * @ApiDoc(
194
     *     section="Event",
195
     *     requirements={
196
     *         {
197
     *             "name"="name",
198
     *             "dataType"="string",
199
     *             "requirement"="true",
200
     *             "description"="event name"
201
     *         },
202
     *         {
203
     *             "name"="date",
204
     *             "dataType"="date (dd-MM-yyyy HH:mm)",
205
     *             "requirement"="true",
206
     *             "description"="event date"
207
     *         },
208
     *         {
209
     *             "name"="description",
210
     *             "dataType"="string",
211
     *             "requirement"="true",
212
     *             "description"="event description"
213
     *         },
214
     *     },
215
     *     statusCodes={
216
     *         204="Event was edited with new data",
217
     *         400="Validation error",
218
     *         404="Event with given id was not found",
219
     *     }
220 2
     * )
221
     * @param string $eventId event id
222 2
     */
223 2
    public function editAction(Request $request, string $eventId): Response
224
    {
225 2
        $form = $this->createEventCreationForm();
226
        $this->processForm($request, $form);
227 1
228
        if ($form->isValid()) {
229 1
            /** @var EventRepository $eventRepository */
230
            $eventRepository = $this->get('rockparade.event_repository');
231 1
            /** @var Event $event */
232
            $event = $eventRepository->findOneById($eventId);
233
234 1
            if (!$event) {
235
                $response = $this->createEventNotFoundErrorResult($eventId);
236 1
            } else {
237 1
                $eventName = $form->get('name')->getData();
238
                /** @var \DateTime $eventDate */
239 1
                $eventDate = $form->get('date')->getData();
240 1
                $eventDescription = $form->get('description')->getData();
241 1
242
                $event->setName($eventName);
243
                $event->setDate($eventDate);
244 1
                $event->setDescription($eventDescription);
245 1
246
                try {
247 1
                    $eventRepository->flush();
248
                    $response = new EmptyApiResponse(Response::HTTP_NO_CONTENT);
249
                } catch (UniqueConstraintViolationException $exception) {
250
                    $response = new ApiError(['Event must have unique name and date.'], Response::HTTP_BAD_REQUEST);
251
                }
252 1
            }
253
254
        } else {
255 2
            $response = new ApiError($this->getFormErrors($form), Response::HTTP_BAD_REQUEST);
256
        }
257
258
        return $this->respond($response);
259
    }
260
261
    /**
262
     * Delete event
263
     * @Route("/{eventId}", name="event_delete")
264
     * @Method("DELETE")
265
     * @Security("has_role('ROLE_USER')")
266
     * @ApiDoc(
267
     *     section="Event",
268
     *     statusCodes={
269
     *         204="Event was deleted",
270
     *         404="Event with given id was not found",
271
     *     }
272 1
     * )
273
     * @param string $eventId event id
274
     */
275 1 View Code Duplication
    public function deleteEvent(string $eventId): Response
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...
276 1
    {
277
        /** @var EventRepository $eventRepository */
278 1
        $eventRepository = $this->get('rockparade.event_repository');
279 1
        $event = $eventRepository->findOneById($eventId);
280 1
281
        if ($event) {
282 1
            $eventRepository->remove($event);
283
            $eventRepository->flush();
284
285
            $response = new EmptyApiResponse(Response::HTTP_NO_CONTENT);
286
        } else {
287
            $response = $this->createEventNotFoundErrorResult($eventId);
288 1
        }
289
290
        return $this->respond($response);
291 1
    }
292
293 1
    /**
294 1
     * Add image to event
295 1
     * @Route("/{eventId}/image", name="event_image_add")
296
     * @Method("POST")
297
     * @Security("has_role('ROLE_USER')")
298
     * @ApiDoc(
299 4
     *     section="Event",
300
     *     statusCodes={
301
     *         404="Event with given id was not found",
302 4
     *     }
303 4
     * )
304 4
     * @param string $eventId event id
305 4
     */
306 4
    public function addImageAction(Request $request, string $eventId): Response
307
    {
308 4
        /** @var EventRepository $eventRepository */
309
        $eventRepository = $this->get('rockparade.event_repository');
310
        $event = $eventRepository->findOneById($eventId);
311
312 4
        if ($event) {
313
            $image = $request->get('image');
314 4
315
            $imageName = $image['name'] ?: null;
316
            $imageContent = $image['content'] ?? null;
317 1
318
            if (!$image || !$imageName || !$imageContent) {
319 1
                $response = new ApiError(
320
                    'Parameters are mandatory: image[name] and image[content].',
321
                    Response::HTTP_BAD_REQUEST
322 1
                );
323
            } else {
324
                try {
325 1
                    $imageExtensionChecker = $this->get('rockparade.image_extension_checker');
326 1
                    $imageExtension = $imageExtensionChecker->getExtensionFromBase64File($imageContent);
327
                    $imageName = sprintf('%s.%s', $imageName, $imageExtension);
328 1
329
                    $imageLocation = $this->generateUrl(
330
                        'event_image_view',
331
                        [
332
                            'eventId'   => $eventId,
333
                            'imageName' => $imageName,
334
                        ]
335
                    );
336
337
                    $fileService = $this->get('rockparade.file_service');
338
                    $fileService->createBase64Image($imageName, $imageContent, $event);
339
340
                    $response = new LocationApiResponse(Response::HTTP_OK, $imageLocation);
341
                } catch (UnsupportedTypeException $exception) {
342
                    $response = new ApiError(
343
                        'Only images of types png, gif and jpeg are supported.',
344
                        Response::HTTP_BAD_REQUEST
345
                    );
346
                }
347
            }
348
        } else {
349
            $response = $this->createEventNotFoundErrorResult($eventId);
350
        }
351
352
        return $this->respond($response);
353
    }
354
355
    /**
356
     * Get event image
357
     * @Route("/{eventId}/image/{imageName}", name="event_image_view")
358
     * @Method("GET")
359
     * @ApiDoc(
360
     *     section="Event",
361
     *     statusCodes={
362
     *         404="Event with given id was not found",
363
     *         404="Image with given name was not found",
364
     *     }
365
     * )
366
     * @param string $eventId event id
367
     * @param string $imageName image name
368
     */
369
    public function viewImageAction(string $eventId, string $imageName): Response
370
    {
371
        /** @var EventRepository $eventRepository */
372
        $eventRepository = $this->get('rockparade.event_repository');
373
        $event = $eventRepository->findOneById($eventId);
374
375
        if ($event) {
376
            $image = $event->getImageWithName($imageName);
377
            $apiResponseFactory = $this->get('rockparade.api_response_factory');
378
379
            if ($image) {
380
                $response = $apiResponseFactory->createResponse($image);
381
            } else {
382
                $response = $apiResponseFactory->createNotFoundResponse();
383
            }
384
        } else {
385
            $response = $this->createEventNotFoundErrorResult($eventId);
386
        }
387
388
        return $this->respond($response);
389
    }
390
391
    /**
392
     * Delete event image
393
     * @Route("/{eventId}/image/{imageId}", name="event_image_delete")
394
     * @Method("DELETE")
395
     * @ApiDoc(
396
     *     section="Event",
397
     *     statusCodes={
398
     *         404="Event with given id was not found",
399
     *         404="Image with given id was not found",
400
     *     }
401
     * )
402
     * @param string $eventId event id
403
     * @param string $imageId image id
404
     */
405
    public function deleteImageAction(string $eventId, string $imageId)
406
    {
407
        /** @var EventRepository $eventRepository */
408
        $eventRepository = $this->get('rockparade.event_repository');
409
        /** @var ImageRepository $imageRepository */
410
        $imageRepository = $this->get('rockparade.image_repository');
411
        $event = $eventRepository->findOneById($eventId);
412
413
        if ($event) {
414
            $image = $imageRepository->findOneById($imageId);
415
416
            if ($image) {
417
                $event->removeImage($image);
418
                $eventRepository->flush();
419
                $response = new EmptyApiResponse(Response::HTTP_OK);
420
            } else {
421
                $apiResponseFactory = $this->get('rockparade.api_response_factory');
422
                $response = $apiResponseFactory->createNotFoundResponse();
423
            }
424
        } else {
425
            $response = $this->createEventNotFoundErrorResult($eventId);
426
        }
427
428
        return $this->respond($response);
429
    }
430
431
    private function createEventNotFoundErrorResult(string $eventId): ApiError
432
    {
433
        return new ApiError(
434
            sprintf('Event with id "%s" was not found.', $eventId),
435
            Response::HTTP_NOT_FOUND
436
        );
437
    }
438
439
    private function createEventCreationForm(): FormInterface
440
    {
441
        /** @var FormBuilder $formBuilder */
442
        $formBuilder = $this->createFormBuilder(new CreateEventDTO());
443
        $formBuilder->add('name', TextType::class);
444
        $formBuilder->add(
445
            'date',
446
            DateType::class,
447
            [
448
                'widget' => 'single_text',
449
                'format' => 'yyyy-MM-dd HH:mm',
450
            ]
451
        );
452
        $formBuilder->add('description', TextareaType::class);
453
454
        return $formBuilder->getForm();
455
    }
456
457
    private function createLocationById(string $eventId): string
458
    {
459
        return $this->generateUrl('event_view', ['eventId' => $eventId]);
460
    }
461
462
    private function createEventByForm(FormInterface $form): Event
463
    {
464
        /** @var CreateEventDTO $createEventDTO */
465
        $createEventDTO = $form->getData();
466
        $creator = $this->getUser();
467
468
        return new Event($createEventDTO->name, $creator, $createEventDTO->date, $createEventDTO->description);
0 ignored issues
show
Documentation introduced by
$creator is of type null|object, but the function expects a object<AppBundle\Entity\User>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
469
    }
470
}
471