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;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
@ -46,21 +50,25 @@ class NotificationPresence
|
||||
$counter = $this->notificationRepository->countNotificationByRelatedEntityAndUserAssociated(
|
||||
$relatedEntityClass,
|
||||
$relatedEntityId,
|
||||
$user
|
||||
$user,
|
||||
$more
|
||||
);
|
||||
|
||||
if ([] === $more) {
|
||||
$this->cache[$relatedEntityClass][$relatedEntityId] = $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[]
|
||||
*/
|
||||
public function getNotificationsForClassAndEntity(string $relatedEntityClass, int $relatedEntityId): array
|
||||
public function getNotificationsForClassAndEntity(string $relatedEntityClass, int $relatedEntityId, array $more = []): array
|
||||
{
|
||||
$user = $this->security->getUser();
|
||||
|
||||
@ -68,7 +76,8 @@ class NotificationPresence
|
||||
return $this->notificationRepository->findNotificationByRelatedEntityAndUserAssociated(
|
||||
$relatedEntityClass,
|
||||
$relatedEntityId,
|
||||
$user
|
||||
$user,
|
||||
$more
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -34,24 +34,30 @@ class NotificationTwigExtensionRuntime implements RuntimeExtensionInterface
|
||||
$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(
|
||||
'@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) {
|
||||
return '';
|
||||
|
@ -29,6 +29,15 @@ final class NotificationRepository implements ObjectRepository
|
||||
|
||||
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)
|
||||
{
|
||||
$this->em = $entityManager;
|
||||
@ -51,29 +60,45 @@ final class NotificationRepository implements ObjectRepository
|
||||
->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) {
|
||||
$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,
|
||||
COUNT(cmn.*) AS total
|
||||
FROM chill_main_notification cmn
|
||||
WHERE relatedentityclass = :relatedEntityClass AND relatedentityid = :relatedEntityId AND sender_id IS NOT NULL';
|
||||
$sql = self::BASE_COUNTER_SQL . ' WHERE relatedentityclass = :relatedEntityClass AND relatedentityid = :relatedEntityId AND sender_id IS NOT NULL';
|
||||
|
||||
$this->notificationByRelatedEntityAndUserAssociatedStatement =
|
||||
$this->em->getConnection()->prepare($sql);
|
||||
}
|
||||
|
||||
$results = $this->notificationByRelatedEntityAndUserAssociatedStatement
|
||||
->executeQuery(['relatedEntityClass' => $relatedEntityClass, 'relatedEntityId' => $relatedEntityId, 'userid' => $user->getId()]);
|
||||
->executeQuery($sqlParams);
|
||||
|
||||
$result = $results->fetchAssociative();
|
||||
|
||||
$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
|
||||
@ -167,8 +192,8 @@ final class NotificationRepository implements ObjectRepository
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed|null $limit
|
||||
* @param mixed|null $offset
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
*
|
||||
* @return Notification[]
|
||||
*/
|
||||
@ -178,13 +203,15 @@ final class NotificationRepository implements ObjectRepository
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array{relatedEntityClass: class-string, relatedEntityId: int}> $more
|
||||
* @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
|
||||
$this->buildQueryNotificationByRelatedEntityAndUserAssociated($relatedEntityClass, $relatedEntityId, $user)
|
||||
$this->buildQueryNotificationByRelatedEntityAndUserAssociated($relatedEntityClass, $relatedEntityId, $user, $more)
|
||||
->select('n')
|
||||
->addOrderBy('n.date', 'DESC')
|
||||
->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
@ -222,13 +249,36 @@ final class NotificationRepository implements ObjectRepository
|
||||
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');
|
||||
|
||||
// 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
|
||||
->where($qb->expr()->eq('n.relatedEntityClass', ':relatedEntityClass'))
|
||||
->andWhere($qb->expr()->eq('n.relatedEntityId', ':relatedEntityId'))
|
||||
->setParameter('relatedEntityClass', $relatedEntityClass)
|
||||
->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()->orX(
|
||||
@ -236,8 +286,6 @@ final class NotificationRepository implements ObjectRepository
|
||||
$qb->expr()->eq('n.sender', ':user')
|
||||
)
|
||||
)
|
||||
->setParameter('relatedEntityClass', $relatedEntityClass)
|
||||
->setParameter('relatedEntityId', $relatedEntityId)
|
||||
->setParameter('user', $user);
|
||||
|
||||
return $qb;
|
||||
|
Loading…
x
Reference in New Issue
Block a user