mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-27 17:15:02 +00:00
added unread and read all function with endpoints for notifications
This commit is contained in:
@@ -13,6 +13,8 @@ namespace Chill\MainBundle\Repository;
|
||||
|
||||
use Chill\MainBundle\Entity\Notification;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\DBAL\Result;
|
||||
use Doctrine\DBAL\Statement;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
@@ -81,10 +83,7 @@ final class NotificationRepository implements ObjectRepository
|
||||
$results->free();
|
||||
} else {
|
||||
$wheres = [];
|
||||
foreach ([
|
||||
['relatedEntityClass' => $relatedEntityClass, 'relatedEntityId' => $relatedEntityId],
|
||||
...$more,
|
||||
] as $k => ['relatedEntityClass' => $relClass, 'relatedEntityId' => $relId]) {
|
||||
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;
|
||||
@@ -228,11 +227,11 @@ final class NotificationRepository implements ObjectRepository
|
||||
$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';
|
||||
'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())
|
||||
@@ -255,10 +254,12 @@ final class NotificationRepository implements ObjectRepository
|
||||
$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')
|
||||
));
|
||||
$or = $qb->expr()->orX(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->eq('n.relatedEntityClass', ':relatedEntityClass'),
|
||||
$qb->expr()->eq('n.relatedEntityId', ':relatedEntityId')
|
||||
)
|
||||
);
|
||||
$qb
|
||||
->setParameter('relatedEntityClass', $relatedEntityClass)
|
||||
->setParameter('relatedEntityId', $relatedEntityId);
|
||||
@@ -310,4 +311,86 @@ final class NotificationRepository implements ObjectRepository
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<int> the ids of the notifications marked as unread
|
||||
*/
|
||||
public function markAllNotificationAsReadForUser(User $user): array
|
||||
{
|
||||
// Get the database connection from the entity manager
|
||||
$connection = $this->em->getConnection();
|
||||
|
||||
/** @var Result $results */
|
||||
$results = $connection->transactional(function (Connection $connection) use ($user) {
|
||||
// Define the SQL query
|
||||
$sql = <<<'SQL'
|
||||
DELETE FROM chill_main_notification_addresses_unread
|
||||
WHERE user_id = :user_id
|
||||
RETURNING notification_id
|
||||
SQL;
|
||||
|
||||
return $connection->executeQuery($sql, ['user_id' => $user->getId()]);
|
||||
});
|
||||
|
||||
$notificationIdsTouched = [];
|
||||
foreach ($results->iterateAssociative() as $row) {
|
||||
$notificationIdsTouched[] = $row['notification_id'];
|
||||
}
|
||||
|
||||
return array_values($notificationIdsTouched);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<int> $notificationIds
|
||||
*/
|
||||
public function markAllNotificationAsUnreadForUser(User $user, array $notificationIds): array
|
||||
{
|
||||
// Get the database connection from the entity manager
|
||||
$connection = $this->em->getConnection();
|
||||
|
||||
/** @var Result $results */
|
||||
$results = $connection->transactional(function (Connection $connection) use ($user, $notificationIds) {
|
||||
// This query double-check that the user is one of the addresses of the notification or the sender,
|
||||
// if the notification is already marked as unread, this query does not fails.
|
||||
// this query return the list of notification id which are affected
|
||||
$sql = <<<'SQL'
|
||||
INSERT INTO chill_main_notification_addresses_unread (user_id, notification_id)
|
||||
SELECT ?, chill_main_notification_addresses_user.notification_id
|
||||
FROM chill_main_notification_addresses_user JOIN chill_main_notification ON chill_main_notification_addresses_user.notification_id = chill_main_notification.id
|
||||
WHERE (chill_main_notification_addresses_user.user_id = ? OR chill_main_notification.sender_id = ?)
|
||||
AND chill_main_notification_addresses_user.notification_id IN ({ notification_ids })
|
||||
ON CONFLICT (user_id, notification_id) DO NOTHING
|
||||
RETURNING notification_id
|
||||
SQL;
|
||||
|
||||
$params = [$user->getId(), $user->getId(), $user->getId(), ...array_values($notificationIds)];
|
||||
$sql = strtr($sql, ['{ notification_ids }' => implode(', ', array_fill(0, count($notificationIds), '?'))]);
|
||||
|
||||
return $connection->executeQuery($sql, $params);
|
||||
});
|
||||
|
||||
$notificationIdsTouched = [];
|
||||
foreach ($results->iterateAssociative() as $row) {
|
||||
$notificationIdsTouched[] = $row['notification_id'];
|
||||
}
|
||||
|
||||
return array_values($notificationIdsTouched);
|
||||
}
|
||||
|
||||
public function findAllUnreadByUser(User $user): 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';
|
||||
|
||||
$nq = $this->em->createNativeQuery($sql, $rsm)
|
||||
->setParameter('userId', $user->getId());
|
||||
|
||||
return $nq->getResult();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user