Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
8.18% |
18 / 220 |
|
29.41% |
5 / 17 |
CRAP | |
0.00% |
0 / 1 |
NotificationController | |
8.18% |
18 / 220 |
|
29.41% |
5 / 17 |
7081.08 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
getDomain | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getModel | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getModelClass | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getFormType | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getListData | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
listAction | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 | |||
listDataTables | |
0.00% |
0 / 45 |
|
0.00% |
0 / 1 |
380 | |||
generateActionCellContent | |
0.00% |
0 / 26 |
|
0.00% |
0 / 1 |
72 | |||
formPrePersistData | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
markAsReadAllAction | |
0.00% |
0 / 17 |
|
0.00% |
0 / 1 |
90 | |||
markAsReadAction | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
72 | |||
markAsUnreadAction | |
0.00% |
0 / 17 |
|
0.00% |
0 / 1 |
72 | |||
getLabelAndKeysArray | |
0.00% |
0 / 23 |
|
0.00% |
0 / 1 |
20 | |||
getObjectLink | |
38.89% |
7 / 18 |
|
0.00% |
0 / 1 |
58.73 | |||
deleteConfirmationAction | |
0.00% |
0 / 15 |
|
0.00% |
0 / 1 |
20 | |||
getRouteForModule | |
9.52% |
2 / 21 |
|
0.00% |
0 / 1 |
118.65 |
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\Notification\Controller; |
25 | |
26 | use App\Application\Controller\CRUDController; |
27 | use App\Application\Symfony\Security\UserProvider; |
28 | use App\Application\Traits\ServersideDatatablesTrait; |
29 | use App\Domain\Notification\Model; |
30 | use App\Domain\Notification\Model\Notification; |
31 | use App\Domain\Notification\Model\NotificationUser; |
32 | use App\Domain\Notification\Repository; |
33 | use App\Domain\User\Dictionary\UserMoreInfoDictionary; |
34 | use App\Domain\User\Dictionary\UserRoleDictionary; |
35 | use App\Infrastructure\ORM\AIPD\Repository\AnalyseImpact; |
36 | use Doctrine\Common\Collections\ArrayCollection; |
37 | use Doctrine\ORM\EntityManagerInterface; |
38 | use Doctrine\ORM\Tools\Pagination\Paginator; |
39 | use Knp\Snappy\Pdf; |
40 | use Symfony\Component\HttpFoundation\JsonResponse; |
41 | use Symfony\Component\HttpFoundation\Request; |
42 | use Symfony\Component\HttpFoundation\Response; |
43 | use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; |
44 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; |
45 | use Symfony\Component\Routing\RouterInterface; |
46 | use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; |
47 | use Symfony\Contracts\Translation\TranslatorInterface; |
48 | |
49 | /** |
50 | * @property Repository\Notification $repository |
51 | */ |
52 | class NotificationController extends CRUDController |
53 | { |
54 | use ServersideDatatablesTrait; |
55 | |
56 | /** |
57 | * @var RouterInterface |
58 | */ |
59 | private $router; |
60 | |
61 | /** |
62 | * @var AuthorizationCheckerInterface |
63 | */ |
64 | protected $authorizationChecker; |
65 | |
66 | /** |
67 | * @var UserProvider |
68 | */ |
69 | protected $userProvider; |
70 | |
71 | protected AnalyseImpact $aipdRepository; |
72 | |
73 | public function __construct( |
74 | RouterInterface $router, |
75 | EntityManagerInterface $entityManager, |
76 | TranslatorInterface $translator, |
77 | Repository\Notification $repository, |
78 | AnalyseImpact $aipdRepository, |
79 | AuthorizationCheckerInterface $authorizationChecker, |
80 | UserProvider $userProvider, |
81 | Pdf $pdf, |
82 | ) { |
83 | parent::__construct($entityManager, $translator, $repository, $pdf, $userProvider, $authorizationChecker); |
84 | $this->router = $router; |
85 | $this->authorizationChecker = $authorizationChecker; |
86 | $this->userProvider = $userProvider; |
87 | $this->aipdRepository = $aipdRepository; |
88 | } |
89 | |
90 | protected function getDomain(): string |
91 | { |
92 | return 'notification'; |
93 | } |
94 | |
95 | protected function getModel(): string |
96 | { |
97 | return 'notification'; |
98 | } |
99 | |
100 | protected function getModelClass(): string |
101 | { |
102 | return Notification::class; |
103 | } |
104 | |
105 | protected function getFormType(): string |
106 | { |
107 | return ''; |
108 | } |
109 | |
110 | protected function getListData() |
111 | { |
112 | $order = [ |
113 | 'createdAt' => 'DESC', |
114 | ]; |
115 | |
116 | return $this->repository->findAll($order); |
117 | } |
118 | |
119 | public function listAction(): Response |
120 | { |
121 | $user = $this->getUser(); |
122 | |
123 | $criteria = []; |
124 | |
125 | if (!$this->authorizationChecker->isGranted('ROLE_ADMIN')) { |
126 | $criteria['collectivity'] = $this->userProvider->getAuthenticatedUser()->getCollectivity(); |
127 | } |
128 | |
129 | return $this->render('Notification/Notification/list.html.twig', [ |
130 | 'totalItem' => $this->repository->count($criteria), |
131 | 'route' => $this->router->generate('notification_notification_list_datatables'), |
132 | ]); |
133 | } |
134 | |
135 | public function listDataTables(Request $request): JsonResponse |
136 | { |
137 | $user = $this->userProvider->getAuthenticatedUser(); |
138 | |
139 | $criteria = []; |
140 | |
141 | if (!$this->authorizationChecker->isGranted('ROLE_REFERENT')) { |
142 | $criteria['collectivity'] = new ArrayCollection([$user->getCollectivity(), null]); |
143 | } |
144 | |
145 | if ($user) { |
146 | if (\in_array(UserRoleDictionary::ROLE_REFERENT, $user->getRoles())) { |
147 | $criteria['collectivity'] = $user->getCollectivitesReferees(); |
148 | } |
149 | } |
150 | |
151 | /** @var Paginator $notifications */ |
152 | $notifications = $this->getResults($request, $criteria); |
153 | |
154 | $reponse = $this->getBaseDataTablesResponse($request, $notifications, $criteria); |
155 | |
156 | /** @var Notification $notification */ |
157 | foreach ($notifications as $notification) { |
158 | $read = '<span class="badge bg-green">' . $this->translator->trans('notifications.label.read') . '</span>'; |
159 | $unread = '<span class="badge bg-yellow">' . $this->translator->trans('notifications.label.unread') . '</span>'; |
160 | |
161 | $link = $this->getObjectLink($notification); |
162 | |
163 | $nameHtml = '<span>' . $notification->getName() . '</span> '; |
164 | |
165 | if ($link && 'notification.actions.delete' !== $notification->getAction() && $this->repository->objectExists($notification)) { |
166 | $nameHtml = '<a href="' . $link . '">' . $notification->getName() . '</a>' |
167 | ; |
168 | } |
169 | |
170 | if ($this->authorizationChecker->isGranted('ROLE_REFERENT') || in_array(UserMoreInfoDictionary::MOREINFO_DPD, $user->getMoreInfos())) { |
171 | $reponse['data'][] = [ |
172 | 'state' => $notification->getReadAt() ? $read : $unread, |
173 | 'module' => $this->translator->trans($notification->getModule()), |
174 | 'action' => $this->translator->trans($notification->getAction()), |
175 | 'name' => $nameHtml, |
176 | 'object' => $notification->getSubject(), |
177 | 'collectivity' => $this->authorizationChecker->isGranted('ROLE_REFERENT') && $notification->getCollectivity() ? $notification->getCollectivity()->getName() : '', |
178 | 'date' => date_format($notification->getCreatedAt(), 'd-m-Y H:i'), |
179 | 'user' => $notification->getCreatedBy() ? $notification->getCreatedBy()->__toString() : '', |
180 | 'read_date' => $notification->getReadAt() ? $notification->getReadAt()->format('d-m-Y H:i') : '', |
181 | 'read_by' => $notification->getReadBy() ? $notification->getReadBy()->__toString() : '', |
182 | 'actions' => $this->generateActionCellContent($notification), |
183 | ]; |
184 | } else { |
185 | $notificationUser = $notification->getNotificationUsers()->filter(function (NotificationUser $nu) use ($user) { |
186 | return $nu->getUser() && $nu->getUser()->getId() === $user->getId(); |
187 | })->first(); |
188 | |
189 | $reponse['data'][] = [ |
190 | 'state' => $notificationUser->getReadAt() ? $read : $unread, |
191 | 'module' => $this->translator->trans($notification->getModule()), |
192 | 'action' => $this->translator->trans($notification->getAction()), |
193 | 'name' => $nameHtml, |
194 | 'object' => $notification->getSubject(), |
195 | 'date' => date_format($notification->getCreatedAt(), 'd-m-Y H:i'), |
196 | 'user' => $notification->getCreatedBy() ? $notification->getCreatedBy()->__toString() : '', |
197 | 'actions' => $this->generateActionCellContent($notification), |
198 | ]; |
199 | } |
200 | } |
201 | |
202 | return new JsonResponse($reponse); |
203 | } |
204 | |
205 | private function generateActionCellContent(Notification $notification) |
206 | { |
207 | $id = $notification->getId(); |
208 | |
209 | $user = $this->userProvider->getAuthenticatedUser(); |
210 | $html = ''; |
211 | |
212 | if ( |
213 | in_array('ROLE_ADMIN', $user->getRoles()) || in_array('ROLE_REFERENT', $user->getRoles()) |
214 | || in_array(UserMoreInfoDictionary::MOREINFO_DPD, $user->getMoreInfos()) |
215 | ) { |
216 | if (null === $notification->getReadAt()) { |
217 | $html .= '<a href="' . $this->router->generate('notification_notification_mark_as_read', ['id' => $id]) . '"> |
218 | <i aria-hidden="true" class="fas fa-clipboard-check"></i> |
219 | ' . $this->translator->trans('notifications.action.mark_as_read') . ' |
220 | </a>'; |
221 | } else { |
222 | $html .= ' <a href="' . $this->router->generate('notification_notification_mark_as_unread', ['id' => $id]) . '"> |
223 | <i aria-hidden="true" class="fas fa-clipboard"></i> |
224 | ' . $this->translator->trans('notifications.action.mark_as_unread') . ' |
225 | </a>'; |
226 | } |
227 | } else { |
228 | $notificationUser = $notification->getNotificationUsers()->filter(function (NotificationUser $nu) use ($user) { |
229 | return $nu->getUser() && $nu->getUser()->getId() === $user->getId(); |
230 | })->first(); |
231 | if ($notificationUser && null === $notificationUser->getReadAt()) { |
232 | $html .= '<a href="' . $this->router->generate('notification_notification_mark_as_read', ['id' => $id]) . '"> |
233 | <i aria-hidden="true" class="fas fa-clipboard-check"></i> |
234 | ' . $this->translator->trans('notifications.action.mark_as_read') . ' |
235 | </a>'; |
236 | } else { |
237 | $html .= ' <a href="' . $this->router->generate('notification_notification_mark_as_unread', ['id' => $id]) . '"> |
238 | <i aria-hidden="true" class="fas fa-clipboard"></i> |
239 | ' . $this->translator->trans('notifications.action.mark_as_unread') . ' |
240 | </a>'; |
241 | } |
242 | } |
243 | |
244 | $html .= ' <a href="' . $this->router->generate('notification_notification_delete', ['id' => $id]) . '"> |
245 | <i aria-hidden="true" class="fas fa-trash"></i> |
246 | ' . $this->translator->trans('global.action.delete') . ' |
247 | </a>'; |
248 | |
249 | return $html; |
250 | } |
251 | |
252 | /** |
253 | * {@inheritdoc} |
254 | * Here, we wanna compute maturity score. |
255 | * |
256 | * @param Notification $object |
257 | */ |
258 | public function formPrePersistData($object, $form = null) |
259 | { |
260 | } |
261 | |
262 | /** |
263 | * Update read status from notification. |
264 | */ |
265 | public function markAsReadAllAction(Request $request) |
266 | { |
267 | $notifications = $this->repository->findAll(); |
268 | $user = $this->userProvider->getAuthenticatedUser(); |
269 | foreach ($notifications as $notification) { |
270 | if (is_array($notification)) { |
271 | $notification = $notification[0]; |
272 | } |
273 | if ($notification->getDpo() && (in_array('ROLE_ADMIN', $user->getRoles()) || in_array('ROLE_REFERENT', $user->getRoles()) || in_array(UserMoreInfoDictionary::MOREINFO_DPD, $user->getMoreInfos()))) { |
274 | $notification->setReadAt(new \DateTime()); |
275 | $notification->setReadBy($this->getUser()); |
276 | } else { |
277 | $nu = $notification->getNotificationUsers()->filter(function ($n) use ($user) { |
278 | /* @var Model\NotificationUser $n */ |
279 | return $n->getUser() && $n->getUser()->getId() === $user->getId(); |
280 | })->first(); |
281 | if ($nu) { |
282 | $nu->setReadAt(new \DateTime()); |
283 | } |
284 | } |
285 | } |
286 | |
287 | $this->entityManager->flush(); |
288 | |
289 | $this->addFlash('success', $this->getFlashbagMessage('success', 'markall')); |
290 | |
291 | $referer = $request->headers->get('referer'); |
292 | |
293 | return $this->redirect($referer); |
294 | // return $this->redirectToRoute($this->getRouteName('list')); |
295 | } |
296 | |
297 | /** |
298 | * Update read_at and read_by from notification. |
299 | */ |
300 | public function markAsReadAction(Request $request, string $id) |
301 | { |
302 | $notification = $this->repository->findOneByID($id); |
303 | if (!$notification) { |
304 | throw new NotFoundHttpException('Notification introuvable'); |
305 | } |
306 | |
307 | $user = $this->userProvider->getAuthenticatedUser(); |
308 | |
309 | if ($notification->getDpo() && (in_array('ROLE_ADMIN', $user->getRoles()) || in_array('ROLE_REFERENT', $user->getRoles()) || in_array(UserMoreInfoDictionary::MOREINFO_DPD, $user->getMoreInfos()))) { |
310 | $notification->setReadAt(new \DateTime()); |
311 | $notification->setReadBy($this->getUser()); |
312 | $this->entityManager->flush(); |
313 | } else { |
314 | $nu = $notification->getNotificationUsers()->filter(function ($n) use ($user) { |
315 | /* @var Model\NotificationUser $n */ |
316 | return $n->getUser() && $n->getUser()->getId() === $user->getId(); |
317 | })->first(); |
318 | if ($nu) { |
319 | $nu->setReadAt(new \DateTime()); |
320 | $this->entityManager->flush(); |
321 | } |
322 | } |
323 | |
324 | $referer = $request->headers->get('referer'); |
325 | |
326 | return $this->redirect($referer); |
327 | } |
328 | |
329 | /** |
330 | * Update read_at and read_by from notification to null. |
331 | */ |
332 | public function markAsUnreadAction(Request $request, string $id) |
333 | { |
334 | /** @var Notification $notification */ |
335 | $notification = $this->repository->findOneByID($id); |
336 | if (!$notification) { |
337 | throw new NotFoundHttpException('Notification introuvable'); |
338 | } |
339 | $user = $this->userProvider->getAuthenticatedUser(); |
340 | if ($notification->getDpo() && (in_array('ROLE_ADMIN', $user->getRoles()) || in_array('ROLE_REFERENT', $user->getRoles()) || in_array(UserMoreInfoDictionary::MOREINFO_DPD, $user->getMoreInfos()))) { |
341 | $notification->setReadAt(null); |
342 | $notification->setReadBy(null); |
343 | $this->entityManager->flush(); |
344 | } else { |
345 | $user = $this->userProvider->getAuthenticatedUser(); |
346 | $nu = $notification->getNotificationUsers()->filter(function (NotificationUser $n) use ($user) { |
347 | return $n->getUser() && $n->getUser()->getId() === $user->getId(); |
348 | })->first(); |
349 | if ($nu) { |
350 | $nu->setReadAt(null); |
351 | $this->entityManager->flush(); |
352 | } |
353 | } |
354 | $referer = $request->headers->get('referer'); |
355 | |
356 | return $this->redirect($referer); |
357 | } |
358 | |
359 | protected function getLabelAndKeysArray(): array |
360 | { |
361 | $user = $this->userProvider->getAuthenticatedUser(); |
362 | if ($this->authorizationChecker->isGranted('ROLE_ADMIN') || $this->authorizationChecker->isGranted('ROLE_REFERENT') || in_array(UserMoreInfoDictionary::MOREINFO_DPD, $user->getMoreInfos())) { |
363 | return [ |
364 | 'state', |
365 | 'module', |
366 | 'action', |
367 | 'name', |
368 | 'object', |
369 | 'collectivity', |
370 | 'date', |
371 | 'user', |
372 | 'read_date', |
373 | 'read_by', |
374 | ]; |
375 | } |
376 | |
377 | return [ |
378 | 'state', |
379 | 'module', |
380 | 'action', |
381 | 'name', |
382 | 'object', |
383 | 'date', |
384 | 'user', |
385 | ]; |
386 | } |
387 | |
388 | private function getObjectLink(Notification $notification): string |
389 | { |
390 | try { |
391 | if ('notification.modules.aipd' === $notification->getModule() && 'notification.actions.validation' === $notification->getAction()) { |
392 | return $this->router->generate('aipd_analyse_impact_validation', ['id' => $notification->getObject()->id], UrlGeneratorInterface::ABSOLUTE_URL); |
393 | } |
394 | if ('notification.modules.aipd' === $notification->getModule() && 'notification.actions.state_change' === $notification->getAction()) { |
395 | return $this->router->generate('aipd_analyse_impact_evaluation', ['id' => $notification->getObject()->id], UrlGeneratorInterface::ABSOLUTE_URL); |
396 | } |
397 | if ('notification.modules.aipd' === $notification->getModule() && 'notification.actions.validated' === $notification->getAction()) { |
398 | /** @var \App\Domain\AIPD\Model\AnalyseImpact $aipd */ |
399 | $aipd = $this->aipdRepository->findOneById($notification->getObject()->id); |
400 | if ($aipd) { |
401 | return $this->router->generate('registry_treatment_show', ['id' => $aipd->getConformiteTraitement()->getTraitement()->getId()->toString()], UrlGeneratorInterface::ABSOLUTE_URL); |
402 | } |
403 | |
404 | return ''; |
405 | } |
406 | if ('notification.modules.aipd' === $notification->getModule() && 'notifications.actions.treatment_needs_aipd' === $notification->getAction()) { |
407 | return $this->router->generate('registry_conformite_traitement_start_aipd', ['id' => $notification->getObject()->id], UrlGeneratorInterface::ABSOLUTE_URL); |
408 | } |
409 | if ('notification.modules.document' === $notification->getModule() && 'notification.actions.delete' !== $notification->getAction()) { |
410 | return $notification->getObject()->url; |
411 | } |
412 | if ('notification.modules.action_plan' === $notification->getModule()) { |
413 | return $this->router->generate('registry_mesurement_show', ['id' => $notification->getObject()->id], UrlGeneratorInterface::ABSOLUTE_URL); |
414 | } |
415 | |
416 | return $this->router->generate($this->getRouteForModule($notification->getModule()), ['id' => $notification->getObject()->id], UrlGeneratorInterface::ABSOLUTE_URL); |
417 | } catch (\Exception $e) { |
418 | return ''; |
419 | } |
420 | } |
421 | |
422 | public function deleteConfirmationAction(string $id): Response |
423 | { |
424 | /** @var Notification $notification */ |
425 | $notification = $this->repository->findOneById($id); |
426 | if (!$notification) { |
427 | throw new NotFoundHttpException("No object found with ID '{$id}'"); |
428 | } |
429 | if ($notification->getDpo()) { |
430 | $this->entityManager->remove($notification); |
431 | $this->entityManager->flush(); |
432 | } else { |
433 | $user = $this->userProvider->getAuthenticatedUser(); |
434 | $nu = $notification->getNotificationUsers()->filter(function ($n) use ($user) { |
435 | /* @var Model\NotificationUser $n */ |
436 | return $n->getUser()->getId() === $user->getId(); |
437 | })->first(); |
438 | if ($nu) { |
439 | $this->entityManager->remove($nu); |
440 | $this->entityManager->flush(); |
441 | } |
442 | } |
443 | |
444 | $this->addFlash('success', $this->getFlashbagMessage('success', 'delete', $notification)); |
445 | |
446 | return $this->redirectToRoute($this->getRouteName('list')); |
447 | } |
448 | |
449 | private function getRouteForModule($module): string |
450 | { |
451 | switch ($module) { |
452 | case 'notification.modules.treatment': |
453 | return 'registry_treatment_show'; |
454 | case 'notification.modules.subcontractor': |
455 | case 'notification.modules.contractor': |
456 | return 'registry_contractor_show'; |
457 | case 'notification.modules.violation': |
458 | return 'registry_violation_show'; |
459 | case 'notification.modules.proof': |
460 | return 'registry_proof_edit'; |
461 | case 'notification.modules.protect_action': |
462 | return 'registry_mesurement_show'; |
463 | case 'notification.modules.request': |
464 | return 'registry_request_show'; |
465 | case 'notification.modules.user': |
466 | return 'user_user_edit'; |
467 | case 'notification.modules.documentation': |
468 | case 'notification.modules.document': |
469 | return 'documentation_document_download'; |
470 | case 'notification.modules.maturity': |
471 | return 'maturity_survey_edit'; |
472 | } |
473 | |
474 | return ''; |
475 | } |
476 | } |