Passed
Push — master ( 21e202...0aab8f )
by Petr
03:53
created

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