Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
67.21% |
164 / 244 |
|
66.67% |
2 / 3 |
CRAP | |
0.00% |
0 / 1 |
UserMetric | |
67.21% |
164 / 244 |
|
66.67% |
2 / 3 |
166.53 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
1 | |||
getData | |
65.81% |
154 / 234 |
|
0.00% |
0 / 1 |
170.52 | |||
getTemplateViewName | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 |
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 | |
22 | declare(strict_types=1); |
23 | |
24 | namespace App\Domain\Reporting\Metrics; |
25 | |
26 | use App\Application\Symfony\Security\UserProvider; |
27 | use App\Domain\Maturity\Model\Referentiel; |
28 | use App\Domain\Registry\Calculator\Completion\ConformiteTraitementCompletion; |
29 | use App\Domain\Registry\Dictionary\ConformiteTraitementLevelDictionary; |
30 | use App\Domain\Registry\Dictionary\MesurementStatusDictionary; |
31 | use App\Domain\Registry\Dictionary\RequestStateDictionary; |
32 | use App\Domain\Registry\Model; |
33 | use App\Domain\Registry\Repository; |
34 | use App\Domain\Registry\Service\ConformiteOrganisationService; |
35 | use App\Domain\Reporting\Dictionary\LogJournalSubjectDictionary; |
36 | use App\Domain\Reporting\Repository\LogJournal; |
37 | use App\Infrastructure\ORM\Maturity\Repository\Survey as SurveyRepository; |
38 | use App\Infrastructure\ORM\Registry\Repository\ConformiteOrganisation\Evaluation; |
39 | use Doctrine\Inflector\InflectorFactory; |
40 | use Doctrine\Inflector\Language; |
41 | use Doctrine\ORM\EntityManagerInterface; |
42 | |
43 | class UserMetric implements MetricInterface |
44 | { |
45 | /** |
46 | * @var EntityManagerInterface |
47 | */ |
48 | private $entityManager; |
49 | |
50 | /** |
51 | * @var Repository\ConformiteTraitement\ConformiteTraitement |
52 | */ |
53 | private $conformiteTraitementRepository; |
54 | |
55 | /** |
56 | * @var Evaluation |
57 | */ |
58 | private $evaluationRepository; |
59 | |
60 | /** |
61 | * @var Repository\Request |
62 | */ |
63 | private $requestRepository; |
64 | |
65 | /** |
66 | * @var Repository\Treatment |
67 | */ |
68 | private $treatmentRepository; |
69 | /** |
70 | * @var SurveyRepository |
71 | */ |
72 | private $surveyRepository; |
73 | |
74 | /** |
75 | * @var UserProvider |
76 | */ |
77 | private $userProvider; |
78 | |
79 | /** |
80 | * @var LogJournal |
81 | */ |
82 | private $logJournalRepository; |
83 | |
84 | /** |
85 | * @var int |
86 | */ |
87 | private $userLogJounalViewLimit; |
88 | |
89 | public function __construct( |
90 | EntityManagerInterface $entityManager, |
91 | Repository\ConformiteTraitement\ConformiteTraitement $conformiteTraitementRepository, |
92 | Repository\Request $requestRepository, |
93 | Repository\Treatment $treatmentRepository, |
94 | UserProvider $userProvider, |
95 | Evaluation $evaluationRepository, |
96 | LogJournal $logJournalRepository, |
97 | SurveyRepository $surveyRepository, |
98 | int $userLogJounalViewLimit, |
99 | ) { |
100 | $this->entityManager = $entityManager; |
101 | $this->conformiteTraitementRepository = $conformiteTraitementRepository; |
102 | $this->requestRepository = $requestRepository; |
103 | $this->treatmentRepository = $treatmentRepository; |
104 | $this->userProvider = $userProvider; |
105 | $this->evaluationRepository = $evaluationRepository; |
106 | $this->logJournalRepository = $logJournalRepository; |
107 | $this->surveyRepository = $surveyRepository; |
108 | $this->userLogJounalViewLimit = $userLogJounalViewLimit; |
109 | } |
110 | |
111 | public function getData(?Referentiel $referentiel = null): array |
112 | { |
113 | $data = [ |
114 | 'conformiteOrganisation' => [ |
115 | ], |
116 | 'conformiteTraitement' => [ |
117 | 'data' => [], |
118 | 'labels' => [], |
119 | 'colors' => [], |
120 | ], |
121 | 'contractor' => [ |
122 | 'all' => 0, |
123 | 'clauses' => [ |
124 | 'yes' => 0, |
125 | 'no' => 0, |
126 | ], |
127 | 'adoptedSecurityFeatures' => [ |
128 | 'yes' => 0, |
129 | 'no' => 0, |
130 | ], |
131 | 'maintainsTreatmentRegister' => [ |
132 | 'yes' => 0, |
133 | 'no' => 0, |
134 | ], |
135 | 'sendingDataOutsideEu' => [ |
136 | 'yes' => 0, |
137 | 'no' => 0, |
138 | ], |
139 | ], |
140 | 'maturity' => [], |
141 | 'mesurement' => [ |
142 | 'value' => [ |
143 | 'applied' => 0, |
144 | 'notApplied' => 0, |
145 | 'notApplicable' => 0, |
146 | 'planified' => 0, |
147 | ], |
148 | 'percent' => [ |
149 | 'applied' => 0, |
150 | 'notApplied' => 0, |
151 | 'notApplicable' => 0, |
152 | 'planified' => 0, |
153 | ], |
154 | ], |
155 | 'request' => [ |
156 | 'value' => [ |
157 | 'all' => 0, |
158 | 'type' => [ |
159 | 'correct' => 0, |
160 | 'delete' => 0, |
161 | 'withdrawConsent' => 0, |
162 | 'access' => 0, |
163 | 'dataPortability' => 0, |
164 | 'limitTreatment' => 0, |
165 | 'oppositeTreatment' => 0, |
166 | 'other' => 0, |
167 | ], |
168 | 'status' => [ |
169 | 'toProcess' => 0, |
170 | 'processed' => 0, |
171 | 'denied' => 0, |
172 | ], |
173 | ], |
174 | ], |
175 | 'treatment' => [ |
176 | 'value' => [ |
177 | 'active' => 0, |
178 | 'numeric' => 0, |
179 | 'data' => [ |
180 | 'securityAccessControl' => [ |
181 | 'yes' => 0, |
182 | 'no' => 0, |
183 | ], |
184 | 'securityUpdate' => [ |
185 | 'yes' => 0, |
186 | 'no' => 0, |
187 | ], |
188 | 'securitySaving' => [ |
189 | 'yes' => 0, |
190 | 'no' => 0, |
191 | ], |
192 | 'securityTracability' => [ |
193 | 'yes' => 0, |
194 | 'no' => 0, |
195 | ], |
196 | ], |
197 | ], |
198 | ], |
199 | 'violation' => [ |
200 | 'value' => [ |
201 | 'all' => 0, |
202 | ], |
203 | ], |
204 | 'aipd' => [ |
205 | 'toDo' => 0, |
206 | ], |
207 | ]; |
208 | |
209 | $collectivity = $this->userProvider->getAuthenticatedUser()->getCollectivity(); |
210 | |
211 | $conformiteOrganisationEvaluation = $this->evaluationRepository->findLastByOrganisation($collectivity); |
212 | |
213 | $contractors = $this->entityManager->getRepository(Model\Contractor::class)->findBy( |
214 | ['collectivity' => $collectivity] |
215 | ); |
216 | |
217 | $data['logJournal'] = $this->logJournalRepository |
218 | ->findAllByCollectivityWithoutSubjects( |
219 | $collectivity, |
220 | $this->userLogJounalViewLimit, |
221 | [ |
222 | LogJournalSubjectDictionary::USER_COLLECTIVITY, |
223 | LogJournalSubjectDictionary::USER_EMAIL, |
224 | LogJournalSubjectDictionary::USER_FIRSTNAME, |
225 | LogJournalSubjectDictionary::USER_LASTNAME, |
226 | LogJournalSubjectDictionary::USER_PASSWORD, |
227 | LogJournalSubjectDictionary::USER_USER, |
228 | LogJournalSubjectDictionary::ADMIN_DUPLICATION, |
229 | ] |
230 | ); |
231 | |
232 | if ($referentiel) { |
233 | $maturity = $this->surveyRepository->findLatestByReferentialAndCollectivity( |
234 | $referentiel, |
235 | $collectivity |
236 | ); |
237 | } |
238 | |
239 | $mesurements = $this->entityManager->getRepository(Model\Mesurement::class)->findBy( |
240 | ['collectivity' => $collectivity] |
241 | ); |
242 | $requests = $this->requestRepository->findAllByCollectivity($collectivity); |
243 | $treatments = $this->entityManager->getRepository(Model\Treatment::class)->findBy( |
244 | ['collectivity' => $collectivity] |
245 | ); |
246 | $violations = $this->entityManager->getRepository(Model\Violation::class)->findBy( |
247 | ['collectivity' => $collectivity] |
248 | ); |
249 | |
250 | // ========================= |
251 | // PROCESS DATA MANIPULATION |
252 | // ========================= |
253 | |
254 | // CONTRACTOR |
255 | /** @var Model\Contractor $contractor */ |
256 | foreach ($contractors as $contractor) { |
257 | ++$data['contractor']['all']; |
258 | if ($contractor->isContractualClausesVerified()) { |
259 | ++$data['contractor']['clauses']['yes']; |
260 | } else { |
261 | ++$data['contractor']['clauses']['no']; |
262 | } |
263 | if ($contractor->isAdoptedSecurityFeatures()) { |
264 | ++$data['contractor']['adoptedSecurityFeatures']['yes']; |
265 | } else { |
266 | ++$data['contractor']['adoptedSecurityFeatures']['no']; |
267 | } |
268 | if ($contractor->isMaintainsTreatmentRegister()) { |
269 | ++$data['contractor']['maintainsTreatmentRegister']['yes']; |
270 | } else { |
271 | ++$data['contractor']['maintainsTreatmentRegister']['no']; |
272 | } |
273 | if ($contractor->isSendingDataOutsideEu()) { |
274 | ++$data['contractor']['sendingDataOutsideEu']['yes']; |
275 | } else { |
276 | ++$data['contractor']['sendingDataOutsideEu']['no']; |
277 | } |
278 | } |
279 | |
280 | // MATURITY |
281 | if (isset($maturity) && isset($maturity[0]) && null !== $maturity[0]->getReferentiel()) { |
282 | $data['maturity']['new']['name'] = $maturity[0]->getCreatedAt()->format('d/m/Y'); |
283 | foreach ($maturity[0]->getMaturity() as $item) { |
284 | $data['maturity']['new']['data'][$item->getDomain()->getPosition()]['name'] = $item->getDomain()->getName(); |
285 | $data['maturity']['new']['data'][$item->getDomain()->getPosition()]['score'] = $item->getScore() / 10; |
286 | } |
287 | if (isset($data['maturity']['new']['data']) && is_array($data['maturity']['new']['data'])) { |
288 | \ksort($data['maturity']['new']['data']); |
289 | } |
290 | } |
291 | if (isset($maturity) && isset($maturity[1]) && null !== $maturity[0]->getReferentiel()) { |
292 | $data['maturity']['old']['name'] = $maturity[1]->getCreatedAt()->format('d/m/Y'); |
293 | foreach ($maturity[1]->getMaturity() as $item) { |
294 | $data['maturity']['old']['data'][$item->getDomain()->getPosition()]['name'] = $item->getDomain()->getName(); |
295 | $data['maturity']['old']['data'][$item->getDomain()->getPosition()]['score'] = $item->getScore() / 10; |
296 | } |
297 | if (isset($data['maturity']['old']['data']) && is_array($data['maturity']['old']['data'])) { |
298 | \ksort($data['maturity']['old']['data']); |
299 | } |
300 | } |
301 | |
302 | // MESUREMENT |
303 | foreach ($mesurements as $mesurement) { |
304 | switch ($mesurement->getStatus()) { |
305 | case MesurementStatusDictionary::STATUS_APPLIED: |
306 | $data['mesurement']['value']['applied']++; |
307 | break; |
308 | case MesurementStatusDictionary::STATUS_NOT_APPLIED: |
309 | $data['mesurement']['value']['notApplied']++; |
310 | if (!\is_null($mesurement->getPlanificationDate())) { |
311 | ++$data['mesurement']['value']['planified']; |
312 | } |
313 | break; |
314 | case MesurementStatusDictionary::STATUS_NOT_APPLICABLE: |
315 | $data['mesurement']['value']['notApplicable']++; |
316 | } |
317 | } |
318 | // Only percent if there is non zero values |
319 | if (0 < $data['mesurement']['value']['applied']) { |
320 | $data['mesurement']['percent']['applied'] = $data['mesurement']['value']['applied'] * 100 / (\count($mesurements) - $data['mesurement']['value']['notApplicable']); |
321 | } |
322 | if (0 < $data['mesurement']['value']['notApplied']) { |
323 | $data['mesurement']['percent']['notApplied'] = $data['mesurement']['value']['notApplied'] * 100 / (\count($mesurements) - $data['mesurement']['value']['notApplicable']); |
324 | } |
325 | if (0 < $data['mesurement']['value']['notApplicable']) { |
326 | $data['mesurement']['percent']['notApplicable'] = $data['mesurement']['value']['notApplicable'] * 100 / \count($mesurements); |
327 | } |
328 | if (0 < $data['mesurement']['value']['planified']) { |
329 | $data['mesurement']['percent']['planified'] = $data['mesurement']['value']['planified'] * 100 / (\count($mesurements) - $data['mesurement']['value']['notApplicable']); |
330 | } |
331 | |
332 | // REQUEST |
333 | $data['request']['value']['all'] = \count($requests); |
334 | foreach ($requests as $request) { |
335 | // Only take under account active requests |
336 | if (!\is_null($request->getDeletedAt())) { |
337 | continue; |
338 | } |
339 | |
340 | // Type |
341 | if ($request->getObject()) { |
342 | $inflector = InflectorFactory::createForLanguage(Language::FRENCH)->build(); |
343 | if (isset($data['request']['value']['type'][$inflector->camelize($request->getObject())])) { |
344 | ++$data['request']['value']['type'][$inflector->camelize($request->getObject())]; |
345 | } else { |
346 | $data['request']['value']['type'][$inflector->camelize($request->getObject())] = 1; |
347 | } |
348 | } |
349 | |
350 | // Status |
351 | if (!is_null($request->getAnswer()->getDate()) && ('completed_closed' == $request->getState(RequestStateDictionary::STATE_COMPLETED_CLOSED))) { |
352 | ++$data['request']['value']['status']['processed']; |
353 | } elseif (!is_null($request->getAnswer()->getDate()) && ('denied' == $request->getState(RequestStateDictionary::STATE_DENIED))) { |
354 | ++$data['request']['value']['status']['denied']; |
355 | } else { |
356 | ++$data['request']['value']['status']['toProcess']; |
357 | } |
358 | } |
359 | |
360 | // TREATMENT |
361 | foreach ($treatments as $treatment) { |
362 | // Only take under account active treatments |
363 | if (!$treatment->isActive()) { |
364 | continue; |
365 | } |
366 | |
367 | ++$data['treatment']['value']['active']; |
368 | |
369 | // Numeric treatment |
370 | if (!\is_null($treatment->getToolsString()) && strlen($treatment->getToolsString()) > 0) { |
371 | ++$data['treatment']['value']['numeric']; |
372 | |
373 | if ($treatment->getSecurityAccessControl()->isCheck()) { |
374 | ++$data['treatment']['value']['data']['securityAccessControl']['yes']; |
375 | } else { |
376 | ++$data['treatment']['value']['data']['securityAccessControl']['no']; |
377 | } |
378 | if ($treatment->getSecurityUpdate()->isCheck()) { |
379 | ++$data['treatment']['value']['data']['securityUpdate']['yes']; |
380 | } else { |
381 | ++$data['treatment']['value']['data']['securityUpdate']['no']; |
382 | } |
383 | if ($treatment->getSecuritySaving()->isCheck()) { |
384 | ++$data['treatment']['value']['data']['securitySaving']['yes']; |
385 | } else { |
386 | ++$data['treatment']['value']['data']['securitySaving']['no']; |
387 | } |
388 | if ($treatment->getSecurityTracability()->isCheck()) { |
389 | ++$data['treatment']['value']['data']['securityTracability']['yes']; |
390 | } else { |
391 | ++$data['treatment']['value']['data']['securityTracability']['no']; |
392 | } |
393 | } |
394 | } |
395 | |
396 | // VIOLATION |
397 | foreach ($violations as $violation) { |
398 | // Only take under account active violations |
399 | if (\is_null($violation->getDeletedAt())) { |
400 | ++$data['violation']['value']['all']; |
401 | } |
402 | } |
403 | |
404 | // CONFORMITE TRAITEMENT |
405 | if ($collectivity->isHasModuleConformiteTraitement()) { |
406 | foreach (ConformiteTraitementLevelDictionary::getConformites() as $key => $label) { |
407 | $data['conformiteTraitement']['data'][$key] = 0; |
408 | $data['conformiteTraitement']['labels'][] = $label; |
409 | $data['conformiteTraitement']['colors'][] = ConformiteTraitementLevelDictionary::getRgbConformitesColorsForChartView()[$key]; |
410 | } |
411 | |
412 | $conformiteTraitements = $this->conformiteTraitementRepository->findActiveByCollectivity($collectivity); |
413 | $nbTreatmentWithNoConformiteTraitements = $this->treatmentRepository->countAllWithNoConformiteTraitementByCollectivity($collectivity); |
414 | $data['conformiteTraitement']['data'][ConformiteTraitementLevelDictionary::NON_EVALUE] = $nbTreatmentWithNoConformiteTraitements; |
415 | |
416 | /** @var Model\ConformiteTraitement\ConformiteTraitement $conformiteTraitement */ |
417 | foreach ($conformiteTraitements as $conformiteTraitement) { |
418 | $level = ConformiteTraitementCompletion::getConformiteTraitementLevel($conformiteTraitement); |
419 | ++$data['conformiteTraitement']['data'][$level]; |
420 | |
421 | if ( |
422 | $conformiteTraitement->getNeedsAipd() |
423 | ) { |
424 | ++$data['aipd']['toDo']; |
425 | } |
426 | } |
427 | |
428 | // reset data if all values equal zéro. Need to hide the chart. |
429 | if (empty(array_filter($data['conformiteTraitement']['data']))) { |
430 | $data['conformiteTraitement']['data'] = []; |
431 | } else { |
432 | $data['conformiteTraitement']['data'] = \array_values($data['conformiteTraitement']['data']); |
433 | } |
434 | } |
435 | |
436 | // CONFORMITE ORGANISATION |
437 | if ($collectivity->isHasModuleConformiteOrganisation() && null !== $conformiteOrganisationEvaluation) { |
438 | $conformites = ConformiteOrganisationService::getOrderedConformites($conformiteOrganisationEvaluation); |
439 | |
440 | foreach ($conformites as $conformite) { |
441 | $data['conformiteOrganisation'][$conformite->getProcessus()->getPosition()]['processus'] = $conformite->getProcessus()->getNom(); |
442 | $data['conformiteOrganisation'][$conformite->getProcessus()->getPosition()]['conformite'] = $conformite->getConformite(); |
443 | } |
444 | } |
445 | |
446 | return $data; |
447 | } |
448 | |
449 | public function getTemplateViewName(): string |
450 | { |
451 | return 'Reporting/Dashboard/index.html.twig'; |
452 | } |
453 | } |