Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
9.95% covered (danger)
9.95%
37 / 372
23.08% covered (danger)
23.08%
6 / 26
CRAP
0.00% covered (danger)
0.00%
0 / 1
ConformiteTraitementController
9.95% covered (danger)
9.95%
37 / 372
23.08% covered (danger)
23.08%
6 / 26
9605.07
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
3
 getDomain
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getModel
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getModelClass
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 reportAction
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 getFormType
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getListData
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
3.03
 listAction
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
1
 createAction
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 1
110
 editAction
0.00% covered (danger)
0.00%
0 / 31
0.00% covered (danger)
0.00%
0 / 1
156
 startAipdAction
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 1
132
 setAnalyseReponsesQuestionConformite
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 listDataTables
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 1
110
 getPlanifiedMesurements
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
 getIcon
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
56
 getLabelAndKeysArray
0.00% covered (danger)
0.00%
0 / 38
0.00% covered (danger)
0.00%
0 / 1
12
 getRequestCriteria
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
12
 getTreatmentLink
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getAvisAipd
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 1
72
 getQuestionConformity
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
56
 getTreatmentConformity
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
30
 generateActionCellContent
0.00% covered (danger)
0.00%
0 / 38
0.00% covered (danger)
0.00%
0 / 1
132
 returnHtmlAction
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 isTreatmentInUserServices
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 getResults
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
12
 getBaseDataTablesResponse
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3/**
4 * This file is part of the MADIS - RGPD Management application.
5 *
6 * @copyright Copyright (c) 2018-2019 Soluris - Solutions Numériques Territoriales Innovantes
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Affero 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 * This program 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 Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22declare(strict_types=1);
23
24namespace App\Domain\Registry\Controller;
25
26use App\Application\Controller\CRUDController;
27use App\Application\Symfony\Security\UserProvider;
28use App\Application\Traits\ServersideDatatablesTrait;
29use App\Domain\AIPD\Converter\ModeleToAnalyseConverter;
30use App\Domain\AIPD\Model\AnalyseImpact;
31use App\Domain\AIPD\Repository as AipdRepository;
32use App\Domain\Documentation\Model\Category;
33use App\Domain\Registry\Calculator\Completion\ConformiteTraitementCompletion;
34use App\Domain\Registry\Dictionary\ConformiteTraitementLevelDictionary;
35use App\Domain\Registry\Form\Type\ConformiteTraitement\ConformiteTraitementType;
36use App\Domain\Registry\Model;
37use App\Domain\Registry\Model\ConformiteTraitement\ConformiteTraitement;
38use App\Domain\Registry\Model\Treatment;
39use App\Domain\Registry\Repository;
40use App\Domain\Registry\Symfony\EventSubscriber\Event\ConformiteTraitementEvent;
41use App\Domain\Reporting\Handler\WordHandler;
42use App\Domain\User\Dictionary\UserRoleDictionary;
43use App\Domain\User\Model\User;
44use App\Domain\User\Repository as UserRepository;
45use Doctrine\ORM\EntityManagerInterface;
46use Doctrine\ORM\Tools\Pagination\Paginator;
47use Knp\Snappy\Pdf;
48use Symfony\Component\EventDispatcher\EventDispatcherInterface;
49use Symfony\Component\HttpFoundation\JsonResponse;
50use Symfony\Component\HttpFoundation\Request;
51use Symfony\Component\HttpFoundation\Response;
52use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
53use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
54use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
55use Symfony\Component\Routing\RouterInterface;
56use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
57use Symfony\Contracts\Translation\TranslatorInterface;
58
59/**
60 * @property Repository\ConformiteTraitement\ConformiteTraitement $repository
61 */
62class ConformiteTraitementController extends CRUDController
63{
64    use ServersideDatatablesTrait;
65
66    /**
67     * @var UserRepository\Collectivity
68     */
69    protected $collectivityRepository;
70
71    /**
72     * @var Repository\Treatment
73     */
74    protected $treatmentRepository;
75
76    /**
77     * @var WordHandler
78     */
79    protected $wordHandler;
80
81    /**
82     * @var AuthorizationCheckerInterface
83     */
84    protected $authorizationChecker;
85
86    /**
87     * @var UserProvider
88     */
89    protected $userProvider;
90
91    /**
92     * @var Repository\ConformiteTraitement\Question
93     */
94    protected $questionRepository;
95
96    /**
97     * @var EventDispatcherInterface
98     */
99    protected $dispatcher;
100
101    private AipdRepository\ModeleAnalyse $modeleRepository;
102
103    private RouterInterface $router;
104
105    public function __construct(
106        EntityManagerInterface $entityManager,
107        TranslatorInterface $translator,
108        Repository\ConformiteTraitement\ConformiteTraitement $repository,
109        UserRepository\Collectivity $collectivityRepository,
110        WordHandler $wordHandler,
111        AuthorizationCheckerInterface $authorizationChecker,
112        UserProvider $userProvider,
113        Repository\Treatment $treatmentRepository,
114        Repository\ConformiteTraitement\Question $questionRepository,
115        EventDispatcherInterface $dispatcher,
116        Pdf $pdf,
117        AipdRepository\ModeleAnalyse $modeleRepository,
118        RouterInterface $router,
119    ) {
120        parent::__construct($entityManager, $translator, $repository, $pdf, $userProvider, $authorizationChecker);
121        $this->collectivityRepository = $collectivityRepository;
122        $this->wordHandler            = $wordHandler;
123        $this->authorizationChecker   = $authorizationChecker;
124        $this->userProvider           = $userProvider;
125        $this->treatmentRepository    = $treatmentRepository;
126        $this->questionRepository     = $questionRepository;
127        $this->dispatcher             = $dispatcher;
128        $this->modeleRepository       = $modeleRepository;
129        $this->router                 = $router;
130        $this->repository             = $repository;
131
132        // Deny access to single collectivity users if conformite traitement module is disabled
133        // Fixes https://gitlab.adullact.net/soluris/madis/-/issues/949
134        $user = $userProvider->getAuthenticatedUser();
135        if ($user && !$user->hasModuleConformiteTraitement()) {
136            throw new AccessDeniedHttpException('Ce module est désactivé sur votre structure');
137        }
138    }
139
140    protected function getDomain(): string
141    {
142        return 'registry';
143    }
144
145    protected function getModel(): string
146    {
147        return 'conformite_traitement';
148    }
149
150    protected function getModelClass(): string
151    {
152        return ConformiteTraitement::class;
153    }
154
155    public function reportAction()
156    {
157        $collectivity = $this->userProvider->getAuthenticatedUser()->getCollectivity();
158
159        if (!$collectivity->isHasModuleConformiteTraitement()) {
160            return $this->redirectToRoute('registry_conformite_organisation_list');
161        }
162        $objects = $this->treatmentRepository->findAllByCollectivity(
163            $collectivity
164        );
165
166        return $this->wordHandler->generateRegistryConformiteTraitementReport($objects);
167    }
168
169    protected function getFormType(): string
170    {
171        return ConformiteTraitementType::class;
172    }
173
174    protected function getListData()
175    {
176        $collectivity = null;
177        $user         = $this->userProvider->getAuthenticatedUser();
178
179        if (!$this->authorizationChecker->isGranted('ROLE_ADMIN')) {
180            $collectivity = $user->getCollectivity();
181        }
182
183        if (\in_array(UserRoleDictionary::ROLE_REFERENT, $user->getRoles())) {
184            $collectivity = \iterable_to_array($user->getCollectivitesReferees());
185        }
186
187        return $this->treatmentRepository->findAllActiveByCollectivityWithHasModuleConformiteTraitement($collectivity);
188    }
189
190    public function listAction(): Response
191    {
192        $user          = $this->userProvider->getAuthenticatedUser();
193        $services_user = $user->getServices();
194        $criteria      = [];
195
196        $category = $this->entityManager->getRepository(Category::class)->findOneBy([
197            'name' => 'Conformité des traitements',
198        ]);
199
200        return $this->render('Registry/Conformite_traitement/list.html.twig', [
201            'objects'       => $this->getListData(),
202            'totalItem'     => $this->repository->count($criteria),
203            'category'      => $category,
204            'services_user' => $services_user,
205            'route'         => $this->router->generate('registry_conformite_traitement_list_datatables'),
206        ]);
207    }
208
209    /**
210     * {@inheritdoc}
211     * Override method in order to hydrate questions.
212     */
213    public function createAction(Request $request): Response
214    {
215        /**
216         * @var ConformiteTraitement
217         */
218        $object = new ConformiteTraitement();
219
220        /** @var User $user */
221        $user = $this->getUser();
222
223        /** @var Treatment $traitement */
224        $traitement = $this->treatmentRepository->findOneById($request->get('idTraitement'));
225        if ($traitement->getCollectivity() && !$traitement->getCollectivity()->isHasModuleConformiteTraitement()) {
226            throw new AccessDeniedHttpException('La structure de ce traitement a le module conformité des traitements désactivé');
227        }
228        $object->setTraitement($traitement);
229
230        if (!$user->hasAccessTo($traitement)) {
231            return $this->redirectToRoute($this->getRouteName('list'));
232        }
233
234        $service       = $object->getTraitement()->getService();
235        $user          = $this->userProvider->getAuthenticatedUser();
236        $services_user = $user->getServices();
237
238        if (!($this->authorizationChecker->isGranted('ROLE_USER') && ($services_user->isEmpty() || $services_user->contains($service)))) {
239            return $this->redirectToRoute('registry_treatment_list');
240        }
241
242        // Before create form, hydrate answers array with potential question responses
243        foreach ($this->questionRepository->findAll(['position' => 'ASC']) as $question) {
244            $reponse = new Model\ConformiteTraitement\Reponse();
245            $reponse->setQuestion($question);
246            $object->addReponse($reponse);
247        }
248
249        $form = $this->createForm($this->getFormType(), $object);
250
251        $form->handleRequest($request);
252        if ($form->isSubmitted() && $form->isValid()) {
253            $em = $this->getDoctrine()->getManager();
254            $em->persist($object);
255            $em->flush();
256
257            $this->addFlash('success', $this->getFlashbagMessage('success', 'create', $object));
258
259            return $this->redirectToRoute($this->getRouteName('list'));
260        }
261
262        $serviceEnabled = $object->getTraitement()->getCollectivity()->getIsServicesEnabled();
263
264        return $this->render($this->getTemplatingBasePath('create'), [
265            'form'           => $form->createView(),
266            'serviceEnabled' => $serviceEnabled,
267        ]);
268    }
269
270    /**
271     * {@inheritdoc}
272     * Override method in order to hydrate new questions.
273     *
274     * @param string $id The ID of the data to edit
275     */
276    public function editAction(Request $request, string $id): Response
277    {
278        /** @var ConformiteTraitement $object */
279        $object = $this->repository->findOneById($id);
280        if (!$object) {
281            throw new NotFoundHttpException("No object found with ID '{$id}'");
282        }
283
284        if (!$object->getTraitement() || !$object->getTraitement()->getCollectivity() || !$object->getTraitement()->getCollectivity()->isHasModuleConformiteTraitement()) {
285            throw new NotFoundHttpException("No object found with ID '{$id}'");
286        }
287
288        /** @var User $user */
289        $user = $this->getUser();
290        if (!$user->hasAccessTo($object->getTraitement())) {
291            return $this->redirectToRoute($this->getRouteName('list'));
292        }
293
294        $service       = $object->getTraitement()->getService();
295        $user          = $this->userProvider->getAuthenticatedUser();
296        $services_user = $user->getServices();
297
298        if (!($this->authorizationChecker->isGranted('ROLE_USER') && ($services_user->isEmpty() || $services_user->contains($service)))) {
299            return $this->redirectToRoute('registry_treatment_list');
300        }
301
302        // Before create form, hydrate new answers array with potential question responses
303        foreach ($this->questionRepository->findNewQuestionsNotUseInGivenConformite($object) as $question) {
304            $reponse = new Model\ConformiteTraitement\Reponse();
305            $reponse->setQuestion($question);
306            $object->addReponse($reponse);
307        }
308
309        $form = $this->createForm($this->getFormType(), $object, ['validation_groups' => ['default', $this->getModel(), 'edit']]);
310
311        $form->handleRequest($request);
312        if ($form->isSubmitted() && $form->isValid()) {
313            $this->formPrePersistData($object);
314            $this->entityManager->persist($object);
315            $this->entityManager->flush();
316
317            $this->dispatcher->dispatch(new ConformiteTraitementEvent($object));
318
319            $this->addFlash('success', $this->getFlashbagMessage('success', 'edit', $object));
320
321            return $this->redirectToRoute($this->getRouteName('list'));
322        }
323
324        $serviceEnabled = $object->getTraitement()->getCollectivity()->getIsServicesEnabled();
325
326        return $this->render($this->getTemplatingBasePath('edit'), [
327            'form'           => $form->createView(),
328            'serviceEnabled' => $serviceEnabled,
329        ]);
330    }
331
332    public function startAipdAction(Request $request, string $id)
333    {
334        /** @var ConformiteTraitement $conformiteTraitement */
335        $conformiteTraitement = $this->repository->findOneById($id);
336        if (!$conformiteTraitement) {
337            throw new NotFoundHttpException("No object found with ID '{$id}'");
338        }
339
340        /** @var User $user */
341        $user       = $this->getUser();
342        $traitement = $conformiteTraitement->getTraitement();
343        if ($traitement->getCollectivity() && !$traitement->getCollectivity()->isHasModuleConformiteTraitement()) {
344            throw new AccessDeniedHttpException('La structure de ce traitement a le module conformité des traitements désactivé');
345        }
346        if (!$user->hasAccessTo($traitement)) {
347            return $this->redirectToRoute($this->getRouteName('list'));
348        }
349
350        if ($request->isMethod('GET')) {
351            return $this->render($this->getTemplatingBasePath('start'), [
352                'totalItem'            => $this->modeleRepository->count(),
353                'route'                => $this->router->generate('aipd_analyse_impact_modele_datatables', ['collectivity' => $conformiteTraitement->getTraitement()->getCollectivity()->getId()->toString()]),
354                'conformiteTraitement' => $conformiteTraitement,
355            ]);
356        }
357
358        if (!$request->request->has('modele_choice')) {
359            throw new BadRequestHttpException('Parameter modele_choice must be present');
360        }
361
362        if (null === $modele = $this->modeleRepository->findOneById($request->request->get('modele_choice'))) {
363            throw new NotFoundHttpException('No modele with Id ' . $request->request->get('modele_choice') . ' exists.');
364        }
365
366        $analyseImpact = ModeleToAnalyseConverter::createFromModeleAnalyse($modele);
367        $analyseImpact->setCreatedAt(new \DateTimeImmutable());
368        $analyseImpact->setConformiteTraitement($conformiteTraitement);
369
370        $this->setAnalyseReponsesQuestionConformite($analyseImpact, $conformiteTraitement);
371
372        foreach ($analyseImpact->getScenarioMenaces() as $scenarioMenace) {
373            if (null !== $scenarioMenace->getMesuresProtections()) {
374                foreach ($scenarioMenace->getMesuresProtections() as $mesureProtection) {
375                    $this->entityManager->persist($mesureProtection);
376                }
377            }
378        }
379
380        $this->entityManager->persist($analyseImpact);
381        $this->entityManager->flush();
382
383        return $this->redirectToRoute('aipd_analyse_impact_create', [
384            'id' => $analyseImpact->getId(),
385        ]);
386    }
387
388    private function setAnalyseReponsesQuestionConformite(AnalyseImpact &$analyseImpact, ConformiteTraitement $conformiteTraitement)
389    {
390        foreach ($conformiteTraitement->getReponses() as $reponse) {
391            $q = $reponse->getQuestion()->getQuestion();
392            $q = $analyseImpact->getQuestionConformitesOfName($q);
393            $q->setAnalyseImpact($analyseImpact);
394            $q->setReponseConformite($reponse);
395            $reponse->addAnalyseQuestionConformite($q);
396            $this->entityManager->persist($reponse);
397        }
398    }
399
400    public function listDataTables(Request $request): JsonResponse
401    {
402        $criteria = $this->getRequestCriteria();
403
404        $treatments = $this->getResults($request, $criteria);
405        $reponse    = $this->getBaseDataTablesResponse($request, $treatments, $criteria);
406
407        /** @var Treatment $treatment */
408        foreach ($treatments as $treatment) {
409            if (is_array($treatment) && count($treatment) > 0) {
410                $treatment = $treatment[0];
411            }
412            $actions = $this->generateActionCellContent($treatment);
413
414            $reponse['data'][] = [
415                'icon'                  => $this->getIcon($treatment),
416                'nom'                   => $this->getTreatmentLink($treatment),
417                'collectivite'          => $this->isGranted('ROLE_REFERENT') ? $treatment->getCollectivity()->getName() : '',
418                'service'               => $this->userProvider->getAuthenticatedUser()->hasServices() && $treatment->getService() ? $treatment->getService()->getName() : '',
419                'gestionnaire'          => $treatment->getManager(),
420                'conformite_traitement' => $this->getTreatmentConformity($treatment),
421                'conformite_question'   => $this->getQuestionConformity($treatment),
422                'eval_createdAt'        => $treatment->getConformiteTraitement() ? date_format($treatment->getConformiteTraitement()->getCreatedAt(), 'd/m/Y') : null,
423                'avis_aipd'             => $this->getAvisAipd($treatment),
424                'aipd_createdAt'        => $treatment->getConformiteTraitement() && $treatment->getConformiteTraitement()->getLastAnalyseImpact() ? date_format($treatment->getConformiteTraitement()->getLastAnalyseImpact()->getCreatedAt(), 'd/m/Y') : null,
425                'actions'               => $actions,
426            ];
427        }
428
429        $jsonResponse = new JsonResponse();
430        $jsonResponse->setJson(\json_encode($reponse));
431
432        return $jsonResponse;
433    }
434
435    protected function getPlanifiedMesurements(ConformiteTraitement $conformiteTraitement): array
436    {
437        $planifiedMesurementsToBeNotified = [];
438        foreach ($conformiteTraitement->getReponses() as $reponse) {
439            $mesurements = \iterable_to_array($reponse->getActionProtectionsPlanifiedNotSeens());
440            foreach ($mesurements as $mesurement) {
441                if (!\in_array($mesurement, $planifiedMesurementsToBeNotified)) {
442                    \array_push($planifiedMesurementsToBeNotified, $mesurement);
443                }
444            }
445        }
446
447        return $planifiedMesurementsToBeNotified;
448    }
449
450    protected function getIcon(Treatment $treatment)
451    {
452        // return '<span style="background:red">blabla</span>';
453        $conf                            = $treatment->getConformiteTraitement();
454        $planifiedMesurementToBeNotified = [];
455        if ($conf) {
456            $planifiedMesurementToBeNotified = $this->getPlanifiedMesurements($conf);
457        }
458        $result = '';
459        if (count($planifiedMesurementToBeNotified)) {
460            $m = '';
461
462            foreach ($planifiedMesurementToBeNotified as $mes) {
463                $m .= '<li>' . $mes->getName() . '</li>';
464            }
465
466            $result = '<div class="mesurement-hide">
467                <i aria-hidden="true" class="primary-i fas fa-exclamation-circle"></i>
468                <div class="primary">
469                    <span>' . $this->translator->trans('registry.conformite_traitement.label.tooltip.mesurements_done') . '</span>
470                    <ul>' . $m . '</ul>
471                </div>
472            </div>';
473        }
474        if ($conf && $conf->getNeedsAipd()) {
475            $aipd = $conf->getLastAnalyseImpact();
476            if ($aipd) {
477                $result .= '<div>
478                    <span style="display:none">
479                  ' . $this->translator->trans('registry.conformite_traitement.label.tooltip.aipd_in_progress') . '  
480</span>
481                    <i class="fa fa-exclamation-triangle" aria-label="' . $this->translator->trans('registry.conformite_traitement.label.tooltip.aipd_in_progress') . '" title="' . $this->translator->trans('registry.conformite_traitement.label.tooltip.aipd_in_progress') . '" style="color:#f39c12;"></i>
482                </div>';
483            } else {
484                $result .= '<div>
485<span style="display:none">
486                  ' . $this->translator->trans('registry.conformite_traitement.label.tooltip.aipd_to_do') . '  
487</span>
488                    <i class="fa fa-exclamation-triangle" aria-label="' . $this->translator->trans('registry.conformite_traitement.label.tooltip.aipd_to_do') . '" title="' . $this->translator->trans('registry.conformite_traitement.label.tooltip.aipd_to_do') . '" style="color:#dd4b39;"></i>
489                </div>';
490            }
491        }
492
493        return $result;
494    }
495
496    protected function getLabelAndKeysArray(): array
497    {
498        if ($this->authorizationChecker->isGranted('ROLE_REFERENT')) {
499            return [
500                'icon',
501                'name',
502                'collectivite',
503                'service',
504                'gestionnaire',
505                'conformite_traitement',
506                'conformite_questions',
507                'eval_createdAt',
508                'avis_aipd',
509                'aipd_createdAt',
510                'actions',
511            ];
512        } elseif ($this->userProvider->getAuthenticatedUser()->hasServices()) {
513            return [
514                'icon',
515                'name',
516                'service',
517                'gestionnaire',
518                'conformite_traitement',
519                'conformite_questions',
520                'eval_createdAt',
521                'avis_aipd',
522                'aipd_createdAt',
523                'actions',
524            ];
525        }
526
527        return [
528            'icon',
529            'name',
530            'gestionnaire',
531            'conformite_traitement',
532            'conformite_questions',
533            'eval_createdAt',
534            'avis_aipd',
535            'aipd_createdAt',
536            'actions',
537        ];
538    }
539
540    private function getRequestCriteria()
541    {
542        $criteria = [];
543        $user     = $this->userProvider->getAuthenticatedUser();
544
545        if (!$this->authorizationChecker->isGranted('ROLE_ADMIN')) {
546            $criteria['collectivity'] = $user->getCollectivity();
547        }
548
549        if (\in_array(UserRoleDictionary::ROLE_REFERENT, $user->getRoles())) {
550            $criteria['collectivity'] = $user->getCollectivitesReferees();
551        }
552
553        // Add active treatment criteria
554        // Fixes https://gitlab.adullact.net/soluris/madis/-/issues/966
555        $criteria['active'] = true;
556
557        // Only for collectivites that have conformité traitement module active
558        // Fix for https://gitlab.adullact.net/soluris/madis/-/issues/950#note_147289
559        $criteria['hasModuleConformiteTraitement'] = true;
560
561        return $criteria;
562    }
563
564    private function getTreatmentLink(Treatment $treatment): string
565    {
566        $path = $this->router->generate('registry_treatment_show', ['id' => $treatment->getId()]);
567
568        return '<a href="' . $path . '">' . $treatment->getName() . '</a> ';
569    }
570
571    private function getAvisAipd(Treatment $treatment)
572    {
573        if (!$treatment->getConformiteTraitement()) {
574            return '<span class="label label-default" style="min-width: 100%; display: inline-block;">Non réalisée</span>';
575        }
576        $conf = $treatment->getConformiteTraitement();
577
578        if (null === $conf->getLastAnalyseImpact()) {
579            return '<span class="label label-default" style="min-width: 100%; display: inline-block;">Non réalisée</span>';
580        }
581        $analyse_impact = $conf->getLastAnalyseImpact();
582        $statut         = $analyse_impact->getStatut();
583
584        switch ($statut) {
585            case 'defavorable':
586                $label = 'Défavorable';
587                $class = 'label-danger';
588                break;
589            case 'favorable_reserve':
590                $label = 'Favorable avec réserve(s)';
591                $class = 'label-warning';
592                break;
593            case 'favorable':
594                $label = 'Favorable';
595                $class = 'label-success';
596                break;
597            case 'en_cours':
598                $label = 'En cours';
599                $class = 'label-default';
600                break;
601            default:
602                $label = 'Non réalisée';
603                $class = 'label-default';
604        }
605
606        return '<span class="label ' . $class . '" style="min-width: 100%; display: inline-block;">' . $label . '</span>';
607    }
608
609    private function getQuestionConformity(Treatment $treatment): string
610    {
611        $res = '';
612        $ct  = $treatment->getConformiteTraitement();
613        if ($ct) {
614            $nbTotal         = $ct->getNbConformes() + $ct->getNbNonConformesMineures() + $ct->getNbNonConformesMajeures();
615            $widthNbConforme = $nbTotal > 0 ? round(($ct->getNbConformes() * 100) / $nbTotal) : 0;
616            $widthNbMineure  = $nbTotal > 0 ? round(($ct->getNbNonConformesMineures() * 100) / $nbTotal) : 0;
617            $widthNbMajeure  = 100 - ($widthNbConforme + $widthNbMineure);
618            $res .= '<div class="stacked-bar-graph">';
619            if ($widthNbConforme) {
620                $res .= '<span style="width:' . $widthNbConforme . '%" class="bar-conforme tooltipchart"><span class="tooltipcharttext">Conforme : ' . $ct->getNbConformes() . '</span></span>';
621            }
622            if ($widthNbMineure) {
623                $res .= '<span style="width:' . $widthNbMineure . '%" class="bar-non-conforme-mineure tooltipchart"><span class="tooltipcharttext">Non-conforme mineure : ' . $ct->getNbNonConformesMineures() . '</span></span>';
624            }
625            if ($widthNbMajeure) {
626                $res .= '<span style="width:' . $widthNbMajeure . '%" class="bar-non-conforme-majeure tooltipchart"><span class="tooltipcharttext">Non-conforme majeure : ' . $ct->getNbNonConformesMajeures() . '</span></span>';
627            }
628
629            $res .= '</div>';
630        }
631
632        return $res;
633    }
634
635    private function getTreatmentConformity(Treatment $treatment)
636    {
637        if (!$treatment->getConformiteTraitement()) {
638            return '<span class="label label-default" style="min-width: 100%; display: inline-block;">Non Ã©valué</span>';
639        }
640        $conf  = $treatment->getConformiteTraitement();
641        $level = ConformiteTraitementCompletion::getConformiteTraitementLevel($conf);
642
643        $weight = ConformiteTraitementLevelDictionary::getConformitesWeight()[$level];
644
645        switch ($weight) {
646            case 1:
647                $label = 'Conforme';
648                $class = 'label-success';
649                break;
650            case 2:
651                $label = 'Non-conforme mineure';
652                $class = 'label-warning';
653                break;
654            default:
655                $label = 'Non-conforme majeure';
656                $class = 'label-danger';
657        }
658
659        return '<span class="label ' . $class . '" style="min-width: 100%; display: inline-block;">' . $label . '</span>';
660    }
661
662    private function generateActionCellContent(Treatment $treatment)
663    {
664        $id                  = $treatment->getId();
665        $conformityTreatment = $treatment->getConformiteTraitement();
666        $aipd                = $conformityTreatment?->getLastAnalyseImpact();
667        $blocHtml            = '';
668        $user                = $this->userProvider->getAuthenticatedUser();
669
670        $interact = true;
671        if ($treatment->getCollectivity()->getIsServicesEnabled() && $user->hasServices() && !$treatment->isInUserServices($user)) {
672            $interact = false;
673        }
674        if ($this->authorizationChecker->isGranted('ROLE_USER') && $interact) {
675            if (!$conformityTreatment) {
676                $path  = $this->router->generate('registry_conformite_traitement_create', ['idTraitement' => $id]);
677                $title = $this->translator->trans('registry.conformite_traitement.action.show_conformite_traitement');
678                $class = 'fa-clipboard-check';
679                $blocHtml .= $this->returnHtmlAction($path, $title, $class);
680            } else {
681                $path  = $this->router->generate('registry_conformite_traitement_edit', ['id' => $conformityTreatment->getId()]);
682                $title = $this->translator->trans('registry.conformite_traitement.action.show_conformite_traitement');
683                $class = 'fa-clipboard-check';
684                $blocHtml .= $this->returnHtmlAction($path, $title, $class);
685                if ($aipd) {
686                    if ($aipd->isValidated()) {
687                        $path  = $this->router->generate('aipd_analyse_impact_print', ['id' => $aipd->getId()]);
688                        $title = $this->translator->trans('aipd.analyse_impact.action.print');
689                        $class = 'fa-print';
690                        $blocHtml .= $this->returnHtmlAction($path, $title, $class);
691                    } else {
692                        $path  = $this->router->generate('aipd_analyse_impact_edit', ['id' => $aipd->getId()]);
693                        $title = $this->translator->trans('aipd.analyse_impact.action.edit');
694                        $class = 'fa-pencil';
695                        $blocHtml .= $this->returnHtmlAction($path, $title, $class);
696                    }
697                } else {
698                    $path  = $this->router->generate('registry_conformite_traitement_start_aipd', ['id' => $conformityTreatment->getId()]);
699                    $title = $this->translator->trans('aipd.analyse_impact.action.create');
700                    $class = 'fa-magnifying-glass-chart';
701                    $blocHtml .= $this->returnHtmlAction($path, $title, $class);
702                }
703            }
704        } elseif ($aipd && $aipd->isValidated()) {
705            $path  = $this->router->generate('aipd_analyse_impact_print', ['id' => $aipd->getId()]);
706            $title = $this->translator->trans('aipd.analyse_impact.action.print');
707            $class = 'fa-print';
708            $blocHtml .= $this->returnHtmlAction($path, $title, $class);
709        }
710
711        return $blocHtml;
712    }
713
714    private function returnHtmlAction($path, $title, $class)
715    {
716        return '<a href="' . $path . '">
717                        <i aria-hidden="true" class="fa ' . $class . '"></i>
718                        ' . $title . '
719                        </a> ';
720    }
721
722    private function isTreatmentInUserServices(Treatment $treatment): bool
723    {
724        $user = $this->userProvider->getAuthenticatedUser();
725        if ($this->authorizationChecker->isGranted('ROLE_ADMIN')) {
726            return true;
727        }
728
729        return $treatment->isInUserServices($user);
730    }
731
732    protected function getResults(Request $request, array $criteria = []): ?Paginator
733    {
734        $first      = $request->request->get('start');
735        $maxResults = $request->request->get('length');
736        $orders     = $request->request->get('order');
737        $columns    = $request->request->get('columns');
738
739        $orderColumn = $this->getCorrespondingLabelFromkey($orders[0]['column']);
740        $orderDir    = $orders[0]['dir'];
741
742        $searches = [];
743        foreach ($columns as $column) {
744            if ('' !== $column['search']['value']) {
745                $searches[$column['data']] = $column['search']['value'];
746            }
747        }
748
749        return $this->treatmentRepository->findPaginated($first, $maxResults, $orderColumn, $orderDir, $searches, $criteria);
750    }
751
752    protected function getBaseDataTablesResponse(Request $request, $results, array $criteria = [])
753    {
754        $draw = $request->request->get('draw');
755
756        $reponse = [
757            'draw'            => $draw,
758            'recordsTotal'    => $this->treatmentRepository->count($criteria),
759            'recordsFiltered' => count($results),
760            'data'            => [],
761        ];
762
763        return $reponse;
764    }
765}