chill-bundles/src/Bundle/ChillMainBundle/Controller/NotificationApiController.php
2022-01-27 17:28:59 +01:00

139 lines
4.3 KiB
PHP

<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\MainBundle\Controller;
use Chill\MainBundle\Entity\Notification;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Pagination\PaginatorFactory;
use Chill\MainBundle\Repository\NotificationRepository;
use Chill\MainBundle\Security\Authorization\NotificationVoter;
use Chill\MainBundle\Serializer\Model\Collection;
use Chill\MainBundle\Serializer\Model\Counter;
use Doctrine\ORM\EntityManagerInterface;
use RuntimeException;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Serializer\SerializerInterface;
use UnexpectedValueException;
/**
* @Route("/api/1.0/main/notification")
*/
class NotificationApiController
{
private EntityManagerInterface $entityManager;
private NotificationRepository $notificationRepository;
private PaginatorFactory $paginatorFactory;
private Security $security;
private SerializerInterface $serializer;
public function __construct(
EntityManagerInterface $entityManager,
NotificationRepository $notificationRepository,
PaginatorFactory $paginatorFactory,
Security $security,
SerializerInterface $serializer
) {
$this->entityManager = $entityManager;
$this->notificationRepository = $notificationRepository;
$this->paginatorFactory = $paginatorFactory;
$this->security = $security;
$this->serializer = $serializer;
}
/**
* @Route("/{id}/mark/read", name="chill_api_main_notification_mark_read", methods={"POST"})
*/
public function markAsRead(Notification $notification): JsonResponse
{
return $this->markAs('read', $notification);
}
/**
* @Route("/{id}/mark/unread", name="chill_api_main_notification_mark_unread", methods={"POST"})
*/
public function markAsUnread(Notification $notification): JsonResponse
{
return $this->markAs('unread', $notification);
}
/**
* @Route("/my/unread")
*/
public function myUnreadNotifications(Request $request): JsonResponse
{
$total = $this->notificationRepository->countUnreadByUser($this->security->getUser());
if ($request->query->getBoolean('countOnly')) {
return new JsonResponse(
$this->serializer->serialize(new Counter($total), 'json', ['groups' => ['read']]),
JsonResponse::HTTP_OK,
[],
true
);
}
$paginator = $this->paginatorFactory->create($total);
$notifications = $this->notificationRepository->findUnreadByUser(
$this->security->getUser(),
$paginator->getItemsPerPage(),
$paginator->getCurrentPageFirstItemNumber()
);
$collection = new Collection($notifications, $paginator);
return new JsonResponse(
$this->serializer->serialize($collection, 'json', ['groups' => ['read']]),
JsonResponse::HTTP_OK,
[],
true
);
}
private function markAs(string $target, Notification $notification): JsonResponse
{
if (!$this->security->isGranted(NotificationVoter::NOTIFICATION_TOGGLE_READ_STATUS, $notification)) {
throw new AccessDeniedException('Not allowed to toggle read status of notification');
}
$user = $this->security->getUser();
if (!$user instanceof User) {
throw new RuntimeException('not possible to mark as read by this user');
}
switch ($target) {
case 'read':
$notification->markAsReadBy($user);
break;
case 'unread':
$notification->markAsUnreadBy($user);
break;
default:
throw new UnexpectedValueException("target not supported: {$target}");
}
$this->entityManager->flush();
return new JsonResponse(null, JsonResponse::HTTP_ACCEPTED, [], false);
}
}