ProjectApiController::postProjectAction()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 9
nc 2
nop 2
dl 0
loc 15
rs 9.9666
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Copyright (c) 2017 Francois-Xavier Soubirou.
5
 *
6
 * This file is part of ci-report.
7
 *
8
 * ci-report is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * ci-report is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with ci-report. If not, see <http://www.gnu.org/licenses/>.
20
 */
21
declare(strict_types=1);
22
23
namespace App\Controller;
24
25
use App\DTO\ProjectDTO;
26
use App\Entity\Project;
27
use App\Service\ProjectService;
28
use FOS\RestBundle\Controller\Annotations as Rest;
29
use FOS\RestBundle\View\View;
30
use Nelmio\ApiDocBundle\Annotation\Operation;
31
use Nelmio\ApiDocBundle\Annotation\Model;
32
use Swagger\Annotations as SWG;
33
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
34
use Symfony\Component\HttpFoundation\Request;
35
use Symfony\Component\HttpFoundation\Response;
36
use Symfony\Component\Validator\ConstraintViolationList;
37
38
/**
39
 * Project API controller class.
40
 *
41
 * @category  ci-report app
42
 *
43
 * @author    Francois-Xavier Soubirou <[email protected]>
44
 * @copyright 2017 Francois-Xavier Soubirou
45
 * @license   http://www.gnu.org/licenses/   GPLv3
46
 *
47
 * @see      https://www.ci-report.io
48
 *
49
 * @Rest\Route("/api")
50
 */
51
class ProjectApiController extends AbstractApiController
52
{
53
    /**
54
     * Get list of projects.
55
     *
56
     * @return array
57
     *
58
     * @Rest\Get("/projects")
59
     * @Rest\View(serializerGroups={"public"})
60
     *
61
     * @Operation(
62
     *     tags={"Projects"},
63
     *     summary="Get the list of all projects.",
64
     *     description="Example: </br><pre><code>curl https://www.ci-report.io/api/projects -X GET</code></pre>",
65
     *     @SWG\Response(
66
     *         response="200",
67
     *         description="Returned when successful array of public data of projects",
68
     *         @SWG\Schema(
69
     *            type="array",
70
     *            @Model(type=Project::class, groups={"public"})
71
     *         )
72
     *     ),
73
     *     @SWG\Response(
74
     *         response="default",
75
     *         description="Unexpected error",
76
     *         @SWG\Schema(ref="#/definitions/ErrorModel")
77
     *     )
78
     * )
79
     */
80
    public function getProjectsAction(): array
81
    {
82
        $projects = $this->getDoctrine()
83
            ->getRepository(Project::class)
84
            ->findAll();
85
86
        return $projects;
87
    }
88
89
    /**
90
     * Get public project data.
91
     *
92
     * @param Project $project Project
93
     *
94
     * @return Project
95
     *
96
     * @Rest\Get("/projects/{prefid}")
97
     * @Rest\View(serializerGroups={"public"})
98
     *
99
     * @ParamConverter("project", options={"mapping": {"prefid": "refid"}})
100
     *
101
     * @Operation(
102
     *     tags={"Projects"},
103
     *     summary="Get public project data.",
104
     *     description="Example: </br><pre><code>curl https://www.ci-report.io/api/projects/project-one -X GET</code></pre>",
105
     *     @SWG\Parameter(
106
     *         name="prefid",
107
     *         in="path",
108
     *         description="Unique short name of project defined on project creation.",
109
     *         type="string"
110
     *     ),
111
     *     @SWG\Response(
112
     *         response="200",
113
     *         description="Returned when successful",
114
     *         @Model(type=Project::class, groups={"public"})
115
     *     ),
116
     *     @SWG\Response(
117
     *         response="404",
118
     *         description="Returned when project not found",
119
     *         @SWG\Schema(ref="#/definitions/ErrorModel")
120
     *     )
121
     * )
122
     */
123
    public function getProjectAction(Project $project): Project
124
    {
125
        return $project;
126
    }
127
128
    /**
129
     * Get private project data.
130
     *
131
     * @param Project $project Project
132
     * @param Request $request The request
133
     *
134
     * @return Project|View
135
     *
136
     * @Rest\Get("/projects/{prefid}/private")
137
     * @Rest\View(serializerGroups={"private"})
138
     *
139
     * @ParamConverter("project", options={"mapping": {"prefid": "refid"}})
140
     *
141
     * @Operation(
142
     *     tags={"Projects"},
143
     *     summary="Get private project data.",
144
     *     description="Example: </br><pre><code>curl https://www.ci-report.io/api/projects/project-one/private -H &quot;X-CIR-TKN: 1f4ffb19e4b9-02278af07b7d-4e370a76f001&quot; -X GET</code></pre>",
145
     *     @SWG\Parameter(
146
     *         name="X-CIR-TKN",
147
     *         in="header",
148
     *         required=true,
149
     *         description="Private token",
150
     *         type="string"
151
     *     ),
152
     *     @SWG\Parameter(
153
     *         name="prefid",
154
     *         in="path",
155
     *         description="Unique short name of project defined on project creation.",
156
     *         type="string"
157
     *     ),
158
     *     @SWG\Response(
159
     *         response="200",
160
     *         description="Returned when successful",
161
     *         @Model(type=Project::class, groups={"private"})
162
     *     ),
163
     *     @SWG\Response(
164
     *         response="401",
165
     *         description="Returned when X-CIR-TKN private token value is invalid",
166
     *         @SWG\Schema(ref="#/definitions/ErrorModel")
167
     *     ),
168
     *     @SWG\Response(
169
     *         response="404",
170
     *         description="Returned when project not found",
171
     *         @SWG\Schema(ref="#/definitions/ErrorModel")
172
     *     )
173
     * )
174
     */
175
    public function getProjectPrivateAction(Project $project, Request $request)
176
    {
177
        if ($this->isInvalidToken($request, $project->getToken())) {
178
            return $this->getInvalidTokenView();
179
        }
180
181
        return $project;
182
    }
183
184
    /**
185
     * Create a project. Private token is sent by email.
186
     *
187
     * @param Project                 $project    Project to create
188
     * @param ConstraintViolationList $violations List of violations
189
     *
190
     * @return Project|View
191
     *
192
     * @Rest\Post("/projects")
193
     * @Rest\View(statusCode=Response::HTTP_CREATED, serializerGroups={"private"})
194
     *
195
     * @ParamConverter("project", converter="fos_rest.request_body", options={ "validator"={"groups"={"input", "unique"}} } )
196
     *
197
     * @Operation(
198
     *     tags={"Projects"},
199
     *     summary="Create a project. Private data are sent by mail.",
200
     *     description="Example: </br><pre><code>curl https://www.ci-report.io/api/projects -H &quot;Content-Type: application/json&quot; -X POST --data '{&quot;name&quot;:&quot;Project To Add&quot;, &quot;warning&quot;:80, &quot;success&quot;:95, &quot;email&quot;:&quot;[email protected]&quot;}'</code></pre>",
201
     *     @SWG\Parameter(
202
     *         name="data",
203
     *         in="body",
204
     *         required=true,
205
     *         @SWG\Schema(ref="#/definitions/ProjectDataModel")
206
     *     ),
207
     *     @SWG\Response(
208
     *         response="201",
209
     *         description="Returned when created",
210
     *         @Model(type=Project::class, groups={"private"})
211
     *     ),
212
     *     @SWG\Response(
213
     *         response="400",
214
     *         description="Returned when a violation is raised by validation",
215
     *         @SWG\Schema(
216
     *            type="array",
217
     *            @SWG\Items(ref="#/definitions/ErrorModel")
218
     *         )
219
     *     )
220
     * )
221
     */
222
    public function postProjectAction(Project $project, ConstraintViolationList $violations)
223
    {
224
        if (count($violations) > 0) {
225
            return $this->view($violations, Response::HTTP_BAD_REQUEST);
226
        }
227
        $projectService = $this->get(ProjectService::class);
228
        $projectService->setSlugAndToken($project);
229
230
        $em = $this->getDoctrine()->getManager();
231
        $em->persist($project);
232
        $em->flush();
233
234
        $projectService->sendRegistrationEmail($project);
235
236
        return $project;
237
    }
238
239
    /**
240
     * Update a project.
241
     *
242
     * @param Project $projectDB  Project to update
243
     * @param Project $projectDTO Project containing values to update
244
     * @param Request $request    The request
245
     *
246
     * @return Project|View
247
     *
248
     * @Rest\Put("/projects/{prefid}")
249
     * @Rest\View(serializerGroups={"private"})
250
     *
251
     * @ParamConverter("projectDB", options={"mapping": {"prefid": "refid"}})
252
     * @ParamConverter("projectDTO", converter="fos_rest.request_body")
253
     *
254
     * @Operation(
255
     *     tags={"Projects"},
256
     *     summary="Update a project.",
257
     *     description="Example: </br><pre><code>curl https://www.ci-report.io/api/projects/project-one -H &quot;Content-Type: application/json&quot; -H &quot;X-CIR-TKN: 1f4ffb19e4b9-02278af07b7d-4e370a76f001&quot; -X PUT --data '{&quot;name&quot;:&quot;Project To Update&quot;, &quot;warning&quot;:85, &quot;success&quot;:90, &quot;email&quot;:&quot;[email protected]&quot;}'</code></pre>",
258
     *     @SWG\Parameter(
259
     *         name="X-CIR-TKN",
260
     *         in="header",
261
     *         required=true,
262
     *         description="Private token",
263
     *         type="string"
264
     *     ),
265
     *     @SWG\Parameter(
266
     *         name="prefid",
267
     *         in="path",
268
     *         description="Unique short name of project defined on project creation.",
269
     *         type="string"
270
     *     ),
271
     *     @SWG\Parameter(
272
     *         name="data",
273
     *         in="body",
274
     *         required=true,
275
     *         @SWG\Schema(ref="#/definitions/ProjectDataModel")
276
     *     ),
277
     *     @SWG\Response(
278
     *         response="200",
279
     *         description="Returned when successful",
280
     *         @Model(type=Project::class, groups={"private"})
281
     *     ),
282
     *     @SWG\Response(
283
     *         response="400",
284
     *         description="Returned when a violation is raised by validation",
285
     *         @SWG\Schema(
286
     *            type="array",
287
     *            @SWG\Items(ref="#/definitions/ErrorModel")
288
     *         )
289
     *     ),
290
     *     @SWG\Response(
291
     *         response="401",
292
     *         description="Returned when X-CIR-TKN private token value is invalid",
293
     *         @SWG\Schema(ref="#/definitions/ErrorModel")
294
     *     ),
295
     *     @SWG\Response(
296
     *         response="404",
297
     *         description="Returned when project not found",
298
     *         @SWG\Schema(ref="#/definitions/ErrorModel")
299
     *     )
300
     * )
301
     */
302
    public function putProjectAction(Project $projectDB, ProjectDTO $projectDTO, Request $request)
303
    {
304
        if ($this->isInvalidToken($request, $projectDB->getToken())) {
305
            return $this->getInvalidTokenView();
306
        }
307
308
        $validator = $this->get('validator');
309
        $violationsDTO = $validator->validate($projectDTO);
310
311
        if (count($violationsDTO) > 0) {
312
            return $this->view($violationsDTO, Response::HTTP_BAD_REQUEST);
313
        }
314
        $projectDB->setFromDTO($projectDTO);
315
316
        // Check for unique name.
317
        $violationsDB = $validator->validate($projectDB, null, array('input', 'unique'));
318
        if (count($violationsDB) > 0) {
319
            return $this->view($violationsDB, Response::HTTP_BAD_REQUEST);
320
        }
321
        $this->getDoctrine()->getManager()->flush();
322
323
        return $projectDB;
324
    }
325
326
    /**
327
     * Delete a project.
328
     *
329
     * @param Project $project Project
330
     * @param Request $request The request
331
     *
332
     * @return void|View
333
     *
334
     * @Rest\Delete("/projects/{prefid}")
335
     * @Rest\View(statusCode=Response::HTTP_NO_CONTENT)
336
     *
337
     * @ParamConverter("project", options={"mapping": {"prefid": "refid"}})
338
     *
339
     * @Operation(
340
     *     tags={"Projects"},
341
     *     summary="Delete a project.",
342
     *     description="Example: </br><pre><code>curl https://www.ci-report.io/api/projects/project-one -H &quot;X-CIR-TKN: 1f4ffb19e4b9-02278af07b7d-4e370a76f001&quot; -X DELETE</code></pre>",
343
     *     @SWG\Parameter(
344
     *         name="X-CIR-TKN",
345
     *         in="header",
346
     *         required=true,
347
     *         description="Private token",
348
     *         type="string"
349
     *     ),
350
     *     @SWG\Parameter(
351
     *         name="prefid",
352
     *         in="path",
353
     *         description="Unique short name of project defined on project creation.",
354
     *         type="string"
355
     *     ),
356
     *     @SWG\Response(
357
     *         response="204",
358
     *         description="Returned when successful"
359
     *     ),
360
     *     @SWG\Response(
361
     *         response="401",
362
     *         description="Returned when X-CIR-TKN private token value is invalid",
363
     *         @SWG\Schema(ref="#/definitions/ErrorModel")
364
     *     ),
365
     *     @SWG\Response(
366
     *         response="404",
367
     *         description="Returned when project not found",
368
     *         @SWG\Schema(ref="#/definitions/ErrorModel")
369
     *     )
370
     * )
371
     */
372
    public function deleteProjectAction(Project $project, Request $request)
373
    {
374
        if ($this->isInvalidToken($request, $project->getToken())) {
375
            return $this->getInvalidTokenView();
376
        }
377
        $em = $this->getDoctrine()->getManager();
378
        $em->remove($project);
379
        $em->flush();
380
    }
381
}
382