Passed
Branch master (9d818b)
by FX
07:15 queued 02:51
created

ProjectApiController::postProjectsAction()   A

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.4285
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 AppBundle\Controller;
24
25
use AppBundle\Entity\Project;
26
use AppBundle\Service\ProjectService;
27
use FOS\RestBundle\Controller\Annotations as Rest;
28
use FOS\RestBundle\Controller\FOSRestController;
29
use FOS\RestBundle\View\View;
30
use Nelmio\ApiDocBundle\Annotation as Doc;
31
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
32
use Symfony\Component\HttpFoundation\Request;
33
use Symfony\Component\HttpFoundation\Response;
34
use Symfony\Component\Validator\ConstraintViolationList;
35
36
/**
37
 * Project controller class.
38
 *
39
 * @category  ci-report app
40
 *
41
 * @author    Francois-Xavier Soubirou <[email protected]>
42
 * @copyright 2017 Francois-Xavier Soubirou
43
 * @license   http://www.gnu.org/licenses/   GPLv3
44
 *
45
 * @see      https://ci-report.io
46
 *
47
 * @Rest\Route("/api")
48
 */
49
class ProjectApiController extends FOSRestController
50
{
51
    /**
52
     * Get list of projects.
53
     *
54
     * @return array
55
     *
56
     * @Rest\Get("/projects")
57
     * @Rest\View(serializerGroups={"public"})
58
     *
59
     * @Doc\ApiDoc(
60
     *     section="Projects",
61
     *     description="Get the list of all projects.",
62
     *     output={
63
     *         "class"=Project::class,
64
     *         "groups"={"public"},
65
     *         "parsers"={"Nelmio\ApiDocBundle\Parser\JmsMetadataParser"}
66
     *     },
67
     *     statusCodes={
68
     *         200="Returned when successful array of public data of projects"
69
     *     }
70
     * )
71
     */
72
    public function getProjectsAction(): array
73
    {
74
        $projects = $this->getDoctrine()
75
            ->getRepository(Project::class)
76
            ->findAll();
77
78
        return $projects;
79
    }
80
81
    /**
82
     * Get public project data.
83
     *
84
     * @param Project $project Project to create
85
     *
86
     * @return Project
87
     *
88
     * @Rest\Get("/projects/{ref_id}")
89
     * @Rest\View(serializerGroups={"public"})
90
     *
91
     * @ParamConverter("project", options={"mapping": {"ref_id": "refId"}})
92
     *
93
     * @Doc\ApiDoc(
94
     *     section="Projects",
95
     *     description="Get public project data.",
96
     *     requirements={
97
     *         {
98
     *             "name"="ref_id",
99
     *             "dataType"="string",
100
     *             "requirement"="string",
101
     *             "description"="Unique short name of project defined on project creation."
102
     *         }
103
     *     },
104
     *     output= {
105
     *         "class"=Project::class,
106
     *         "groups"={"public"},
107
     *         "parsers"={"Nelmio\ApiDocBundle\Parser\JmsMetadataParser"}
108
     *     },
109
     *     statusCodes={
110
     *         200="Returned when successful",
111
     *         404="Returned when project not found"
112
     *     }
113
     * )
114
     */
115
    public function getProjectAction(Project $project): Project
116
    {
117
        return $project;
118
    }
119
120
    /**
121
     * Create a project. Private token is sent by email.
122
     *
123
     * @param Project                 $project    Project to create
124
     * @param ConstraintViolationList $violations List of violations
125
     *
126
     * @return Project|View
127
     *
128
     * @Rest\Post("/projects")
129
     * @Rest\View(statusCode=Response::HTTP_CREATED, serializerGroups={"private"})
130
     *
131
     * @ParamConverter("project", converter="fos_rest.request_body", options={ "validator"={"groups"={"input", "unique"}} } )
132
     *
133
     * @Doc\ApiDoc(
134
     *     section="Projects",
135
     *     description="Create a project. Private data are sent by mail.",
136
     *     input= { "class"=Project::class, "groups"={"input"} },
137
     *     output= {
138
     *         "class"=Project::class,
139
     *         "groups"={"private"},
140
     *         "parsers"={"Nelmio\ApiDocBundle\Parser\JmsMetadataParser"}
141
     *     },
142
     *     statusCodes={
143
     *         201="Returned when created",
144
     *         400="Returned when a violation is raised by validation"
145
     *     }
146
     * )
147
     */
148
    public function postProjectsAction(Project $project, ConstraintViolationList $violations)
149
    {
150
        if (count($violations) > 0) {
151
            return $this->view($violations, Response::HTTP_BAD_REQUEST);
152
        }
153
        $projectService = $this->get(ProjectService::class);
154
        $projectService->setSlugAndToken($project);
155
156
        $em = $this->getDoctrine()->getManager();
157
        $em->persist($project);
158
        $em->flush();
159
160
        $projectService->sendRegistrationEmail($project);
161
162
        return $project;
163
    }
164
165
    /**
166
     * Update a project.
167
     *
168
     * @param Project $projectDB Project to update
169
     * @param Project $projectIn Project containing values to update
170
     * @param Request $request   The request
171
     *
172
     * @return Project|View
173
     *
174
     * @Rest\Put("/projects/{ref_id}")
175
     * @Rest\View(serializerGroups={"private"})
176
     *
177
     * @ParamConverter("projectDB", options={"mapping": {"ref_id": "refId"}})
178
     * @ParamConverter("projectIn", converter="fos_rest.request_body")
179
     *
180
     * @Doc\ApiDoc(
181
     *     section="Projects",
182
     *     description="Update a project.",
183
     *     headers={
184
     *         {
185
     *             "name"="X-CIR-TKN",
186
     *             "required"=true,
187
     *             "description"="Private token"
188
     *         }
189
     *     },
190
     *     requirements={
191
     *         {
192
     *             "name"="ref_id",
193
     *             "dataType"="string",
194
     *             "requirement"="string",
195
     *             "description"="Unique short name of project defined on project creation."
196
     *         }
197
     *     },
198
     *     input= { "class"=Project::class, "groups"={"input"} },
199
     *     output= {
200
     *         "class"=Project::class,
201
     *         "groups"={"private"},
202
     *         "parsers"={"Nelmio\ApiDocBundle\Parser\JmsMetadataParser"}
203
     *     },
204
     *     statusCodes={
205
     *         200="Returned when successful",
206
     *         400="Returned when a violation is raised by validation",
207
     *         401="Returned when X-CIR-TKN private token value is invalid"
208
     *     },
209
     *     tags={
210
     *         "token" = "#87ceeb"
211
     *     }
212
     * )
213
     */
214
    public function putProjectsAction(Project $projectDB, Project $projectIn, Request $request)
215
    {
216
        $token = $request->headers->get('X-CIR-TKN');
217
218
        if ((null === $token) || ($projectDB->getToken() !== $token)) {
219
            return $this->view(
220
                array(
221
                    'code' => Response::HTTP_UNAUTHORIZED,
222
                    'message' => 'Invalid token',
223
                ),
224
                Response::HTTP_UNAUTHORIZED
225
            );
226
        }
227
        $validator = $this->get('validator');
228
        $violationsUpdate = $validator->validate($projectIn, null, array('input'));
229
230
        if (count($violationsUpdate) > 0) {
231
            return $this->view($violationsUpdate, Response::HTTP_BAD_REQUEST);
232
        }
233
        $projectDB->setName($projectIn->getName())
234
            ->setEmail($projectIn->getEmail())
235
            ->setWarningLimit($projectIn->getWarningLimit())
236
            ->setSuccessLimit($projectIn->getSuccessLimit());
237
238
        // Check for unique name.
239
        $errors = $validator->validate($projectDB, null, array('input', 'unique'));
240
        if (count($errors) > 0) {
241
            return $this->view($errors, Response::HTTP_BAD_REQUEST);
242
        }
243
        $this->getDoctrine()->getManager()->flush();
244
245
        return $projectDB;
246
    }
247
}
248