Passed
Push — master ( 2db6fa...1b9891 )
by Petr
03:38
created

EventController::findLikeAction()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 21
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2

Importance

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