Passed
Push — master ( a532fe...5ccf6a )
by Petr
03:21
created

BandController::listMembersAction()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 8

Duplication

Lines 13
Ratio 100 %

Code Coverage

Tests 6
CRAP Score 2.0116

Importance

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