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