chill-bundles/src/Bundle/ChillMainBundle/Controller/NotificationApiController.php

98 lines
3.7 KiB
PHP

<?php
declare(strict_types=1);
/*
* 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.
*/
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 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;
#[Route(path: '/api/1.0/main/notification')]
class NotificationApiController
{
public function __construct(private readonly EntityManagerInterface $entityManager, private readonly NotificationRepository $notificationRepository, private readonly PaginatorFactory $paginatorFactory, private readonly Security $security, private readonly SerializerInterface $serializer) {}
#[Route(path: '/{id}/mark/read', name: 'chill_api_main_notification_mark_read', methods: ['POST'])]
public function markAsRead(Notification $notification): JsonResponse
{
return $this->markAs('read', $notification);
}
#[Route(path: '/{id}/mark/unread', name: 'chill_api_main_notification_mark_unread', methods: ['POST'])]
public function markAsUnread(Notification $notification): JsonResponse
{
return $this->markAs('unread', $notification);
}
#[Route(path: '/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');
}
match ($target) {
'read' => $notification->markAsReadBy($user),
'unread' => $notification->markAsUnreadBy($user),
default => throw new \UnexpectedValueException("target not supported: {$target}"),
};
$this->entityManager->flush();
return new JsonResponse(null, JsonResponse::HTTP_ACCEPTED, [], false);
}
}