mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Notification: fix counter, and allow to add more related entity in a single query
Sometimes, there are entities which embed other entities, which in turn have notification. This more parameter allow to fetch notification and counter for those embedded entities in a single query.
This commit is contained in:
parent
cb4de1f3d2
commit
3879e5cd9b
@ -34,9 +34,13 @@ class NotificationPresence
|
|||||||
$this->notificationRepository = $notificationRepository;
|
$this->notificationRepository = $notificationRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function countNotificationsForClassAndEntity(string $relatedEntityClass, int $relatedEntityId): array
|
/**
|
||||||
|
* @param list<array{relatedEntityClass: class-string, relatedEntityId: int}> $more
|
||||||
|
* @return array{unread: int, sent: int, total: int}
|
||||||
|
*/
|
||||||
|
public function countNotificationsForClassAndEntity(string $relatedEntityClass, int $relatedEntityId, array $more = [], array $options = []): array
|
||||||
{
|
{
|
||||||
if (array_key_exists($relatedEntityClass, $this->cache) && array_key_exists($relatedEntityId, $this->cache[$relatedEntityClass])) {
|
if ([] === $more && array_key_exists($relatedEntityClass, $this->cache) && array_key_exists($relatedEntityId, $this->cache[$relatedEntityClass])) {
|
||||||
return $this->cache[$relatedEntityClass][$relatedEntityId];
|
return $this->cache[$relatedEntityClass][$relatedEntityId];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,21 +50,25 @@ class NotificationPresence
|
|||||||
$counter = $this->notificationRepository->countNotificationByRelatedEntityAndUserAssociated(
|
$counter = $this->notificationRepository->countNotificationByRelatedEntityAndUserAssociated(
|
||||||
$relatedEntityClass,
|
$relatedEntityClass,
|
||||||
$relatedEntityId,
|
$relatedEntityId,
|
||||||
$user
|
$user,
|
||||||
|
$more
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ([] === $more) {
|
||||||
$this->cache[$relatedEntityClass][$relatedEntityId] = $counter;
|
$this->cache[$relatedEntityClass][$relatedEntityId] = $counter;
|
||||||
|
}
|
||||||
|
|
||||||
return $counter;
|
return $counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ['unread' => 0, 'read' => 0];
|
return ['unread' => 0, 'sent' => 0, 'total' => 0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param list<array{relatedEntityClass: class-string, relatedEntityId: int}> $more
|
||||||
* @return array|Notification[]
|
* @return array|Notification[]
|
||||||
*/
|
*/
|
||||||
public function getNotificationsForClassAndEntity(string $relatedEntityClass, int $relatedEntityId): array
|
public function getNotificationsForClassAndEntity(string $relatedEntityClass, int $relatedEntityId, array $more = []): array
|
||||||
{
|
{
|
||||||
$user = $this->security->getUser();
|
$user = $this->security->getUser();
|
||||||
|
|
||||||
@ -68,7 +76,8 @@ class NotificationPresence
|
|||||||
return $this->notificationRepository->findNotificationByRelatedEntityAndUserAssociated(
|
return $this->notificationRepository->findNotificationByRelatedEntityAndUserAssociated(
|
||||||
$relatedEntityClass,
|
$relatedEntityClass,
|
||||||
$relatedEntityId,
|
$relatedEntityId,
|
||||||
$user
|
$user,
|
||||||
|
$more
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,24 +34,30 @@ class NotificationTwigExtensionRuntime implements RuntimeExtensionInterface
|
|||||||
$this->urlGenerator = $urlGenerator;
|
$this->urlGenerator = $urlGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function counterNotificationFor(Environment $environment, string $relatedEntityClass, int $relatedEntityId, array $options = []): string
|
public function counterNotificationFor(Environment $environment, string $relatedEntityClass, int $relatedEntityId, array $more = [], array $options = []): string
|
||||||
{
|
{
|
||||||
return $environment->render(
|
return $environment->render(
|
||||||
'@ChillMain/Notification/extension_counter_notifications_for.html.twig',
|
'@ChillMain/Notification/extension_counter_notifications_for.html.twig',
|
||||||
[
|
[
|
||||||
'counter' => $this->notificationPresence->countNotificationsForClassAndEntity($relatedEntityClass, $relatedEntityId),
|
'counter' => $this->notificationPresence->countNotificationsForClassAndEntity($relatedEntityClass, $relatedEntityId, $more),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function countNotificationsFor(string $relatedEntityClass, int $relatedEntityId, array $options = []): array
|
/**
|
||||||
|
* @param list<array{relatedEntityClass: class-string, relatedEntityId: int}> $more
|
||||||
|
*/
|
||||||
|
public function countNotificationsFor(string $relatedEntityClass, int $relatedEntityId, array $more = [], array $options = []): array
|
||||||
{
|
{
|
||||||
return $this->notificationPresence->countNotificationsForClassAndEntity($relatedEntityClass, $relatedEntityId);
|
return $this->notificationPresence->countNotificationsForClassAndEntity($relatedEntityClass, $relatedEntityId, $more);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function listNotificationsFor(Environment $environment, string $relatedEntityClass, int $relatedEntityId, array $options = []): string
|
/**
|
||||||
|
* @param list<array{relatedEntityClass: class-string, relatedEntityId: int}> $more
|
||||||
|
*/
|
||||||
|
public function listNotificationsFor(Environment $environment, string $relatedEntityClass, int $relatedEntityId, array $more = [], array $options = []): string
|
||||||
{
|
{
|
||||||
$notifications = $this->notificationPresence->getNotificationsForClassAndEntity($relatedEntityClass, $relatedEntityId);
|
$notifications = $this->notificationPresence->getNotificationsForClassAndEntity($relatedEntityClass, $relatedEntityId, $more);
|
||||||
|
|
||||||
if ([] === $notifications) {
|
if ([] === $notifications) {
|
||||||
return '';
|
return '';
|
||||||
|
@ -29,6 +29,15 @@ final class NotificationRepository implements ObjectRepository
|
|||||||
|
|
||||||
private EntityRepository $repository;
|
private EntityRepository $repository;
|
||||||
|
|
||||||
|
private const BASE_COUNTER_SQL = <<<'SQL'
|
||||||
|
SELECT
|
||||||
|
SUM((EXISTS (SELECT 1 AS c FROM chill_main_notification_addresses_unread cmnau WHERE user_id = :userid and cmnau.notification_id = cmn.id))::int) AS unread,
|
||||||
|
SUM((cmn.sender_id = :userid)::int) AS sent,
|
||||||
|
SUM((EXISTS (SELECT 1 AS c FROM chill_main_notification_addresses_user cmnau_all WHERE user_id = :userid and cmnau_all.notification_id = cmn.id))::int) + SUM((cmn.sender_id = :userid)::int) AS total
|
||||||
|
FROM chill_main_notification cmn
|
||||||
|
SQL;
|
||||||
|
|
||||||
|
|
||||||
public function __construct(EntityManagerInterface $entityManager)
|
public function __construct(EntityManagerInterface $entityManager)
|
||||||
{
|
{
|
||||||
$this->em = $entityManager;
|
$this->em = $entityManager;
|
||||||
@ -51,29 +60,45 @@ final class NotificationRepository implements ObjectRepository
|
|||||||
->getSingleScalarResult();
|
->getSingleScalarResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function countNotificationByRelatedEntityAndUserAssociated(string $relatedEntityClass, int $relatedEntityId, User $user): array
|
/**
|
||||||
|
* @param list<array{relatedEntityClass: class-string, relatedEntityId: int}> $more
|
||||||
|
* @return array{unread: int, sent: int, total: int}
|
||||||
|
*/
|
||||||
|
public function countNotificationByRelatedEntityAndUserAssociated(string $relatedEntityClass, int $relatedEntityId, User $user, array $more = []): array
|
||||||
{
|
{
|
||||||
|
$sqlParams = ['relatedEntityClass' => $relatedEntityClass, 'relatedEntityId' => $relatedEntityId, 'userid' => $user->getId()];
|
||||||
|
|
||||||
|
if ([] === $more) {
|
||||||
if (null === $this->notificationByRelatedEntityAndUserAssociatedStatement) {
|
if (null === $this->notificationByRelatedEntityAndUserAssociatedStatement) {
|
||||||
$sql =
|
$sql = self::BASE_COUNTER_SQL . ' WHERE relatedentityclass = :relatedEntityClass AND relatedentityid = :relatedEntityId AND sender_id IS NOT NULL';
|
||||||
'SELECT
|
|
||||||
SUM((EXISTS (SELECT 1 AS c FROM chill_main_notification_addresses_unread cmnau WHERE user_id = :userid and cmnau.notification_id = cmn.id))::int) AS unread,
|
|
||||||
SUM((cmn.sender_id = :userid)::int) AS sent,
|
|
||||||
COUNT(cmn.*) AS total
|
|
||||||
FROM chill_main_notification cmn
|
|
||||||
WHERE relatedentityclass = :relatedEntityClass AND relatedentityid = :relatedEntityId AND sender_id IS NOT NULL';
|
|
||||||
|
|
||||||
$this->notificationByRelatedEntityAndUserAssociatedStatement =
|
$this->notificationByRelatedEntityAndUserAssociatedStatement =
|
||||||
$this->em->getConnection()->prepare($sql);
|
$this->em->getConnection()->prepare($sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
$results = $this->notificationByRelatedEntityAndUserAssociatedStatement
|
$results = $this->notificationByRelatedEntityAndUserAssociatedStatement
|
||||||
->executeQuery(['relatedEntityClass' => $relatedEntityClass, 'relatedEntityId' => $relatedEntityId, 'userid' => $user->getId()]);
|
->executeQuery($sqlParams);
|
||||||
|
|
||||||
$result = $results->fetchAssociative();
|
$result = $results->fetchAssociative();
|
||||||
|
|
||||||
$results->free();
|
$results->free();
|
||||||
|
} else {
|
||||||
|
$wheres = [];
|
||||||
|
foreach ([
|
||||||
|
['relatedEntityClass' => $relatedEntityClass, 'relatedEntityId' => $relatedEntityId],
|
||||||
|
...$more
|
||||||
|
] as $k => ['relatedEntityClass' => $relClass, 'relatedEntityId' => $relId]) {
|
||||||
|
$wheres[] = "(relatedEntityClass = :relatedEntityClass_{$k} AND relatedEntityId = :relatedEntityId_{$k})";
|
||||||
|
$sqlParams["relatedEntityClass_{$k}"] = $relClass;
|
||||||
|
$sqlParams["relatedEntityId_{$k}"] = $relId;
|
||||||
|
}
|
||||||
|
|
||||||
return $result;
|
$sql = self::BASE_COUNTER_SQL . ' WHERE sender_id IS NOT NULL AND (' . implode(' OR ', $wheres) . ')';
|
||||||
|
|
||||||
|
$result = $this->em->getConnection()->fetchAssociative($sql, $sqlParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_map(fn (?int $number) => $number ?? 0, $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function countUnreadByUser(User $user): int
|
public function countUnreadByUser(User $user): int
|
||||||
@ -167,8 +192,8 @@ final class NotificationRepository implements ObjectRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mixed|null $limit
|
* @param int|null $limit
|
||||||
* @param mixed|null $offset
|
* @param int|null $offset
|
||||||
*
|
*
|
||||||
* @return Notification[]
|
* @return Notification[]
|
||||||
*/
|
*/
|
||||||
@ -178,13 +203,15 @@ final class NotificationRepository implements ObjectRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param list<array{relatedEntityClass: class-string, relatedEntityId: int}> $more
|
||||||
* @return array|Notification[]
|
* @return array|Notification[]
|
||||||
*/
|
*/
|
||||||
public function findNotificationByRelatedEntityAndUserAssociated(string $relatedEntityClass, int $relatedEntityId, User $user): array
|
public function findNotificationByRelatedEntityAndUserAssociated(string $relatedEntityClass, int $relatedEntityId, User $user, array $more): array
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
$this->buildQueryNotificationByRelatedEntityAndUserAssociated($relatedEntityClass, $relatedEntityId, $user)
|
$this->buildQueryNotificationByRelatedEntityAndUserAssociated($relatedEntityClass, $relatedEntityId, $user, $more)
|
||||||
->select('n')
|
->select('n')
|
||||||
|
->addOrderBy('n.date', 'DESC')
|
||||||
->getQuery()
|
->getQuery()
|
||||||
->getResult();
|
->getResult();
|
||||||
}
|
}
|
||||||
@ -222,13 +249,36 @@ final class NotificationRepository implements ObjectRepository
|
|||||||
return Notification::class;
|
return Notification::class;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildQueryNotificationByRelatedEntityAndUserAssociated(string $relatedEntityClass, int $relatedEntityId, User $user): QueryBuilder
|
/**
|
||||||
|
* @param list<array{relatedEntityClass: class-string, relatedEntityId: int}> $more
|
||||||
|
*/
|
||||||
|
private function buildQueryNotificationByRelatedEntityAndUserAssociated(string $relatedEntityClass, int $relatedEntityId, User $user, array $more = []): QueryBuilder
|
||||||
{
|
{
|
||||||
$qb = $this->repository->createQueryBuilder('n');
|
$qb = $this->repository->createQueryBuilder('n');
|
||||||
|
|
||||||
|
// add condition for related entity (in main arguments, and in more)
|
||||||
|
$or = $qb->expr()->orX($qb->expr()->andX(
|
||||||
|
$qb->expr()->eq('n.relatedEntityClass', ':relatedEntityClass'),
|
||||||
|
$qb->expr()->eq('n.relatedEntityId', ':relatedEntityId')
|
||||||
|
));
|
||||||
$qb
|
$qb
|
||||||
->where($qb->expr()->eq('n.relatedEntityClass', ':relatedEntityClass'))
|
->setParameter('relatedEntityClass', $relatedEntityClass)
|
||||||
->andWhere($qb->expr()->eq('n.relatedEntityId', ':relatedEntityId'))
|
->setParameter('relatedEntityId', $relatedEntityId);
|
||||||
|
|
||||||
|
foreach ($more as $k => ['relatedEntityClass' => $relatedClass, 'relatedEntityId' => $relatedId]) {
|
||||||
|
$or->add(
|
||||||
|
$qb->expr()->andX(
|
||||||
|
$qb->expr()->eq('n.relatedEntityClass', ':relatedEntityClass_'.$k),
|
||||||
|
$qb->expr()->eq('n.relatedEntityId', ':relatedEntityId_'.$k)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$qb
|
||||||
|
->setParameter('relatedEntityClass_'.$k, $relatedClass)
|
||||||
|
->setParameter('relatedEntityId_'.$k, $relatedId);
|
||||||
|
}
|
||||||
|
|
||||||
|
$qb
|
||||||
|
->andWhere($or)
|
||||||
->andWhere($qb->expr()->isNotNull('n.sender'))
|
->andWhere($qb->expr()->isNotNull('n.sender'))
|
||||||
->andWhere(
|
->andWhere(
|
||||||
$qb->expr()->orX(
|
$qb->expr()->orX(
|
||||||
@ -236,8 +286,6 @@ final class NotificationRepository implements ObjectRepository
|
|||||||
$qb->expr()->eq('n.sender', ':user')
|
$qb->expr()->eq('n.sender', ':user')
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
->setParameter('relatedEntityClass', $relatedEntityClass)
|
|
||||||
->setParameter('relatedEntityId', $relatedEntityId)
|
|
||||||
->setParameter('user', $user);
|
->setParameter('user', $user);
|
||||||
|
|
||||||
return $qb;
|
return $qb;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user