diff --git a/src/Bundle/ChillMainBundle/Controller/NotificationApiController.php b/src/Bundle/ChillMainBundle/Controller/NotificationApiController.php index 8751aa50a..c50564d58 100644 --- a/src/Bundle/ChillMainBundle/Controller/NotificationApiController.php +++ b/src/Bundle/ChillMainBundle/Controller/NotificationApiController.php @@ -13,13 +13,17 @@ 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 Doctrine\ORM\EntityManagerInterface; use RuntimeException; use Symfony\Component\HttpFoundation\JsonResponse; 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; /** @@ -29,12 +33,26 @@ class NotificationApiController { private EntityManagerInterface $entityManager; + private NotificationRepository $notificationRepository; + + private PaginatorFactory $paginatorFactory; + private Security $security; - public function __construct(EntityManagerInterface $entityManager, 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; } /** @@ -53,6 +71,29 @@ class NotificationApiController return $this->markAs('unread', $notification); } + /** + * @Route("/my/unread") + */ + public function myUnreadNotifications(): JsonResponse + { + $total = $this->notificationRepository->countUnreadByUser($this->security->getUser()); + $paginator = $this->paginatorFactory->create($total); + $notifications = $this->notificationRepository->findUnreadByUser( + $this->security->getUser(), + $paginator->getItemsPerPage(), + $paginator->getCurrentPageFirstItemNumber() + ); + dump($notifications); + $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)) { diff --git a/src/Bundle/ChillMainBundle/Repository/NotificationRepository.php b/src/Bundle/ChillMainBundle/Repository/NotificationRepository.php index 35ec64114..1580cfa6a 100644 --- a/src/Bundle/ChillMainBundle/Repository/NotificationRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/NotificationRepository.php @@ -179,6 +179,29 @@ final class NotificationRepository implements ObjectRepository return $this->repository->findOneBy($criteria, $orderBy); } + /** + * @return array|Notification[] + */ + public function findUnreadByUser(User $user, int $limit = 20, int $offset = 0): array + { + $rsm = new Query\ResultSetMappingBuilder($this->em); + $rsm->addRootEntityFromClassMetadata(Notification::class, 'cmn'); + + $sql = 'SELECT ' . $rsm->generateSelectClause(['cmn' => 'cmn']) . ' ' . + 'FROM chill_main_notification cmn ' . + 'WHERE ' . + 'EXISTS (select 1 FROM chill_main_notification_addresses_unread cmnau WHERE cmnau.user_id = :userId and cmnau.notification_id = cmn.id) ' . + 'ORDER BY cmn.date DESC ' . + 'LIMIT :limit OFFSET :offset'; + + $nq = $this->em->createNativeQuery($sql, $rsm) + ->setParameter('userId', $user->getId()) + ->setParameter('limit', $limit) + ->setParameter('offset', $offset); + + return $nq->getResult(); + } + public function getClassName() { return Notification::class; diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/NotificationNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/NotificationNormalizer.php new file mode 100644 index 000000000..89f2285f2 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/NotificationNormalizer.php @@ -0,0 +1,70 @@ +notificationHandlerManager = $notificationHandlerManager; + $this->entityManager = $entityManager; + $this->security = $security; + } + + /** + * @param Notification $object + * + * @return array|ArrayObject|bool|float|int|string|void|null + */ + public function normalize($object, ?string $format = null, array $context = []) + { + dump($object); + $entity = $this->entityManager + ->getRepository($object->getRelatedEntityClass()) + ->find($object->getRelatedEntityId()); + + return [ + 'type' => 'notification', + 'addressees' => $this->normalizer->normalize($object->getAddressees(), $format, $context), + 'date' => $this->normalizer->normalize($object->getDate(), $format, $context), + 'isRead' => $object->isReadBy($this->security->getUser()), + 'message' => $object->getMessage(), + 'relatedEntityClass' => $object->getRelatedEntityClass(), + 'relatedEntityId' => $object->getRelatedEntityId(), + 'sender' => $this->normalizer->normalize($object->getSender(), $format, $context), + 'title' => $object->getTitle(), + 'entity' => null !== $entity ? $this->normalizer->normalize($entity, $format, $context) : null, + ]; + } + + public function supportsNormalization($data, ?string $format = null) + { + return $data instanceof Notification && 'json' === $format; + } +}