Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 147
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
ConformiteOrganisationGenerator
0.00% covered (danger)
0.00%
0 / 147
0.00% covered (danger)
0.00%
0 / 8
756
0.00% covered (danger)
0.00%
0 / 1
 addSyntheticView
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 addDetailedView
0.00% covered (danger)
0.00%
0 / 42
0.00% covered (danger)
0.00%
0 / 1
42
 addGlobalOverview
0.00% covered (danger)
0.00%
0 / 62
0.00% covered (danger)
0.00%
0 / 1
20
 getConformitesTable
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
30
 extractConformiteProcessus
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 getFormattedReponse
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
 getFormattedParticipants
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
12
 getFormattedActionsDeProtection
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3namespace App\Domain\Reporting\Generator\Word;
4
5use App\Domain\Registry\Dictionary\ConformiteOrganisation\ReponseDictionary;
6use App\Domain\Registry\Model\ConformiteOrganisation\Conformite;
7use App\Domain\Registry\Model\ConformiteOrganisation\Evaluation;
8use App\Domain\Registry\Model\ConformiteOrganisation\Reponse;
9use App\Domain\Registry\Model\Mesurement;
10use App\Domain\Registry\Service\ConformiteOrganisationService;
11use App\Domain\User\Dictionary\ContactCivilityDictionary;
12use PhpOffice\PhpWord\Element\Section;
13use PhpOffice\PhpWord\Shared\Converter;
14use PhpOffice\PhpWord\SimpleType\TblWidth;
15use PhpOffice\PhpWord\Style\ListItem;
16use PhpOffice\PhpWord\Style\Table;
17
18class ConformiteOrganisationGenerator extends AbstractGenerator implements ImpressionGeneratorInterface
19{
20    protected $average;
21
22    public function addSyntheticView(Section $section, array $data): void
23    {
24        /*  Not used anymore in this generator since it's useless
25            All content is generated in the addDetailedView() method below */
26    }
27
28    public function addDetailedView(Section $section, array $data): void
29    {
30        /** @var Evaluation $evaluation */
31        $evaluation = $data[0];
32
33        /* ////////////////////////////////////////////////////////////// */
34        $section->addTitle('Contexte', 1);
35        $contextData = [
36            [
37                'Date de l\'évaluation',
38                $evaluation->getDate()->format('Y-m-d'),
39            ],
40            [
41                'Liste des participants',
42                [['array' => $this->getFormattedParticipants($evaluation)]],
43            ],
44        ];
45        $this->addTable($section, $contextData, false, self::TABLE_ORIENTATION_VERTICAL);
46
47        /* ////////////////////////////////////////////////////////////// */
48        $section->addTitle('Liste des processus', 1);
49
50        $orderedConformites = ConformiteOrganisationService::getOrderedConformites($evaluation);
51        $tableData          = $this->getConformitesTable($orderedConformites);
52
53        $this->addTable($section, $tableData, false, self::TABLE_ORIENTATION_HORIZONTAL);
54
55        /* ////////////////////////////////////////////////////////////// */
56        $section->addPageBreak();
57        $section->addTitle('Détail des processus', 1);
58
59        /** @var Conformite $conformite */
60        foreach ($orderedConformites as $key => $conformite) {
61            if (0 != $key) {
62                $section->addPageBreak();
63            }
64
65            $processus = [];
66
67            $section->addTitle($conformite->getProcessus()->getNom(), 3);
68            $section->addText($conformite->getProcessus()->getDescription());
69
70            foreach (ConformiteOrganisationService::getOrderedReponse($conformite) as $reponse) {
71                $processus[] = [
72                    \strip_tags($reponse->getQuestion()->getNom()),
73                    $this->getFormattedReponse($reponse),
74                ];
75            }
76            $actions        = \iterable_to_array($conformite->getActionProtections());
77            $withAllActions = $data[1]; /* Useless, for reading purpose only */
78            if (!$withAllActions) {
79                $actions = $conformite->getNonAppliedActionProtections();
80            }
81
82            $actions = !empty(\iterable_to_array($conformite->getActionProtections()))
83                ? $this->getFormattedActionsDeProtection($actions)
84                : 'Aucune';
85            $processus[] = [
86                'Actions de protection',
87                $actions,
88            ];
89
90            $this->addTable($section, $processus, false, self::TABLE_ORIENTATION_VERTICAL);
91        }
92    }
93
94    public function addGlobalOverview(Section $section, ?Evaluation $evaluation = null)
95    {
96        if (null === $evaluation) {
97            return;
98        }
99
100        $conformites = ConformiteOrganisationService::getOrderedConformites($evaluation);
101
102        $scores = [];
103        foreach ($conformites as $conformite) {
104            $scores[] = $conformite->getConformite();
105        }
106
107        $style = [
108            'width'            => Converter::cmToEmu(15),
109            'height'           => Converter::cmToEmu(11),
110            'showAxisLabels'   => true,
111            'showGridY'        => true,
112            'dataLabelOptions' => [
113                'showVal'     => false,
114                'showCatName' => false,
115            ],
116        ];
117
118        $section->addTitle('Analyse de la conformité de la structure', 2);
119        $listStyle = ['listType' => ListItem::TYPE_NUMBER_NESTED];
120        $section->addText('Afin de répondre aux objectifs du RGPD, la gestion des données à caractère personnel est structurée en 12 processus dont les objectifs sont définis dans le document figurant en annexe et à valeur de preuve.');
121        $section->addText('Chacun des 12 processus est évalué annuellement et selon l’échelle de maturité ci-après.');
122        $section->addText('Lorsque cela est nécessaire une ou plusieurs actions de progrès sont proposées au responsable du traitement pour validation et mise en opération.');
123        $section->addText('Liste des 12 processus :');
124        $section->addListItem('Organiser la conformité', 0, null, $listStyle);
125        $section->addListItem('Gérer les exigences et les poursuites', 0, null, $listStyle);
126        $section->addListItem('Gérer les sous-traitants de données à caractère personnel', 0, null, $listStyle);
127        $section->addListItem('Évaluer et auditer', 0, null, $listStyle);
128        $section->addListItem('Gérer les traitements', 0, null, $listStyle);
129        $section->addListItem('Sensibiliser, former, communiquer', 0, null, $listStyle);
130        $section->addListItem('Gérer les risques et les impacts sur la vie privée', 0, null, $listStyle);
131        $section->addListItem('Gérer les droits des personnes concernées', 0, null, $listStyle);
132        $section->addListItem('Gérer les violations de données à caractère personnel', 0, null, $listStyle);
133        $section->addListItem('Gérer la protection des données à caractère personnel', 0, null, $listStyle);
134        $section->addListItem('Gérer la documentation et les preuves', 0, null, $listStyle);
135        $section->addListItem('Gérer les opérations du système de management de la protection des données', 0, null, $listStyle);
136
137        $this->average = 0;
138        $tableData     = $this->getConformitesTable($conformites);
139
140        $section->addText('Le graphique représente la situation au ' . date('d/m/Y') . '. Sur l’ensemble des processus, la moyenne est de ' . round($this->average, 2) . '/5. À chaque processus, des propositions d’améliorations sont faites puis retranscrites dans le plan de progrès.');
141
142        $section->addChart('column', $this->extractConformiteProcessus($evaluation), $scores, $style);
143
144        $tableStyleConformite = [
145            'borderColor' => '006699',
146            'borderSize'  => 6,
147            'cellMargin'  => 100,
148            'unit'        => TblWidth::PERCENT,
149            'width'       => 100 * 50,
150            'layout'      => Table::LAYOUT_FIXED,
151        ];
152        $tableOrganisationConformite = $section->addTable($tableStyleConformite);
153        $tableOrganisationConformite->addRow(null, ['tblHeader' => true, 'cantsplit' => true]);
154        $cell = $tableOrganisationConformite->addCell(2000, $this->cellHeadStyle);
155        $cell->addText('Pilote', $this->textHeadStyle);
156        $cell = $tableOrganisationConformite->addCell(4500, $this->cellHeadStyle);
157        $cell->addText('Processus', $this->textHeadStyle);
158        $cell = $tableOrganisationConformite->addCell(1500, $this->cellHeadStyle);
159        $cell->addText('Conformité', $this->textHeadStyle);
160
161        foreach ($tableData as $line) {
162            $tableOrganisationConformite->addRow(null, ['cantsplit' => true]);
163            $cell1 = $tableOrganisationConformite->addCell(2000);
164            $cell1->addText($line[0]);
165            $cell2 = $tableOrganisationConformite->addCell(4500);
166            $cell2->addText($line[1]);
167            $cell3 = $tableOrganisationConformite->addCell(1500, ['align' => 'center', 'bgColor' => $line[2]['style']['bgColor']]);
168            $cell3->addText($line[2]['content']['text'], ['bold' => true], ['align' => 'center']);
169        }
170    }
171
172    private function getConformitesTable(array $conformites): array
173    {
174        $tableData = [];
175        foreach ($conformites as $conformite) {
176            $this->average += $conformite->getConformite();
177            switch (true) {
178                case $conformite->getConformite() < 2.5:
179                    $bgColor = 'ffa7a7';
180                    break;
181                case $conformite->getConformite() < 3.5:
182                    $bgColor = 'fac9ad';
183                    break;
184                default:
185                    $bgColor = 'bce292';
186                    break;
187            }
188            $tableData[] = [
189                $conformite->getPilote() ?? 'Inexistant',
190                $conformite->getProcessus()->getNom(),
191                ['content' => ['text' => $conformite->getConformite()], 'style' => ['bgColor' => $bgColor, 'bold' => true]],
192            ];
193        }
194        $this->average /= 12;
195
196        return $tableData;
197    }
198
199    private function extractConformiteProcessus(Evaluation $evaluation): array
200    {
201        $processus = [];
202        foreach (ConformiteOrganisationService::getOrderedConformites($evaluation) as $conformite) {
203            $processus[] = $conformite->getProcessus()->getNom();
204        }
205
206        return $processus;
207    }
208
209    private function getFormattedReponse(Reponse $reponse): string
210    {
211        switch ($reponse->getReponse()) {
212            case null:
213                return 'Inexistant';
214            case ReponseDictionary::NON_CONCERNE:
215                return
216                    ReponseDictionary::getReponseLabelFromKey($reponse->getReponse()) .
217                    ' (' . $reponse->getReponseRaison() . ')';
218            default:
219                return ReponseDictionary::getReponseLabelFromKey($reponse->getReponse());
220        }
221    }
222
223    private function getFormattedParticipants(Evaluation $evaluation): array
224    {
225        $participants = [];
226        foreach ($evaluation->getParticipants() as $participant) {
227            $participantsString = '';
228            $participantsString .= ContactCivilityDictionary::getCivilities()[$participant->getCivilite()];
229            $participantsString .= ' ' . $participant->getPrenom() . ' ' . $participant->getNomDeFamille();
230            if (null !== $participant->getFonction()) {
231                $participantsString .= ', ' . $participant->getFonction();
232            }
233            $participants[] = $participantsString;
234        }
235
236        return $participants;
237    }
238
239    private function getFormattedActionsDeProtection(array $actions)
240    {
241        $formattedActions = [];
242        /** @var Mesurement $action */
243        foreach ($actions as $action) {
244            $formattedActions[] = $action->getName();
245        }
246
247        return $formattedActions;
248    }
249}