<?php
namespace App\Controller\Front;
use App\Entity\Notification;
use App\Entity\NotificationStatistics;
use App\Repository\App\NotificationRepository;
use App\Repository\App\NotificationStatisticsRepository;
use App\Security\RoleInterface;
use App\Traits\DonneeCompteClientAvailableTrait;
use DateTime;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\RequestStack;
class NotificationsController extends AbstractController
{
/**
* Injecte DonneeCompteClientManager dans le controlleur
* Ajoute automatiquement la variable donneeCompteClient aux paramètres de la méthode render
*/
use DonneeCompteClientAvailableTrait;
/** @var NotificationRepository */
protected NotificationRepository $notificationRepository;
/** @var NotificationStatisticsRepository */
protected NotificationStatisticsRepository $notificationStatisticsRepository;
protected $session;
/** @var EntityManagerInterface */
protected EntityManagerInterface $em;
/** @var RequestStack */
protected RequestStack $requestStack;
public function __construct(
NotificationRepository $notificationRepository,
NotificationStatisticsRepository $notificationStatisticsRepository,
RequestStack $requestStack,
EntityManagerInterface $em,
)
{
$this->notificationRepository = $notificationRepository;
$this->notificationStatisticsRepository = $notificationStatisticsRepository;
$this->requestStack = $requestStack;
$this->session = $this->requestStack->getSession();
$this->em = $em;
}
/**
* Returns the number of unread notifications by the user
*
* @return JsonResponse
* @Route("/notifications/counter", name="notification_counter")
*/
public function getUnreadNotificationCounter(): JsonResponse
{
$counter = $this->notificationRepository->countUnreadByUser($this->getUser());
if (is_numeric($counter)) {
return new JsonResponse([
'status' => 'success',
'message' => 'Success',
'data' => ['count' => $counter]
],
Response::HTTP_OK
);
}
return new JsonResponse([
'status' => 'error',
'message' => 'No data given'
],
Response::HTTP_BAD_REQUEST
);
}
/**
* Returns an array of unread notifications by the user
* Used in ajax menu update
*
* @param Request $request
* @return JsonResponse
* @Route("/notifications/notread", name="notification_unread")
*/
public function getUnreadNotificationsForMenu(Request $request): JsonResponse
{
$notifications = $request->get('notifications', []);
$notifications = $this->notificationRepository->findUnreadByUserWithoutGivenArray($this->getUser(), $notifications);
if (is_array($notifications)) {
return new JsonResponse([
'status' => 'success',
'message' => 'Success',
'data' => ['notifications' => $notifications]
],
Response::HTTP_OK
);
}
return new JsonResponse([
'status' => 'error',
'message' => 'No data given'
],
Response::HTTP_BAD_REQUEST
);
}
/**
* @param Notification $notification
* @return JsonResponse
*
* @Route(path="/notifications/read/{notification}")
*/
public function markAsRead(Notification $notification): JsonResponse
{
if ($this->isGranted(RoleInterface::ROLE_PREVIOUS_ADMIN)) {
return new JsonResponse([
'status' => 'error',
'message' => 'Interdit pour cet utilisateur',
], Response::HTTP_UNAUTHORIZED);
}
try {
$statistics = $this->_findStatistic($notification);
$statistics->setLastSeenDate(new DateTime());
$statistics->setReadLater(false);
// increase count read for notification popup
if($notification->getSetPopUp()){
$statistics->incrementCountRead();
}
$this->em->flush();
return new JsonResponse(null, Response::HTTP_OK);
} catch (\Exception $e) {
return new JsonResponse([
'status' => 'error',
'message' => $e->getMessage(),
], Response::HTTP_BAD_REQUEST);
}
}
/**
* @param Notification $notification
* @return NotificationStatistics|null
* @throws \Exception
*/
public function _findStatistic(Notification $notification): ?NotificationStatistics
{
if (!$statistics = $this->notificationStatisticsRepository->findOneBy([
'customerNumber' => $this->getUser()->getCustomerNumber(),
'notification' => $notification
])) {
throw new \Exception('No valid statistic');
}
return $statistics;
}
/**
* Returns the view of all the notifications addressed to the user.
* NB: The ID is used in Javascript to scroll to the selected notification if set
*
* @param int|null $id
* @return Response
*
* @Route("/notifications/{id}", name="notifications_list")
*/
public function list(int $id = null): Response
{
$user = $this->getUser();
return $this->render('front/notifications/list.html.twig', [
'notifications' => $this->notificationRepository->findActiveNotificationsByUser($user),
]);
}
/**
* Show the list of notifications in the menu
* @param Request $request
* @param int $max
* @return Response
*/
public function menu(Request $request): Response
{
$user = $this->getUser();
return $this->render('front/notifications/menu.html.twig', [
'notifications' => $this->notificationRepository->findActiveNotificationsByUser($user, true),
'active_route' => $request->get('active_route')
]);
}
/**
* Returns all the popups not displayed yet
*
* @return Response
*/
public function getPopup(): Response
{
$user = $this->getUser();
$seenPopUps = $this->session->get('seenPopUps', []);
return $this->render('front/notifications/popup.html.twig', [
'notifications' => $this->notificationRepository->findPopUpNotificationsByUser($user, $seenPopUps)
]);
}
/**
* Store the answer to a notification
*
* @param Notification $notification
* @param Request $request
* @return JsonResponse
*
* @Route("notifications/input/{id}", name="notification_store_userInput")
*/
public function storeNotificationUserInput(Notification $notification, Request $request): JsonResponse
{
if ($this->isGranted(RoleInterface::ROLE_PREVIOUS_ADMIN)) {
return new JsonResponse([
'status' => 'error',
'message' => 'Interdit pour cet utilisateur',
], Response::HTTP_UNAUTHORIZED);
}
$answer = $request->get('answer');
try {
$statistics = $this->_findStatistic($notification);
$this->_checkIfAnswerIsValid($notification, $answer);
} catch (\Exception $e) {
return new JsonResponse([
'status' => 'error',
'message' => $e->getMessage(),
], Response::HTTP_BAD_REQUEST);
}
if ($notification->getRequiredCheckboxToggle()) {
$statistics->setCheckboxIsChecked($answer['userAgreement'] === 'true');
}
$statistics->setAnswer($answer['choice'] === NotificationStatistics::ANSWER_ACCEPTED);
$this->em->flush();
return new JsonResponse([
'status' => 'success',
'message' => 'Success',
'answer' => $statistics->getAnswer()
],
Response::HTTP_OK
);
}
/**
* @param Notification $notification
* @param $answer
* @throws \Exception
*/
public function _checkIfAnswerIsValid(Notification $notification, $answer): void
{
$choice = $answer['choice'];
// Throws an error if the answer is not one of the options
if (!in_array($choice, [NotificationStatistics::ANSWER_REFUSED, NotificationStatistics::ANSWER_ACCEPTED])) {
throw new \Exception('La réponse n\'est pas valide');
}
if ((!isset($answer['userAgreement']) || $answer['userAgreement'] === 'false') && $notification->getRequiredCheckboxToggle()) {
throw new \Exception('La réponse n\'est pas valide');
}
}
/**
* @param Notification $notification
* @return JsonResponse
*
* @Route("/notifications/popup/readLater/{notification}", name="notifications_popup_readLater")
*/
public function setReadLaterPopUp(Notification $notification): JsonResponse
{
if ($this->isGranted(RoleInterface::ROLE_PREVIOUS_ADMIN)) {
return new JsonResponse([
'status' => 'error',
'message' => 'Interdit pour cet utilisateur',
], Response::HTTP_UNAUTHORIZED);
}
$stat = $this->notificationStatisticsRepository->findOneBy([
'notification' => $notification,
'customerNumber' => $this->getUser()->getCustomerNumber()
]);
if (!$stat) {
return new JsonResponse(['error' => 'not found'], 404);
}
$this->_saveSeenPopUpToSession($notification);
$stat->setReadLater(true);
$this->em->flush();
return new JsonResponse([
'status' => 'success',
'message' => 'Success'
],
Response::HTTP_OK
);
}
/**
* @param Notification $notification
*/
private function _saveSeenPopUpToSession(Notification $notification): void
{
$seenPopUps = $this->session->get('seenPopUps', []);
$id = $notification->getId();
if (!in_array($id, $seenPopUps)) {
$seenPopUps[] = $id;
}
$this->session->set('seenPopUps', $seenPopUps);
}
/**
* Save popup as unread in session, increment insistence coefficient
*
* @param Notification $notification
* @return JsonResponse
*
* @Route("/notifications/popup/closed/{notification}", name="notifications_popup_closed")
*/
public function setClosedPopUp(Notification $notification): JsonResponse
{
$this->_saveSeenPopUpToSession($notification);
if ($this->isGranted(RoleInterface::ROLE_PREVIOUS_ADMIN)) {
return new JsonResponse([
'status' => 'success',
'message' => 'success',
], Response::HTTP_OK);
}
return new JsonResponse([
'status' => 'success',
'message' => 'Success'
],
Response::HTTP_OK
);
}
}