Passed
Push — master ( e87c14...4d04ef )
by Petr
05:47 queued 02:34
created

BandController::createResponseFromUpdateForm()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

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