Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
5.91% |
13 / 220 |
|
14.29% |
3 / 21 |
CRAP | |
0.00% |
0 / 1 |
ConformiteOrganisationController | |
5.91% |
13 / 220 |
|
14.29% |
3 / 21 |
3694.53 | |
0.00% |
0 / 1 |
__construct | |
90.91% |
10 / 11 |
|
0.00% |
0 / 1 |
3.01 | |||
createAction | |
0.00% |
0 / 33 |
|
0.00% |
0 / 1 |
90 | |||
showAction | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
deleteAction | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
deleteConfirmationAction | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
listConformitesAction | |
0.00% |
0 / 28 |
|
0.00% |
0 / 1 |
42 | |||
editAction | |
0.00% |
0 / 24 |
|
0.00% |
0 / 1 |
90 | |||
reportAction | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
30 | |||
addMissingNewQuestionsAndProcessus | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
20 | |||
getDomain | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getModel | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getModelClass | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getFormType | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
listDataTables | |
0.00% |
0 / 19 |
|
0.00% |
0 / 1 |
30 | |||
getLabelAndKeysArray | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
6 | |||
generateActionCell | |
0.00% |
0 / 18 |
|
0.00% |
0 / 1 |
6 | |||
getRequestCriteria | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
12 | |||
getBaseDataTablesResponse | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
2 | |||
createQueryBuilder | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
count | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
20 | |||
getManager | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | |
3 | namespace App\Domain\Registry\Controller; |
4 | |
5 | use App\Application\Controller\CRUDController; |
6 | use App\Application\Symfony\Security\UserProvider; |
7 | use App\Application\Traits\RepositoryUtils; |
8 | use App\Application\Traits\ServersideDatatablesTrait; |
9 | use App\Domain\Documentation\Model\Category; |
10 | use App\Domain\Registry\Form\Type\ConformiteOrganisation\EvaluationPiloteType; |
11 | use App\Domain\Registry\Form\Type\ConformiteOrganisation\EvaluationType; |
12 | use App\Domain\Registry\Model\ConformiteOrganisation\Conformite; |
13 | use App\Domain\Registry\Model\ConformiteOrganisation\Evaluation; |
14 | use App\Domain\Registry\Model\ConformiteOrganisation\Reponse; |
15 | use App\Domain\Registry\Repository\ConformiteOrganisation as Repository; |
16 | use App\Domain\Registry\Symfony\EventSubscriber\Event\ConformiteOrganisationEvent; |
17 | use App\Domain\Reporting\Handler\WordHandler; |
18 | use App\Domain\User\Dictionary\UserRoleDictionary; |
19 | use App\Domain\User\Model\User; |
20 | use Doctrine\Common\Collections\Collection; |
21 | use Doctrine\ORM\EntityManagerInterface; |
22 | use Doctrine\ORM\QueryBuilder; |
23 | use Doctrine\Persistence\ManagerRegistry; |
24 | use Knp\Snappy\Pdf; |
25 | use Symfony\Component\EventDispatcher\EventDispatcherInterface; |
26 | use Symfony\Component\Form\SubmitButton; |
27 | use Symfony\Component\HttpFoundation\JsonResponse; |
28 | use Symfony\Component\HttpFoundation\Request; |
29 | use Symfony\Component\HttpFoundation\Response; |
30 | use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; |
31 | use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; |
32 | use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; |
33 | use Symfony\Component\Routing\RouterInterface; |
34 | use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; |
35 | use Symfony\Contracts\Translation\TranslatorInterface; |
36 | |
37 | /** |
38 | * @property Repository\Evaluation $repository |
39 | */ |
40 | class ConformiteOrganisationController extends CRUDController |
41 | { |
42 | use ServersideDatatablesTrait; |
43 | use RepositoryUtils; |
44 | |
45 | /** |
46 | * @var Repository\Question |
47 | */ |
48 | private $questionRepository; |
49 | |
50 | /** |
51 | * @var Repository\Processus |
52 | */ |
53 | private $processusRepository; |
54 | |
55 | /** |
56 | * @var Repository\Conformite |
57 | */ |
58 | private $conformiteRepository; |
59 | |
60 | /** |
61 | * @var EventDispatcherInterface |
62 | */ |
63 | private $dispatcher; |
64 | |
65 | /** |
66 | * @var WordHandler |
67 | */ |
68 | private $wordHandler; |
69 | private ManagerRegistry $registry; |
70 | private RouterInterface $router; |
71 | |
72 | public function __construct( |
73 | EntityManagerInterface $entityManager, |
74 | TranslatorInterface $translator, |
75 | Repository\Evaluation $repository, |
76 | Repository\Question $questionRepository, |
77 | Repository\Processus $processusRepository, |
78 | Repository\Conformite $conformiteRepository, |
79 | UserProvider $userProvider, |
80 | AuthorizationCheckerInterface $authorizationChecker, |
81 | EventDispatcherInterface $dispatcher, |
82 | WordHandler $wordHandler, |
83 | Pdf $pdf, |
84 | RouterInterface $router, |
85 | ManagerRegistry $registry, |
86 | ) { |
87 | parent::__construct($entityManager, $translator, $repository, $pdf, $userProvider, $authorizationChecker); |
88 | $this->questionRepository = $questionRepository; |
89 | $this->processusRepository = $processusRepository; |
90 | $this->conformiteRepository = $conformiteRepository; |
91 | $this->dispatcher = $dispatcher; |
92 | $this->wordHandler = $wordHandler; |
93 | $this->router = $router; |
94 | $this->registry = $registry; |
95 | // Deny access to single collectivity users if conformite organisation module is disabled |
96 | // Fixes https://gitlab.adullact.net/soluris/madis/-/issues/949 |
97 | $user = $userProvider->getAuthenticatedUser(); |
98 | if ($user && !$user->hasModuleConformiteOrganisation()) { |
99 | throw new AccessDeniedHttpException('Ce module est désactivé sur votre structure'); |
100 | } |
101 | } |
102 | |
103 | public function createAction(Request $request): Response |
104 | { |
105 | $organisation = $this->userProvider->getAuthenticatedUser()->getCollectivity(); |
106 | |
107 | if ($organisation && !$organisation->isHasModuleConformiteOrganisation()) { |
108 | throw new AccessDeniedHttpException('Ce module est désactivé sur la structure'); |
109 | } |
110 | |
111 | $evaluation = $this->repository->findLastByOrganisation($organisation); |
112 | if (null !== $evaluation) { |
113 | $evaluation = clone $evaluation; |
114 | $this->addMissingNewQuestionsAndProcessus($evaluation); |
115 | } else { |
116 | $evaluation = new Evaluation(); |
117 | |
118 | foreach ($this->processusRepository->findAll(['position' => 'asc']) as $processus) { |
119 | $conformite = new Conformite(); |
120 | $conformite->setProcessus($processus); |
121 | foreach ($this->questionRepository->findAllByProcessus($processus) as $question) { |
122 | $reponse = new Reponse(); |
123 | $reponse->setConformite($conformite); |
124 | $reponse->setQuestion($question); |
125 | $conformite->addReponse($reponse); |
126 | } |
127 | $evaluation->addConformite($conformite); |
128 | } |
129 | $evaluation->setCollectivity($organisation); |
130 | } |
131 | $evaluation->setDate(new \DateTime()); |
132 | |
133 | $form = $this->createForm($this->getFormType(), $evaluation); |
134 | |
135 | $form->handleRequest($request); |
136 | if ($form->isSubmitted() && $form->isValid()) { |
137 | $em = $this->getDoctrine()->getManager(); |
138 | /** @var SubmitButton $button */ |
139 | $button = $form->get('save'); |
140 | if ($button->isClicked()) { |
141 | $evaluation->setIsDraft(false); |
142 | } |
143 | $em->persist($evaluation); |
144 | $em->flush(); |
145 | |
146 | $this->addFlash('success', $this->getFlashbagMessage('success', 'create', $evaluation)); |
147 | |
148 | return $this->redirectToRoute($this->getRouteName('list')); |
149 | } |
150 | |
151 | return $this->render($this->getTemplatingBasePath('create'), [ |
152 | 'form' => $form->createView(), |
153 | ]); |
154 | } |
155 | |
156 | public function showAction(string $id): Response |
157 | { |
158 | /** @var Conformite $object */ |
159 | $object = $this->repository->findOneById($id); |
160 | |
161 | if ($object->getCollectivity()->isHasModuleConformiteOrganisation()) { |
162 | return parent::showAction($id); |
163 | } |
164 | |
165 | return $this->redirectToRoute('registry_conformite_organisation_list'); |
166 | } |
167 | |
168 | public function deleteAction(string $id): Response |
169 | { |
170 | /** @var Conformite $object */ |
171 | $object = $this->repository->findOneById($id); |
172 | |
173 | if ($object->getCollectivity()->isHasModuleConformiteOrganisation()) { |
174 | return parent::deleteAction($id); |
175 | } |
176 | |
177 | return $this->redirectToRoute('registry_conformite_organisation_list'); |
178 | } |
179 | |
180 | public function deleteConfirmationAction(string $id): Response |
181 | { |
182 | /** @var Conformite $object */ |
183 | $object = $this->repository->findOneById($id); |
184 | |
185 | if ($object->getCollectivity()->isHasModuleConformiteOrganisation()) { |
186 | return parent::deleteConfirmationAction($id); |
187 | } |
188 | |
189 | return $this->redirectToRoute('registry_conformite_organisation_list'); |
190 | } |
191 | |
192 | public function listConformitesAction(Request $request): Response |
193 | { |
194 | $criteria = []; |
195 | $collectivity = $this->userProvider->getAuthenticatedUser()->getCollectivity(); |
196 | if (!$this->authorizationChecker->isGranted('ROLE_ADMIN')) { |
197 | $criteria['collectivity'] = $collectivity; |
198 | } |
199 | |
200 | $category = $this->entityManager->getRepository(Category::class)->findOneBy([ |
201 | 'name' => 'Conformité de la structure', |
202 | ]); |
203 | |
204 | $form = null; |
205 | $evaluations = null; |
206 | $isAdminView = $this->authorizationChecker->isGranted('ROLE_REFERENT'); |
207 | $lastEvaluation = $this->repository->findLastByOrganisation($collectivity); |
208 | |
209 | if (!$isAdminView && null !== $lastEvaluation) { |
210 | $evaluations = $this->repository->findAllByActiveOrganisationWithHasModuleConformiteOrganisationAndOrderedByDate($collectivity); |
211 | |
212 | $form = $this->createForm(EvaluationPiloteType::class, $lastEvaluation); |
213 | $form->handleRequest($request); |
214 | if ($form->isSubmitted() && $form->isValid()) { |
215 | $em = $this->getDoctrine()->getManager(); |
216 | $em->flush(); |
217 | |
218 | $this->addFlash('success', $this->getFlashbagMessage('success', 'pilote', $evaluations[0])); |
219 | |
220 | return $this->redirectToRoute($this->getRouteName('list')); |
221 | } |
222 | $form = $form->createView(); |
223 | } |
224 | |
225 | return $this->render('Registry/Conformite_organisation/list.html.twig', [ |
226 | 'totalItem' => $this->repository->count($criteria), |
227 | 'evaluations' => $evaluations, |
228 | 'category' => $category, |
229 | 'route' => $this->router->generate('registry_conformite_organisation_list_datatables'), |
230 | 'form' => $form, |
231 | ]); |
232 | } |
233 | |
234 | public function editAction(Request $request, string $id): Response |
235 | { |
236 | /** @var Evaluation $evaluation */ |
237 | $evaluation = $this->repository->findOneById($id); |
238 | if (!$evaluation) { |
239 | throw new NotFoundHttpException("No object found with ID '{$id}'"); |
240 | } |
241 | |
242 | if ($evaluation->getCollectivity() && !$evaluation->getCollectivity()->isHasModuleConformiteOrganisation()) { |
243 | throw new AccessDeniedHttpException('Ce module est désactivé sur la structure'); |
244 | } |
245 | |
246 | if (!$evaluation->isDraft()) { |
247 | throw new BadRequestHttpException("Submitted evaluation can't be modified"); |
248 | } |
249 | |
250 | /** @var User $user */ |
251 | $user = $this->getUser(); |
252 | if (!$user->hasAccessTo($evaluation)) { |
253 | return $this->redirectToRoute($this->getRouteName('list')); |
254 | } |
255 | |
256 | $this->addMissingNewQuestionsAndProcessus($evaluation); |
257 | |
258 | $form = $this->createForm($this->getFormType(), $evaluation); |
259 | |
260 | $form->handleRequest($request); |
261 | if ($form->isSubmitted() && $form->isValid()) { |
262 | /** @var SubmitButton $button */ |
263 | $button = $form->get('save'); |
264 | if ($button->isClicked()) { |
265 | $evaluation->setIsDraft(false); |
266 | } |
267 | $this->entityManager->flush(); |
268 | |
269 | $this->addFlash('success', $this->getFlashbagMessage('success', 'edit', $evaluation)); |
270 | |
271 | $this->dispatcher->dispatch(new ConformiteOrganisationEvent($evaluation)); |
272 | |
273 | return $this->redirectToRoute($this->getRouteName('list')); |
274 | } |
275 | |
276 | return $this->render($this->getTemplatingBasePath('edit'), [ |
277 | 'form' => $form->createView(), |
278 | ]); |
279 | } |
280 | |
281 | public function reportAction(Request $request, string $id) |
282 | { |
283 | $evaluation = $this->repository->findOneById($id); |
284 | if (!$evaluation) { |
285 | throw new NotFoundHttpException("No object found with ID '{$id}'"); |
286 | } |
287 | if ($evaluation->getCollectivity() && !$evaluation->getCollectivity()->isHasModuleConformiteOrganisation()) { |
288 | throw new AccessDeniedHttpException('Ce module est désactivé sur la structure'); |
289 | } |
290 | $withAllActions = $request->query->getBoolean('all_actions', true); |
291 | |
292 | /** @var User $user */ |
293 | $user = $this->getUser(); |
294 | if (!$user->hasAccessTo($evaluation)) { |
295 | return $this->redirectToRoute($this->getRouteName('list')); |
296 | } |
297 | |
298 | return $this->wordHandler->generateRegistryConformiteOrganisationReport($evaluation, $withAllActions); |
299 | } |
300 | |
301 | private function addMissingNewQuestionsAndProcessus(Evaluation $evaluation) |
302 | { |
303 | foreach ($this->processusRepository->findNewNotUsedInGivenConformite($evaluation) as $processus) { |
304 | $conformite = new Conformite(); |
305 | $conformite->setProcessus($processus); |
306 | $evaluation->addConformite($conformite); |
307 | } |
308 | |
309 | foreach ($evaluation->getConformites() as $conformite) { |
310 | foreach ($this->questionRepository->findNewNotUsedByGivenConformite($conformite) as $question) { |
311 | $reponse = new Reponse(); |
312 | $reponse->setQuestion($question); |
313 | $conformite->addReponse($reponse); |
314 | } |
315 | } |
316 | } |
317 | |
318 | protected function getDomain(): string |
319 | { |
320 | return 'registry'; |
321 | } |
322 | |
323 | protected function getModel(): string |
324 | { |
325 | return 'conformite_organisation'; |
326 | } |
327 | |
328 | protected function getModelClass(): string |
329 | { |
330 | return Evaluation::class; |
331 | } |
332 | |
333 | protected function getFormType(): string |
334 | { |
335 | return EvaluationType::class; |
336 | } |
337 | |
338 | public function listDataTables(Request $request): JsonResponse |
339 | { |
340 | $criteria = $this->getRequestCriteria(); |
341 | |
342 | $conformites = $this->getResults($request, $criteria); |
343 | $reponse = $this->getBaseDataTablesResponse($request, $conformites, $criteria); |
344 | |
345 | $yes = '<span class="badge bg-dark-gray">' . $this->translator->trans('global.label.yes') . '</span>'; |
346 | $no = '<span class="badge bg-gray">' . $this->translator->trans('global.label.no') . '</span>'; |
347 | |
348 | /* @var Evaluation $conformite */ |
349 | foreach ($conformites as $evaluation) { |
350 | if (is_array($evaluation)) { |
351 | $evaluation = $evaluation[0]; |
352 | } |
353 | $reponse['data'][] = [ |
354 | 'id' => $evaluation->getId(), |
355 | 'created_at' => $evaluation ? date_format($evaluation->getCreatedAt(), 'd/m/Y') : null, |
356 | 'collectivite' => $evaluation->getCollectivity()->getName(), |
357 | 'participant' => $evaluation->getParticipants()->count(), |
358 | 'draft' => $evaluation->isDraft() ? $yes : $no, |
359 | 'actions' => $this->generateActionCell($evaluation), |
360 | ]; |
361 | } |
362 | |
363 | $jsonResponse = new JsonResponse(); |
364 | $jsonResponse->setJson(\json_encode($reponse)); |
365 | |
366 | return $jsonResponse; |
367 | } |
368 | |
369 | protected function getLabelAndKeysArray(): array |
370 | { |
371 | if ($this->authorizationChecker->isGranted('ROLE_REFERENT')) { |
372 | return [ |
373 | 0 => 'created_at', |
374 | 1 => 'collectivite', |
375 | 2 => 'participant', |
376 | 3 => 'draft', |
377 | 4 => 'actions', |
378 | ]; |
379 | } |
380 | |
381 | return [ |
382 | 0 => 'created_at', |
383 | 1 => 'participant', |
384 | 2 => 'draft', |
385 | 3 => 'actions', |
386 | ]; |
387 | } |
388 | |
389 | private function generateActionCell(Evaluation $conformity) |
390 | { |
391 | $html = '<a href="' . |
392 | $this->router->generate('registry_conformite_organisation_report', ['id' => $conformity->getId()]) . '"> |
393 | <i aria-hidden="true" class="fa fa-print"></i> ' . |
394 | $this->translator->trans('global.action.print') |
395 | . '</a> '; |
396 | |
397 | if ($conformity->isDraft()) { |
398 | $html .= '<a href="' . |
399 | $this->router->generate('registry_conformite_organisation_edit', ['id' => $conformity->getId()]) . '"> |
400 | <i aria-hidden="true" class="fa fa-pencil"></i> ' . |
401 | $this->translator->trans('global.action.edit') |
402 | . '</a> '; |
403 | } |
404 | |
405 | $html .= '<a href="' . |
406 | $this->router->generate('registry_conformite_organisation_delete', ['id' => $conformity->getId()]) . |
407 | '"><i aria-hidden="true" class="fa fa-trash"></i> ' . |
408 | $this->translator->trans('global.action.delete') |
409 | . '</a> ' |
410 | ; |
411 | |
412 | return $html; |
413 | } |
414 | |
415 | private function getRequestCriteria() |
416 | { |
417 | $criteria = []; |
418 | $user = $this->userProvider->getAuthenticatedUser(); |
419 | |
420 | if (!$this->authorizationChecker->isGranted('ROLE_ADMIN')) { |
421 | $criteria['collectivity'] = $user->getCollectivity(); |
422 | } |
423 | |
424 | if (\in_array(UserRoleDictionary::ROLE_REFERENT, $user->getRoles())) { |
425 | $criteria['collectivity'] = $user->getCollectivitesReferees(); |
426 | } |
427 | |
428 | return $criteria; |
429 | } |
430 | |
431 | protected function getBaseDataTablesResponse(Request $request, $results, array $criteria = []) |
432 | { |
433 | $draw = $request->request->get('draw'); |
434 | |
435 | $reponse = [ |
436 | 'draw' => $draw, |
437 | 'recordsTotal' => $this->repository->count(), |
438 | 'recordsFiltered' => $this->repository->count($criteria), |
439 | 'data' => [], |
440 | ]; |
441 | |
442 | return $reponse; |
443 | } |
444 | |
445 | protected function createQueryBuilder(): QueryBuilder |
446 | { |
447 | return $this->getManager() |
448 | ->createQueryBuilder() |
449 | ->select('o') |
450 | ->from($this->getModelClass(), 'o') |
451 | ; |
452 | } |
453 | |
454 | public function count(array $criteria = []) |
455 | { |
456 | $qb = $this |
457 | ->createQueryBuilder() |
458 | ->select('count(o.id)') |
459 | ; |
460 | |
461 | if (isset($criteria['collectivity']) && $criteria['collectivity'] instanceof Collection) { |
462 | $qb->leftJoin('o.collectivity', 'collectivite'); |
463 | $this->addInClauseCollectivities($qb, $criteria['collectivity']->toArray()); |
464 | unset($criteria['collectivity']); |
465 | } |
466 | |
467 | foreach ($criteria as $key => $value) { |
468 | $this->addWhereClause($qb, $key, $value); |
469 | } |
470 | |
471 | return $qb |
472 | ->getQuery() |
473 | ->getSingleScalarResult() |
474 | ; |
475 | } |
476 | |
477 | protected function getManager(): EntityManagerInterface |
478 | { |
479 | $manager = $this->registry->getManager(); |
480 | |
481 | if (!$manager instanceof EntityManagerInterface) { |
482 | throw new \Exception('Registry Manager must be an instance of EntityManagerInterface'); |
483 | } |
484 | |
485 | return $manager; |
486 | } |
487 | } |