Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.95% |
2 / 210 |
|
8.70% |
2 / 23 |
CRAP | |
0.00% |
0 / 1 |
Violation | |
0.95% |
2 / 210 |
|
8.70% |
2 / 23 |
3441.49 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getManager | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
createQueryBuilder | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
insert | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
update | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
create | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
remove | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
findAll | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 | |||
findOneById | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
getModelClass | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
addWhereClause | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
addArchivedClause | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
addCollectivityClause | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
addOrder | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
findAllByCollectivity | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
6 | |||
findBy | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
findAllArchivedByCollectivity | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
2 | |||
countAllByCollectivity | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
findOneOrNullLastUpdateByCollectivity | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
count | |
0.00% |
0 / 17 |
|
0.00% |
0 / 1 |
30 | |||
findPaginated | |
0.00% |
0 / 18 |
|
0.00% |
0 / 1 |
30 | |||
addTableOrder | |
0.00% |
0 / 54 |
|
0.00% |
0 / 1 |
132 | |||
addTableWhere | |
0.00% |
0 / 42 |
|
0.00% |
0 / 1 |
182 |
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\Infrastructure\ORM\Registry\Repository; |
25 | |
26 | use App\Application\Traits\RepositoryUtils; |
27 | use App\Domain\Registry\Dictionary\ViolationCauseDictionary; |
28 | use App\Domain\Registry\Dictionary\ViolationGravityDictionary; |
29 | use App\Domain\Registry\Dictionary\ViolationNatureDictionary; |
30 | use App\Domain\Registry\Dictionary\ViolationNotificationDictionary; |
31 | use App\Domain\Registry\Model; |
32 | use App\Domain\Registry\Repository; |
33 | use App\Domain\User\Model\Collectivity; |
34 | use Doctrine\Common\Collections\Collection; |
35 | use Doctrine\ORM\EntityManagerInterface; |
36 | use Doctrine\ORM\QueryBuilder; |
37 | use Doctrine\ORM\Tools\Pagination\Paginator; |
38 | use Doctrine\Persistence\ManagerRegistry; |
39 | |
40 | class Violation implements Repository\Violation |
41 | { |
42 | use RepositoryUtils; |
43 | /** |
44 | * @var ManagerRegistry |
45 | */ |
46 | protected $registry; |
47 | |
48 | /** |
49 | * Violation constructor. |
50 | */ |
51 | public function __construct(ManagerRegistry $registry) |
52 | { |
53 | $this->registry = $registry; |
54 | } |
55 | |
56 | /** |
57 | * Get the registry manager |
58 | * Since we use Doctrine, we expect to get EntityManagerInterface. |
59 | * |
60 | * @throws \Exception |
61 | */ |
62 | protected function getManager(): EntityManagerInterface |
63 | { |
64 | $manager = $this->registry->getManager(); |
65 | |
66 | if (!$manager instanceof EntityManagerInterface) { |
67 | throw new \Exception('Registry Manager must be an instance of EntityManagerInterface #PHPStan'); |
68 | } |
69 | |
70 | return $manager; |
71 | } |
72 | |
73 | /** |
74 | * Create the base of QueryBuilder to use for repository calls. |
75 | * |
76 | * @throws \Exception |
77 | */ |
78 | protected function createQueryBuilder(): QueryBuilder |
79 | { |
80 | return $this->getManager() |
81 | ->createQueryBuilder() |
82 | ->select('o') |
83 | ->from($this->getModelClass(), 'o') |
84 | ; |
85 | } |
86 | |
87 | /** |
88 | * Insert an object. |
89 | * |
90 | * @throws \Exception |
91 | */ |
92 | public function insert($object): void |
93 | { |
94 | $this->getManager()->persist($object); |
95 | $this->getManager()->flush(); |
96 | } |
97 | |
98 | /** |
99 | * Update an object. |
100 | * |
101 | * @throws \Exception |
102 | */ |
103 | public function update($object): void |
104 | { |
105 | $this->getManager()->flush(); |
106 | } |
107 | |
108 | /** |
109 | * Create an object. |
110 | */ |
111 | public function create() |
112 | { |
113 | $class = $this->getModelClass(); |
114 | |
115 | return new $class(); |
116 | } |
117 | |
118 | /** |
119 | * Remove an object. |
120 | * |
121 | * @throws \Exception |
122 | */ |
123 | public function remove($object): void |
124 | { |
125 | $this->getManager()->remove($object); |
126 | $this->getManager()->flush(); |
127 | } |
128 | |
129 | /** |
130 | * @throws \Exception |
131 | */ |
132 | public function findAll(bool $deleted = false): array |
133 | { |
134 | $qb = $this->createQueryBuilder(); |
135 | |
136 | if ($deleted) { |
137 | $qb->andWhere('o.deletedAt is not null'); |
138 | } else { |
139 | $qb->andWhere('o.deletedAt is null'); |
140 | } |
141 | |
142 | return $qb |
143 | ->getQuery() |
144 | ->getResult() |
145 | ; |
146 | } |
147 | |
148 | /** |
149 | * Get an object by ID. |
150 | * |
151 | * @param string $id The ID to find |
152 | * |
153 | * @return object|null |
154 | */ |
155 | public function findOneById(string $id) |
156 | { |
157 | return $this->registry |
158 | ->getManager() |
159 | ->getRepository($this->getModelClass()) |
160 | ->find($id) |
161 | ; |
162 | } |
163 | |
164 | protected function getModelClass(): string |
165 | { |
166 | return Model\Violation::class; |
167 | } |
168 | |
169 | /** |
170 | * Add a where clause. |
171 | */ |
172 | protected function addWhereClause(QueryBuilder $qb, string $key, $value): QueryBuilder |
173 | { |
174 | return $qb |
175 | ->andWhere("o.{$key} = :{$key}_value") |
176 | ->setParameter("{$key}_value", $value) |
177 | ; |
178 | } |
179 | |
180 | /** |
181 | * Add archive clause to query. |
182 | */ |
183 | protected function addArchivedClause(QueryBuilder $qb, bool $archived = false): QueryBuilder |
184 | { |
185 | // Get not archived |
186 | if (!$archived) { |
187 | return $qb->andWhere('o.deletedAt is null'); |
188 | } |
189 | |
190 | // Get archived |
191 | return $qb->andWhere('o.deletedAt is not null'); |
192 | } |
193 | |
194 | /** |
195 | * Add collectivity clause to query. |
196 | */ |
197 | protected function addCollectivityClause(QueryBuilder $qb, Collectivity $collectivity): QueryBuilder |
198 | { |
199 | return $qb |
200 | ->andWhere('o.collectivity = :collectivity') |
201 | ->setParameter('collectivity', $collectivity) |
202 | ; |
203 | } |
204 | |
205 | /** |
206 | * Add order to query. |
207 | */ |
208 | protected function addOrder(QueryBuilder $qb, array $order = []): QueryBuilder |
209 | { |
210 | foreach ($order as $key => $dir) { |
211 | $qb->addOrderBy("o.{$key}", $dir); |
212 | } |
213 | |
214 | return $qb; |
215 | } |
216 | |
217 | /** |
218 | * @throws \Exception |
219 | */ |
220 | public function findAllByCollectivity(Collectivity $collectivity, bool $deleted = false, array $order = []) |
221 | { |
222 | $qb = $this->createQueryBuilder(); |
223 | |
224 | $this->addCollectivityClause($qb, $collectivity); |
225 | |
226 | if ($deleted) { |
227 | $qb->andWhere('o.deletedAt is not null'); |
228 | } else { |
229 | $qb->andWhere('o.deletedAt is null'); |
230 | } |
231 | |
232 | $this->addOrder($qb, $order); |
233 | |
234 | return $qb |
235 | ->getQuery() |
236 | ->getResult() |
237 | ; |
238 | } |
239 | |
240 | /** |
241 | * @throws \Exception |
242 | */ |
243 | public function findBy(array $criteria = []) |
244 | { |
245 | $qb = $this->createQueryBuilder(); |
246 | |
247 | foreach ($criteria as $key => $value) { |
248 | $this->addWhereClause($qb, $key, $value); |
249 | } |
250 | |
251 | return $qb |
252 | ->getQuery() |
253 | ->getResult() |
254 | ; |
255 | } |
256 | |
257 | /** |
258 | * @throws \Exception |
259 | */ |
260 | public function findAllArchivedByCollectivity(Collectivity $collectivity, bool $archived = false, array $order = []) |
261 | { |
262 | $qb = $this->createQueryBuilder(); |
263 | |
264 | $this->addCollectivityClause($qb, $collectivity); |
265 | $this->addArchivedClause($qb, $archived); |
266 | $this->addOrder($qb, $order); |
267 | |
268 | return $qb |
269 | ->getQuery() |
270 | ->getResult() |
271 | ; |
272 | } |
273 | |
274 | public function countAllByCollectivity(Collectivity $collectivity) |
275 | { |
276 | $qb = $this->createQueryBuilder(); |
277 | |
278 | $qb->select('COUNT(o.id)'); |
279 | $this->addCollectivityClause($qb, $collectivity); |
280 | |
281 | return $qb->getQuery()->getSingleScalarResult(); |
282 | } |
283 | |
284 | public function findOneOrNullLastUpdateByCollectivity(Collectivity $collectivity): ?Model\Violation |
285 | { |
286 | $qb = $this->createQueryBuilder(); |
287 | |
288 | $this->addCollectivityClause($qb, $collectivity); |
289 | $qb->addOrderBy('o.updatedAt', 'DESC'); |
290 | $qb->setMaxResults(1); |
291 | |
292 | return $qb->getQuery()->getOneOrNullResult(); |
293 | } |
294 | |
295 | public function count(array $criteria = []) |
296 | { |
297 | $qb = $this |
298 | ->createQueryBuilder() |
299 | ->select('count(o.id)') |
300 | ; |
301 | |
302 | if (\array_key_exists('archive', $criteria)) { |
303 | $this->addArchivedClause($qb, $criteria['archive']); |
304 | unset($criteria['archive']); |
305 | } |
306 | |
307 | if (isset($criteria['collectivity']) && $criteria['collectivity'] instanceof Collection) { |
308 | $qb->leftJoin('o.collectivity', 'collectivite'); |
309 | $this->addInClauseCollectivities($qb, $criteria['collectivity']->toArray()); |
310 | unset($criteria['collectivity']); |
311 | } |
312 | |
313 | foreach ($criteria as $key => $value) { |
314 | $this->addWhereClause($qb, $key, $value); |
315 | } |
316 | |
317 | return $qb |
318 | ->getQuery() |
319 | ->getSingleScalarResult() |
320 | ; |
321 | } |
322 | |
323 | public function findPaginated($firstResult, $maxResults, $orderColumn, $orderDir, $searches, $criteria = []) |
324 | { |
325 | $qb = $this->createQueryBuilder(); |
326 | |
327 | if (\array_key_exists('archive', $criteria)) { |
328 | $this->addArchivedClause($qb, $criteria['archive']); |
329 | unset($criteria['archive']); |
330 | } |
331 | |
332 | $qb->leftJoin('o.collectivity', 'collectivite') |
333 | ->leftJoin('o.service', 'service') |
334 | ->addSelect('collectivite'); |
335 | |
336 | if (isset($criteria['collectivity']) && $criteria['collectivity'] instanceof Collection) { |
337 | $this->addInClauseCollectivities($qb, $criteria['collectivity']->toArray()); |
338 | unset($criteria['collectivity']); |
339 | } |
340 | |
341 | foreach ($criteria as $key => $value) { |
342 | $this->addWhereClause($qb, $key, $value); |
343 | } |
344 | |
345 | $this->addTableOrder($qb, $orderColumn, $orderDir); |
346 | $this->addTableWhere($qb, $searches); |
347 | |
348 | $query = $qb->getQuery(); |
349 | $query->setFirstResult($firstResult); |
350 | $query->setMaxResults($maxResults); |
351 | |
352 | return new Paginator($query); |
353 | } |
354 | |
355 | private function addTableOrder(QueryBuilder $queryBuilder, $orderColumn, $orderDir) |
356 | { |
357 | switch ($orderColumn) { |
358 | case 'collectivite': |
359 | $queryBuilder->addOrderBy('collectivite.name', $orderDir); |
360 | break; |
361 | case 'service': |
362 | $queryBuilder->addOrderBy('service.name', $orderDir); |
363 | break; |
364 | case 'date': |
365 | |
366 | $queryBuilder->addOrderBy('o.date', $orderDir); |
367 | break; |
368 | case 'nature': |
369 | $queryBuilder->addSelect('(case |
370 | WHEN o.violationNatures LIKE \'%' . ViolationNatureDictionary::NATURE_INTEGRITY . '%\' THEN 1 |
371 | WHEN o.violationNatures LIKE \'%' . ViolationNatureDictionary::NATURE_CONFIDENTIALITY . '%\' THEN 2 |
372 | WHEN o.violationNatures LIKE \'%' . ViolationNatureDictionary::NATURE_AVAILABILITY . '%\' THEN 3 |
373 | |
374 | ELSE 4 END) AS HIDDEN hidden_violation_nature') |
375 | ->addOrderBy('hidden_violation_nature', $orderDir); |
376 | break; |
377 | case 'cause': |
378 | $queryBuilder->addSelect('(case |
379 | WHEN o.cause = \'' . ViolationCauseDictionary::CAUSE_EXTERNAL_ACCIDENTAL . '\' THEN 1 |
380 | WHEN o.cause = \'' . ViolationCauseDictionary::CAUSE_EXTERNAL_MALICIOUS . '\' THEN 2 |
381 | WHEN o.cause = \'' . ViolationCauseDictionary::CAUSE_INTERNAL_ACCIDENTAL . '\' THEN 3 |
382 | WHEN o.cause = \'' . ViolationCauseDictionary::CAUSE_INTERNAL_MALICIOUS . '\' THEN 4 |
383 | WHEN o.cause = \'' . ViolationCauseDictionary::CAUSE_UNKNOWN . '\' THEN 5 |
384 | ELSE 6 END) AS HIDDEN hidden_cause') |
385 | ->addOrderBy('hidden_cause', $orderDir); |
386 | break; |
387 | case 'gravity': |
388 | $queryBuilder->addSelect('(case |
389 | WHEN o.gravity = \'' . ViolationGravityDictionary::GRAVITY_IMPORTANT . '\' THEN 1 |
390 | WHEN o.gravity = \'' . ViolationGravityDictionary::GRAVITY_LIMITED . '\' THEN 2 |
391 | WHEN o.gravity = \'' . ViolationGravityDictionary::GRAVITY_MAXIMUM . '\' THEN 3 |
392 | WHEN o.gravity = \'' . ViolationGravityDictionary::GRAVITY_NEGLIGIBLE . '\' THEN 4 |
393 | ELSE 5 END) AS HIDDEN hidden_gravity') |
394 | ->addOrderBy('hidden_gravity', $orderDir); |
395 | break; |
396 | case 'notification': |
397 | $queryBuilder->addSelect('(case |
398 | WHEN o.notification = \'' . ViolationNotificationDictionary::NOTIFICATION_NOTHING . '\' THEN 1 |
399 | WHEN o.notification = \'' . ViolationNotificationDictionary::NOTIFICATION_CNIL . '\' THEN 2 |
400 | WHEN o.notification = \'' . ViolationNotificationDictionary::NOTIFICATION_CROSS_BORDER . '\' THEN 3 |
401 | WHEN o.notification = \'' . ViolationNotificationDictionary::NOTIFICATION_OTHER . '\' THEN 4 |
402 | ELSE 5 END) AS HIDDEN hidden_notif') |
403 | ->addOrderBy('hidden_notif', $orderDir); |
404 | break; |
405 | case 'createdAt': |
406 | $queryBuilder->addOrderBy('o.createdAt', $orderDir); |
407 | break; |
408 | case 'inProgress': |
409 | $queryBuilder->addOrderBy('o.inProgress', $orderDir); |
410 | break; |
411 | case 'updatedAt': |
412 | $queryBuilder->addOrderBy('o.updatedAt', $orderDir); |
413 | break; |
414 | } |
415 | } |
416 | |
417 | private function addTableWhere(QueryBuilder $queryBuilder, $searches) |
418 | { |
419 | foreach ($searches as $columnName => $search) { |
420 | switch ($columnName) { |
421 | case 'collectivite': |
422 | $queryBuilder->andWhere('collectivite.name LIKE :nom') |
423 | ->setParameter('nom', '%' . $search . '%'); |
424 | break; |
425 | case 'service': |
426 | $queryBuilder->andWhere('service.name LIKE :sernom') |
427 | ->setParameter('sernom', '%' . $search . '%'); |
428 | break; |
429 | case 'date': |
430 | $queryBuilder->andWhere('o.date BETWEEN :date_start_date AND :date_finish_date') |
431 | ->setParameter('date_start_date', date_create_from_format('d/m/y', substr($search, 0, 8))->format('Y-m-d 00:00:00')) |
432 | ->setParameter('date_finish_date', date_create_from_format('d/m/y', substr($search, 11, 8))->format('Y-m-d 23:59:59')); |
433 | break; |
434 | case 'nature': |
435 | $queryBuilder->andWhere('o.violationNatures LIKE :nature') |
436 | ->setParameter('nature', '%' . $search . '%'); |
437 | break; |
438 | case 'inProgress': |
439 | $this->addWhereClause($queryBuilder, 'inProgress', $search); |
440 | break; |
441 | case 'cause': |
442 | $this->addWhereClause($queryBuilder, 'cause', $search); |
443 | break; |
444 | case 'gravity': |
445 | $this->addWhereClause($queryBuilder, 'gravity', $search); |
446 | break; |
447 | case 'notification': |
448 | if ('none' == $search) { |
449 | $queryBuilder->andWhere('o.notification IS NULL'); |
450 | } else { |
451 | $this->addWhereClause($queryBuilder, 'notification', $search); |
452 | } |
453 | |
454 | break; |
455 | case 'createdAt': |
456 | $queryBuilder->andWhere('o.createdAt BETWEEN :created_start_date AND :created_finish_date') |
457 | ->setParameter('created_start_date', date_create_from_format('d/m/y', substr($search, 0, 8))->format('Y-m-d 00:00:00')) |
458 | ->setParameter('created_finish_date', date_create_from_format('d/m/y', substr($search, 11, 8))->format('Y-m-d 23:59:59')); |
459 | break; |
460 | case 'updatedAt': |
461 | $queryBuilder->andWhere('o.updatedAt BETWEEN :updated_start_date AND :updated_finish_date') |
462 | ->setParameter('updated_start_date', date_create_from_format('d/m/y', substr($search, 0, 8))->format('Y-m-d 00:00:00')) |
463 | ->setParameter('updated_finish_date', date_create_from_format('d/m/y', substr($search, 11, 8))->format('Y-m-d 23:59:59')); |
464 | break; |
465 | } |
466 | } |
467 | } |
468 | } |