Passed
Push — master ( 9d8bb8...60c6b0 )
by Petr
03:23
created

EventController::listAction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 10
c 0
b 0
f 0
rs 9.4285
ccs 4
cts 4
cp 1
cc 1
eloc 6
nc 1
nop 2
crap 1
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
     * @param int $limit Limit results. Default is 50
50
     * @param int $offset Starting serial number of result collection. Default is 0
51
     */
52 4
    public function findLikeAction($searchString = null, $limit = null, $offset = null)
53
    {
54 4
        $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 4
        $offset = (int) filter_var($offset, FILTER_VALIDATE_INT);
60
61 4
        if ($limit || $offset) {
62 2
            $events = $events->slice($offset, $limit ?: null);
63
        }
64
65 4
        $response = new CollectionApiResponse(
66
            $events,
67 4
            Response::HTTP_OK,
68
            $total,
69
            $limit,
70
            $offset
71
        );
72
73 4
        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
     * @param int $limit Limit results. Default is 50
87
     * @param int $offset Starting serial number of result collection. Default is 0
88
     */
89 1
    public function listAction($limit = null, $offset = null): Response
90
    {
91 1
        return $this->respond(
92 1
            $this->createCollectionResponse(
93 1
                $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
     * )
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
    {
115
        /** @var EventRepository $eventRepository */
116 3
        $eventRepository = $this->get('rockparade.event_repository');
117 3
        $event = $eventRepository->findOneById($eventId);
118
119 3
        if ($event) {
120 2
            $response = new ApiResponse($event, Response::HTTP_OK);
121
        } else {
122 1
            $response = $this->createEventNotFoundErrorResult($eventId);
123
        }
124
125 3
        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
     *     }
159
     * )
160
     */
161 2
    public function createAction(Request $request): Response
162
    {
163 2
        $form = $this->createEventCreationForm();
164 2
        $this->processForm($request, $form);
165
166 2
        if ($form->isValid()) {
167 1
            $newEvent = $this->createEventByForm($form);
168
169
            /** @var EventRepository $eventRepository */
170 1
            $eventRepository = $this->get('rockparade.event_repository');
171 1
            $eventRepository->persist($newEvent);
172
173
            try {
174 1
                $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 1
                $response = new ApiError($this->getFormErrors($form), Response::HTTP_BAD_REQUEST);
179
            }
180
181
        } else {
182 1
            $response = new ApiError($this->getFormErrors($form), Response::HTTP_BAD_REQUEST);
183
        }
184
185 2
        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
     * )
221
     * @param string $eventId event id
222
     */
223 2
    public function editAction(Request $request, string $eventId): Response
224
    {
225 2
        $form = $this->createEventCreationForm();
226 2
        $this->processForm($request, $form);
227
228 2
        if ($form->isValid()) {
229
            /** @var EventRepository $eventRepository */
230 1
            $eventRepository = $this->get('rockparade.event_repository');
231
            /** @var Event $event */
232 1
            $event = $eventRepository->findOneById($eventId);
233
234 1
            if (!$event) {
235
                $response = $this->createEventNotFoundErrorResult($eventId);
236
            } 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
242 1
                $event->setName($eventName);
243 1
                $event->setDate($eventDate);
244 1
                $event->setDescription($eventDescription);
245
246
                try {
247 1
                    $eventRepository->flush();
248 1
                    $response = new EmptyApiResponse(Response::HTTP_NO_CONTENT);
249
                } catch (UniqueConstraintViolationException $exception) {
250 1
                    $response = new ApiError(['Event must have unique name and date.'], Response::HTTP_BAD_REQUEST);
251
                }
252
            }
253
254
        } else {
255 1
            $response = new ApiError($this->getFormErrors($form), Response::HTTP_BAD_REQUEST);
256
        }
257
258 2
        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
     * )
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
    {
277
        /** @var EventRepository $eventRepository */
278 1
        $eventRepository = $this->get('rockparade.event_repository');
279 1
        $event = $eventRepository->findOneById($eventId);
280
281 1
        if ($event) {
282 1
            $eventRepository->remove($event);
283 1
            $eventRepository->flush();
284
285 1
            $response = new EmptyApiResponse(Response::HTTP_NO_CONTENT);
286
        } else {
287
            $response = $this->createEventNotFoundErrorResult($eventId);
288
        }
289
290 1
        return $this->respond($response);
291
    }
292
293
    /**
294
     * Add image to event
295
     * @Route("/{eventId}/image", name="event_image_add")
296
     * @Method("POST")
297
     * @Security("has_role('ROLE_USER')")
298
     * @ApiDoc(
299
     *     section="Event",
300
     *     statusCodes={
301
     *         404="Event with given id was not found",
302
     *     }
303
     * )
304
     * @param string $eventId event id
305
     */
306 3
    public function addImageAction(Request $request, string $eventId): Response
307
    {
308
        /** @var EventRepository $eventRepository */
309 3
        $eventRepository = $this->get('rockparade.event_repository');
310 3
        $event = $eventRepository->findOneById($eventId);
311
312 3
        if ($event) {
313 2
            $image = $request->get('image');
314
315 2
            $imageName = $image['name'] ?: null;
316 2
            $imageContent = $image['content'] ?? null;
317
318 2
            if (!$image || !$imageName || !$imageContent) {
319 1
                $response = new ApiError(
320 1
                    'Parameters are mandatory: image[name] and image[content].',
321 1
                    Response::HTTP_BAD_REQUEST
322
                );
323
            } else {
324
                try {
325 1
                    $imageExtensionChecker = $this->get('rockparade.image_extension_checker');
326 1
                    $imageExtension = $imageExtensionChecker->getExtensionFromBase64File($imageContent);
327 1
                    $imageName = sprintf('%s.%s', $imageName, $imageExtension);
328
329 1
                    $fileService = $this->get('rockparade.file_service');
330 1
                    $image = $fileService->createBase64Image($imageName, $imageContent, $event);
331
332 1
                    $imageLocation = $this->generateUrl(
333 1
                        'event_image_view',
334
                        [
335 1
                            'eventId'   => $eventId,
336 1
                            'imageName' => $image->getName(),
337
                        ]
338
                    );
339
340
341 1
                    $response = new LocationApiResponse(Response::HTTP_OK, $imageLocation);
342
                } catch (UnsupportedTypeException $exception) {
343
                    $response = new ApiError(
344
                        'Only images of types png, gif and jpeg are supported.',
345 2
                        Response::HTTP_BAD_REQUEST
346
                    );
347
                }
348
            }
349
        } else {
350 1
            $response = $this->createEventNotFoundErrorResult($eventId);
351
        }
352
353 3
        return $this->respond($response);
354
    }
355
356
    /**
357
     * Get event image
358
     * @Route("/{eventId}/image/{imageName}", name="event_image_view")
359
     * @Method("GET")
360
     * @ApiDoc(
361
     *     section="Event",
362
     *     statusCodes={
363
     *         404="Event with given id was not found",
364
     *         404="Image with given name was not found",
365
     *     }
366
     * )
367
     * @param string $eventId event id
368
     * @param string $imageName image name
369
     */
370 1
    public function viewImageAction(string $eventId, string $imageName): Response
371
    {
372
        /** @var EventRepository $eventRepository */
373 1
        $eventRepository = $this->get('rockparade.event_repository');
374 1
        $event = $eventRepository->findOneById($eventId);
375
376 1
        if ($event) {
377 1
            $image = $event->getImageWithName($imageName);
378 1
            $apiResponseFactory = $this->get('rockparade.api_response_factory');
379
380 1
            if ($image) {
381 1
                $response = $apiResponseFactory->createResponse($image);
382
            } else {
383 1
                $response = $apiResponseFactory->createNotFoundResponse();
384
            }
385
        } else {
386
            $response = $this->createEventNotFoundErrorResult($eventId);
387
        }
388
389 1
        return $this->respond($response);
390
    }
391
392
    /**
393
     * Delete event image
394
     * @Route("/{eventId}/image/{imageId}", name="event_image_delete")
395
     * @Method("DELETE")
396
     * @Security("has_role('ROLE_USER')")
397
     * @ApiDoc(
398
     *     section="Event",
399
     *     statusCodes={
400
     *         404="Event with given id was not found",
401
     *         404="Image with given id was not found",
402
     *     }
403
     * )
404
     * @param string $eventId event id
405
     * @param string $imageId image id
406
     */
407 1
    public function deleteImageAction(string $eventId, string $imageId)
408
    {
409
        /** @var EventRepository $eventRepository */
410 1
        $eventRepository = $this->get('rockparade.event_repository');
411
        /** @var ImageRepository $imageRepository */
412 1
        $imageRepository = $this->get('rockparade.image_repository');
413 1
        $event = $eventRepository->findOneById($eventId);
414
415 1
        if ($event) {
416 1
            $image = $imageRepository->findOneById($imageId);
417
418 1
            if ($image) {
419 1
                $event->removeImage($image);
420 1
                $eventRepository->flush();
421 1
                $response = new EmptyApiResponse(Response::HTTP_OK);
422
            } else {
423
                $apiResponseFactory = $this->get('rockparade.api_response_factory');
424 1
                $response = $apiResponseFactory->createNotFoundResponse();
425
            }
426
        } else {
427
            $response = $this->createEventNotFoundErrorResult($eventId);
428
        }
429
430 1
        return $this->respond($response);
431
    }
432
433 2
    private function createEventNotFoundErrorResult(string $eventId): ApiError
434
    {
435 2
        return new ApiError(
436 2
            sprintf('Event with id "%s" was not found.', $eventId),
437 2
            Response::HTTP_NOT_FOUND
438
        );
439
    }
440
441 4
    private function createEventCreationForm(): FormInterface
442
    {
443
        /** @var FormBuilder $formBuilder */
444 4
        $formBuilder = $this->createFormBuilder(new CreateEventDTO());
445 4
        $formBuilder->add('name', TextType::class);
446 4
        $formBuilder->add(
447 4
            'date',
448 4
            DateType::class,
449
            [
450 4
                'widget' => 'single_text',
451
                'format' => 'yyyy-MM-dd HH:mm',
452
            ]
453
        );
454 4
        $formBuilder->add('description', TextareaType::class);
455
456 4
        return $formBuilder->getForm();
457
    }
458
459 1
    private function createLocationById(string $eventId): string
460
    {
461 1
        return $this->generateUrl('event_view', ['eventId' => $eventId]);
462
    }
463
464 1
    private function createEventByForm(FormInterface $form): Event
465
    {
466
        /** @var CreateEventDTO $createEventDTO */
467 1
        $createEventDTO = $form->getData();
468 1
        $creator = $this->getUser();
469
470 1
        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...
471
    }
472
}
473