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