Passed
Push — master ( 136a3c...f3426b )
by Petr
03:31
created

BandController::listAction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
crap 1
1
<?php
2
3
namespace AppBundle\Controller;
4
5
use AppBundle\Entity\Band;
6
use AppBundle\Entity\BandMember;
7
use AppBundle\Entity\DTO\CreateBandMemberDTO;
8
use AppBundle\Entity\DTO\CreateBand;
9
use AppBundle\Entity\DTO\UpdateBandMemberDTO;
10
use AppBundle\Entity\Repository\BandRepository;
11
use AppBundle\Entity\User;
12
use AppBundle\Response\ApiValidationError;
13
use AppBundle\Response\CreatedApiResponse;
14
use AppBundle\Response\EmptyApiResponse;
15
use AppBundle\Response\Infrastructure\AbstractApiResponse;
16
use AppBundle\Service\BandService;
17
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
18
use AppBundle\Controller\Infrastructure\RestController;
19
use AppBundle\Response\ApiError;
20
use AppBundle\Response\ApiResponse;
21
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
22
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
23
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
24
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
25
use Symfony\Component\Form\Extension\Core\Type\TextType;
26
use Symfony\Component\Form\FormInterface;
27
use Symfony\Component\HttpFoundation\Request;
28
use Symfony\Component\HttpFoundation\Response;
29
use Symfony\Component\Validator\Constraints as Assert;
30
31
/**
32
 * @author Vehsamrak
33
 * @Route("band")
34
 */
35
class BandController extends RestController
36
{
37
38
    /**
39
     * List all registered bands
40
     * @Route("s/{limit}/{offset}", name="bands_list")
41
     * @Method("GET")
42
     * @ApiDoc(
43
     *     section="Band",
44
     *     statusCodes={
45
     *         200="OK",
46
     *     }
47
     * )
48
     * @param int $limit Limit results. Default is 50
49
     * @param int $offset Starting serial number of result collection. Default is 0
50
     */
51 2
    public function listAction($limit = null, $offset = null): Response
52
    {
53 2
        return $this->respond(
54 2
            $this->createCompleteCollectionResponse($this->get('rockparade.band_repository'), $limit, $offset)
55
        );
56
    }
57
58
    /**
59
     * View band by name
60
     * @Route("/{bandName}", name="band_view")
61
     * @Method("GET")
62
     * @ApiDoc(
63
     *     section="Band",
64
     *     statusCodes={
65
     *         200="Band was found",
66
     *         404="Band with given name was not found",
67
     *     }
68
     * )
69
     * @param string $bandName band name
70
     */
71 3
    public function viewAction(string $bandName): Response
72
    {
73 3
        $bandRepository = $this->get('rockparade.band_repository');
74 3
        $band = $bandRepository->findOneByName($bandName);
75
76 3
        if ($band) {
77 2
            $response = new ApiResponse($band, Response::HTTP_OK);
78
        } else {
79 2
            $response = $this->createEntityNotFoundResponse(Band::class, $bandName);
80
        }
81
82 3
        return $this->respond($response);
83
    }
84
85
    /**
86
     * Create new band
87
     * @Route("", name="band_create")
88
     * @Method("POST")
89
     * @Security("has_role('ROLE_USER')")
90
     * @ApiDoc(
91
     *     section="Band",
92
     *     requirements={
93
     *         {
94
     *             "name"="name",
95
     *             "dataType"="string",
96
     *             "requirement"="true",
97
     *             "description"="band name"
98
     *         },
99
     *         {
100
     *             "name"="description",
101
     *             "dataType"="string",
102
     *             "requirement"="true",
103
     *             "description"="band description"
104
     *         },
105
     *         {
106
     *             "name"="members",
107
     *             "dataType"="array",
108
     *             "requirement"="true",
109
     *             "description"="logins and short descriptions of band musicians"
110
     *         },
111
     *     },
112
     *     statusCodes={
113
     *         201="New band was created. Link to new resource in header 'Location'",
114
     *         400="Validation error",
115
     *     }
116
     * )
117
     */
118 2
    public function createAction(Request $request): Response
119
    {
120 2
        $form = $this->createFormBandCreate();
121 2
        $this->processForm($request, $form);
122 2
        $form = $this->get('rockparade.band')->processFormAndCreateBand($form, $this->getUser());
123
124 2
        return $this->respond($this->createResponseFromCreateForm($form));
125
    }
126
127
    /**
128
     * Edit band
129
     * @Route("/{bandName}", name="band_edit")
130
     * @Method("PUT")
131
     * @Security("has_role('ROLE_USER')")
132
     * @ApiDoc(
133
     *     section="Band",
134
     *     requirements={
135
     *         {
136
     *             "name"="name",
137
     *             "dataType"="string",
138
     *             "requirement"="true",
139
     *             "description"="band name"
140
     *         },
141
     *         {
142
     *             "name"="description",
143
     *             "dataType"="string",
144
     *             "requirement"="true",
145
     *             "description"="band description"
146
     *         },
147
     *         {
148
     *             "name"="users",
149
     *             "dataType"="array",
150
     *             "requirement"="true",
151
     *             "description"="logins of band musicians"
152
     *         },
153
     *     },
154
     *     statusCodes={
155
     *         204="Band was edited with new data",
156
     *         400="Validation error",
157
     *     }
158
     * )
159
     * @param string $bandName band name
160
     */
161 2
    public function editAction(Request $request, string $bandName): Response
162
    {
163
        /** @var BandRepository $bandRepository */
164 2
        $bandRepository = $this->get('rockparade.band_repository');
165 2
        $band = $bandRepository->findOneByName($bandName);
166
167 2
        $form = $this->createFormBandCreate();
168 2
        $this->processForm($request, $form);
169 2
        $form = $this->get('rockparade.band')->processFormAndUpdateBand($form, $band, $this->getUser());
170
171 2
        return $this->respond($this->createResponseFromUpdateForm($form));
172
    }
173
174
    /**
175
     * List all band members
176
     * @Route("/{bandName}/members", name="band_members")
177
     * @Method("GET")
178
     * @ApiDoc(
179
     *     section="Band",
180
     *     statusCodes={
181
     *         200="OK",
182
     *         404="Band was not found",
183
     *     }
184
     * )
185
     */
186 4
    public function listMembersAction(string $bandName): Response
187
    {
188 4
        $bandRepository = $this->get('rockparade.band_repository');
189 4
        $band = $bandRepository->findOneByName($bandName);
190
191 4
        if (!$band) {
192
            $response = $this->createEntityNotFoundResponse(Band::class, $bandName);
193
        } else {
194 4
            $response = new ApiResponse($band->getMembers(), Response::HTTP_OK);
195
        }
196
197 4
        return $this->respond($response);
198
    }
199
200
    /**
201
     * Add member to band
202
     * @Route("/{bandName}/members", name="band_member_add")
203
     * @Method("POST")
204
     * @Security("has_role('ROLE_USER')")
205
     * @ApiDoc(
206
     *     section="Band",
207
     *     requirements={
208
     *         {
209
     *             "name"="login",
210
     *             "dataType"="string",
211
     *             "requirement"="true",
212
     *             "description"="user login"
213
     *         },
214
     *         {
215
     *             "name"="short_description",
216
     *             "dataType"="string",
217
     *             "requirement"="true",
218
     *             "description"="short description of musicians role in band"
219
     *         },
220
     *         {
221
     *             "name"="description",
222
     *             "dataType"="string",
223
     *             "requirement"="false",
224
     *             "description"="long description of musician"
225
     *         },
226
     *     },
227
     *     statusCodes={
228
     *         200="Member was added to the band",
229
     *         400="Validation error",
230
     *     }
231
     * )
232
     * @param string $bandName band name
233
     */
234 1
    public function addMemberAction(Request $request, string $bandName): Response
235
    {
236 1
        $form = $this->createFormCreateBandMember();
237 1
        $this->processForm($request, $form);
238
239 1
        if ($form->isValid()) {
240 1
            $bandRepository = $this->get('rockparade.band_repository');
241 1
            $band = $bandRepository->findOneByName($bandName);
242
243 1
            if (!$band) {
244
                $response = $this->createEntityNotFoundResponse(Band::class, $bandName);
245
            } else {
246 1
                $newUserLogin = $form->get('login')->getData();
247 1
                $newUser = $this->get('rockparade.user_repository')->findOneByLogin($newUserLogin);
248
249 1
                if (!$newUser) {
250
                    $response = $this->createEntityNotFoundResponse(User::class, $newUserLogin);
251
                } else {
252 1
                    $bandMemberRepository = $this->get('rockparade.band_member_repository');
253 1
                    $shortDescription = (string) $form->get('short_description')->getData();
254 1
                    $description = (string) $form->get('description')->getData();
255 1
                    $bandMember = $bandMemberRepository->getOrCreateByBandAndUser(
256
                        $band,
257
                        $newUser,
258
                        $shortDescription,
259
                        $description
260
                    );
261
262 1
                    $band->addMember($bandMember);
263 1
                    $bandRepository->flush();
264
265 1
                    $response = new EmptyApiResponse(Response::HTTP_OK);
266
                }
267
            }
268
        } else {
269
            $response = new ApiValidationError($form);
270
        }
271
272 1
        return $this->respond($response);
273
    }
274
275
    /**
276
     * Delete member from band
277
     * @Route("/{bandName}/member/{userLogin}", name="band_member_delete")
278
     * @Method("DELETE")
279
     * @Security("has_role('ROLE_USER')")
280
     * @ApiDoc(
281
     *     section="Band",
282
     *     statusCodes={
283
     *         204="Member was deleted from the band",
284
     *         404="Band or user was not found",
285
     *     }
286
     * )
287
     * @param string $bandName band name
288
     * @param string $userLogin member login
289
     */
290 1
    public function deleteMemberAction(string $bandName, string $userLogin)
291
    {
292 1
        $bandRepository = $this->get('rockparade.band_repository');
293 1
        $band = $bandRepository->findOneByName($bandName);
294
295 1
        if ($band) {
296 1
            $userRepository = $this->get('rockparade.user_repository');
297 1
            $user = $userRepository->findOneByLogin($userLogin);
298
299 1
            if ($user) {
300 1
                $bandMemberRepository = $this->get('rockparade.band_member_repository');
301 1
                $bandMember = $bandMemberRepository->findByBandAndUser($band, $user);
302
303 1
                if ($bandMember) {
304 1
                    $band->removeMember($bandMember);
305 1
                    $bandRepository->flush();
306
307 1
                    $response = new EmptyApiResponse(Response::HTTP_NO_CONTENT);
308
                } else {
309 1
                    $response = $this->createEntityNotFoundResponse(BandMember::class, $userLogin);
310
                }
311
            } else {
312 1
                $response = $this->createEntityNotFoundResponse(User::class, $userLogin);
313
            }
314
        } else {
315
            $response = $this->createEntityNotFoundResponse(Band::class, $bandName);
316
        }
317
318 1
        return $this->respond($response);
319
    }
320
    
321
    /**
322
     * Update band member
323
     * @Route("/{bandName}/member/{userLogin}", name="band_member_update")
324
     * @Method("PUT")
325
     * @Security("has_role('ROLE_USER')")
326
     * @ApiDoc(
327
     *     section="Band",
328
     *     requirements={
329
     *         {
330
     *             "name"="short_description",
331
     *             "dataType"="string",
332
     *             "requirement"="true",
333
     *             "description"="short description of role in band"
334
     *         },
335
     *         {
336
     *             "name"="description",
337
     *             "dataType"="string",
338
     *             "requirement"="false",
339
     *             "description"="long description of musician"
340
     *         },
341
     *     },
342
     *     statusCodes={
343
     *         204="Band member was successfully updated",
344
     *         404="Band or user was not found",
345
     *     }
346
     * )
347
     * @param string $bandName band name
348
     * @param string $userLogin member login
349
     */
350 1
    public function updateMemberAction(Request $request, string $bandName, string $userLogin)
351
    {
352 1
        $bandRepository = $this->get('rockparade.band_repository');
353 1
        $band = $bandRepository->findOneByName($bandName);
354
355 1
        if ($band) {
356 1
            $userRepository = $this->get('rockparade.user_repository');
357 1
            $user = $userRepository->findOneByLogin($userLogin);
358
359 1
            if ($user) {
360 1
                $bandMemberRepository = $this->get('rockparade.band_member_repository');
361 1
                $bandMember = $bandMemberRepository->findByBandAndUser($band, $user);
362
                
363 1
                if ($bandMember) {
364 1
                    $form = $this->createFormUpdateBandMember();
365 1
                    $this->processForm($request, $form);
366 1
                    $form = $this->get('rockparade.band')->processFormAndUpdateBandMember($form, $bandMember);
367
                    
368 1
                    $bandRepository->flush();
369
370 1
                    $response = $this->createResponseFromUpdateForm($form);
371
                } else {
372 1
                    $response = $this->createEntityNotFoundResponse(BandMember::class, $userLogin);
373
                }
374
            } else {
375 1
                $response = $this->createEntityNotFoundResponse(User::class, $userLogin);
376
            }
377
        } else {
378
            $response = $this->createEntityNotFoundResponse(Band::class, $bandName);
379
        }
380
381 1
        return $this->respond($response);
382
    }
383
384 1
    private function createLocationByNameFieldInForm(FormInterface $form): string
385
    {
386 1
        $bandName = $form->get('name')->getData();
387
388 1
        return $this->generateUrl('band_view', ['bandName' => $bandName]);
389
    }
390
391
    /**
392
     * @param $form
393
     * @param $band
394
     * @return ApiError|CreatedApiResponse|EmptyApiResponse
395
     */
396 2
    private function createResponseFromCreateForm(FormInterface $form): AbstractApiResponse
397
    {
398 2
        if ($form->isValid()) {
399 1
            return new CreatedApiResponse($this->createLocationByNameFieldInForm($form));
400
        } else {
401 1
            return new ApiValidationError($form);
402
        }
403
    }
404
405
    /**
406
     * @return ApiError|CreatedApiResponse|EmptyApiResponse
407
     */
408 3
    private function createResponseFromUpdateForm(FormInterface $form): AbstractApiResponse
409
    {
410 3
        if ($form->isValid()) {
411 2
            return new EmptyApiResponse(Response::HTTP_NO_CONTENT);
412
        } else {
413 1
            return new ApiValidationError($form);
414
        }
415
    }
416
417 4 View Code Duplication
    private function createFormBandCreate(): FormInterface
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...
418
    {
419 4
        $formBuilder = $this->createFormBuilder(new CreateBand());
420 4
        $formBuilder->add('name', TextType::class);
421 4
        $formBuilder->add(BandService::ATTRIBUTE_MEMBERS, TextType::class);
422 4
        $formBuilder->add('description', TextareaType::class);
423
424 4
        return $formBuilder->getForm();
425
    }
426
427 1 View Code Duplication
    private function createFormUpdateBandMember(): FormInterface
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...
428
    {
429 1
        $formBuilder = $this->createFormBuilder(new UpdateBandMemberDTO());
430 1
        $formBuilder->add('short_description', TextType::class);
431 1
        $formBuilder->add('description', TextareaType::class);
432
433 1
        return $formBuilder->getForm();
434
    }
435
436 1 View Code Duplication
    private function createFormCreateBandMember(): FormInterface
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...
437
    {
438 1
        $formBuilder = $this->createFormBuilder(new CreateBandMemberDTO());
439 1
        $formBuilder->add('login', TextType::class);
440 1
        $formBuilder->add('short_description', TextType::class);
441 1
        $formBuilder->add('description', TextareaType::class);
442
443 1
        return $formBuilder->getForm();
444
    }
445
}
446