MediaController::upload()   A
last analyzed

Complexity

Conditions 5
Paths 5

Size

Total Lines 26
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 16
nc 5
nop 3
dl 0
loc 26
rs 9.4222
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Damax\Media\Bridge\Symfony\Bundle\Controller\Api;
6
7
use Damax\Common\Bridge\Symfony\Bundle\Annotation\Deserialize;
8
use Damax\Media\Application\Command\CreateMedia;
9
use Damax\Media\Application\Command\DeleteMedia;
10
use Damax\Media\Application\Command\UploadMedia;
11
use Damax\Media\Application\Dto\NewMediaDto;
12
use Damax\Media\Application\Dto\UploadDto;
13
use Damax\Media\Application\Exception\MediaNotFound;
14
use Damax\Media\Application\Exception\MediaUploadFailure;
15
use Damax\Media\Domain\Model\IdGenerator;
16
use Nelmio\ApiDocBundle\Annotation\Model;
17
use SimpleBus\Message\Bus\MessageBus;
18
use Swagger\Annotations as OpenApi;
19
use Symfony\Component\HttpFoundation\Request;
20
use Symfony\Component\HttpFoundation\Response;
21
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
22
use Symfony\Component\HttpKernel\Exception\LengthRequiredHttpException;
23
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
24
use Symfony\Component\Routing\Annotation\Route;
25
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
26
use Symfony\Component\Validator\ConstraintViolationListInterface;
27
use Symfony\Component\Validator\Validator\ValidatorInterface;
28
29
/**
30
 * @Route("/media")
31
 */
32
final class MediaController
33
{
34
    private $commandBus;
35
    private $urlGenerator;
36
37
    public function __construct(MessageBus $commandBus, UrlGeneratorInterface $urlGenerator)
38
    {
39
        $this->commandBus = $commandBus;
40
        $this->urlGenerator = $urlGenerator;
41
    }
42
43
    /**
44
     * @OpenApi\Post(
45
     *     tags={"media"},
46
     *     summary="Create media.",
47
     *     security={
48
     *         {"Bearer"=""}
49
     *     },
50
     *     @OpenApi\Parameter(
51
     *         name="body",
52
     *         in="body",
53
     *         required=true,
54
     *         @OpenApi\Schema(ref=@Model(type=NewMediaDto::class))
55
     *     ),
56
     *     @OpenApi\Response(
57
     *         response=202,
58
     *         description="Request accepted.",
59
     *         @OpenApi\Header(
60
     *             header="Location",
61
     *             type="string",
62
     *             description="New media resource."
63
     *         )
64
     *     )
65
     * )
66
     *
67
     * @Route("", methods={"POST"})
68
     * @Deserialize(NewMediaDto::class, validate=true, param="media")
69
     */
70
    public function create(IdGenerator $idGenerator, NewMediaDto $media): Response
71
    {
72
        // Violation of DDD?
73
        $mediaId = (string) $idGenerator->mediaId();
74
75
        $this->commandBus->handle(new CreateMedia($mediaId, $media));
76
77
        $resource = $this->urlGenerator->generate('media_view', ['id' => $mediaId]);
78
79
        return Response::create('', Response::HTTP_ACCEPTED, ['location' => $resource]);
80
    }
81
82
    /**
83
     * @OpenApi\Put(
84
     *     tags={"media"},
85
     *     summary="Upload media.",
86
     *     security={
87
     *         {"Bearer"=""}
88
     *     },
89
     *     consumes={"application/octet-stream", "application/pdf", "image/jpg", "image/png"},
90
     *     @OpenApi\Parameter(
91
     *         name="body",
92
     *         in="body",
93
     *         required=true,
94
     *         @OpenApi\Schema(type="string", format="binary")
95
     *     ),
96
     *     @OpenApi\Response(
97
     *         response=202,
98
     *         description="Request accepted.",
99
     *         @OpenApi\Header(
100
     *             header="Location",
101
     *             type="string",
102
     *             description="Media resource."
103
     *         )
104
     *     ),
105
     *     @OpenApi\Response(
106
     *         response=404,
107
     *         description="Media not found."
108
     *     ),
109
     *     @OpenApi\Response(
110
     *         response=400,
111
     *         description="Upload failure."
112
     *     )
113
     * )
114
     *
115
     * @Route("/{id}/upload", methods={"PUT"})
116
     *
117
     * @return Response|ConstraintViolationListInterface
118
     *
119
     * @throws LengthRequiredHttpException
120
     * @throws BadRequestHttpException
121
     * @throws NotFoundHttpException
122
     */
123
    public function upload(Request $request, string $id, ValidatorInterface $validator)
124
    {
125
        if (!($length = $request->headers->get('Content-Length'))) {
126
            throw new LengthRequiredHttpException();
127
        }
128
129
        $upload = new UploadDto();
130
        $upload->stream = $request->getContent(true);
131
        $upload->mimeType = $request->headers->get('Content-Type');
132
        $upload->fileSize = (int) $length;
133
134
        if (count($violations = $validator->validate($upload))) {
135
            return $violations;
136
        }
137
138
        try {
139
            $this->commandBus->handle(new UploadMedia($id, $upload));
140
        } catch (MediaNotFound $e) {
141
            throw new NotFoundHttpException();
142
        } catch (MediaUploadFailure $e) {
143
            throw new BadRequestHttpException();
144
        }
145
146
        $resource = $this->urlGenerator->generate('media_view', ['id' => $id]);
147
148
        return Response::create('', Response::HTTP_ACCEPTED, ['location' => $resource]);
149
    }
150
151
    /**
152
     * @OpenApi\Delete(
153
     *     tags={"media"},
154
     *     summary="Delete media.",
155
     *     security={
156
     *         {"Bearer"=""}
157
     *     },
158
     *     @OpenApi\Response(
159
     *         response=204,
160
     *         description="Media deleted."
161
     *     ),
162
     *     @OpenApi\Response(
163
     *         response=404,
164
     *         description="Media not found."
165
     *     )
166
     * )
167
     *
168
     * @Route("/{id}", methods={"DELETE"})
169
     *
170
     * @throws NotFoundHttpException
171
     */
172
    public function delete(string $id): Response
173
    {
174
        try {
175
            $this->commandBus->handle(new DeleteMedia($id));
176
        } catch (MediaNotFound $e) {
177
            throw new NotFoundHttpException();
178
        }
179
180
        return Response::create('', Response::HTTP_NO_CONTENT);
181
    }
182
}
183