feat(notification) : notifier le nouvel assigné d'une tâche

This commit is contained in:
Matthieu
2026-06-15 11:44:12 +02:00
parent 4e430cca43
commit 390f2a40a8
2 changed files with 252 additions and 0 deletions
@@ -0,0 +1,107 @@
<?php
declare(strict_types=1);
namespace App\EventListener;
use App\Entity\Notification;
use App\Entity\Task;
use App\Entity\User;
use DateTimeImmutable;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\ORM\Event\PostFlushEventArgs;
use Doctrine\ORM\Events;
use Symfony\Bundle\SecurityBundle\Security;
#[AsDoctrineListener(event: Events::onFlush)]
#[AsDoctrineListener(event: Events::postFlush)]
final class TaskNotificationListener
{
/** @var list<array{user: User, type: string, task: Task}> */
private array $pending = [];
public function __construct(private readonly Security $security) {}
public function onFlush(OnFlushEventArgs $args): void
{
$actor = $this->security->getUser();
if (!$actor instanceof User) {
return;
}
$uow = $args->getObjectManager()->getUnitOfWork();
// Assignation sur une tâche nouvellement créée.
foreach ($uow->getScheduledEntityInsertions() as $entity) {
if (!$entity instanceof Task) {
continue;
}
$assignee = $entity->getAssignee();
if ($assignee instanceof User && $assignee !== $actor) {
$this->pending[] = ['user' => $assignee, 'type' => 'task_assigned', 'task' => $entity];
}
}
// Changement d'assignation sur une tâche existante.
foreach ($uow->getScheduledEntityUpdates() as $entity) {
if (!$entity instanceof Task) {
continue;
}
$changeSet = $uow->getEntityChangeSet($entity);
if (!isset($changeSet['assignee'])) {
continue;
}
$new = $changeSet['assignee'][1];
if ($new instanceof User && $new !== $actor) {
$this->pending[] = ['user' => $new, 'type' => 'task_assigned', 'task' => $entity];
}
}
}
public function postFlush(PostFlushEventArgs $args): void
{
if ([] === $this->pending) {
return;
}
$pending = $this->pending;
$this->pending = [];
$em = $args->getObjectManager();
foreach ($pending as $item) {
$em->persist($this->buildNotification($item['user'], $item['type'], $item['task']));
}
$em->flush();
}
private function buildNotification(User $user, string $type, Task $task): Notification
{
[$title, $message] = $this->render($type, $task);
$notification = new Notification();
$notification->setUser($user);
$notification->setType($type);
$notification->setTitle($title);
$notification->setMessage($message);
$notification->setCreatedAt(new DateTimeImmutable());
return $notification;
}
/**
* @return array{0: string, 1: string}
*/
private function render(string $type, Task $task): array
{
$projectName = $task->getProject()?->getName() ?? '';
$suffix = '' !== $projectName ? sprintf(' — %s', $projectName) : '';
$context = sprintf('« %s »%s', (string) $task->getTitle(), $suffix);
return match ($type) {
'task_assigned' => ['Nouvelle tâche assignée', $context],
'task_collaborator_added' => ['Ajout à une tâche', $context],
default => ['Notification', $context],
};
}
}