mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-10-17 10:42:48 +00:00
Introduce PersonsUpdateEvent
for handling person modifications in tickets
- Added `PersonsUpdateEvent`, `TicketUpdateEvent`, and `TicketUpdateKindEnum` to encapsulate and differentiate ticket update types. - Updated `SetPersonsCommandHandler` to dispatch `PersonsUpdateEvent` when persons are added or removed. - Extended tests to verify event dispatching for person modifications.
This commit is contained in:
@@ -15,9 +15,12 @@ use Chill\MainBundle\Entity\User;
|
|||||||
use Chill\TicketBundle\Action\Ticket\SetPersonsCommand;
|
use Chill\TicketBundle\Action\Ticket\SetPersonsCommand;
|
||||||
use Chill\TicketBundle\Entity\PersonHistory;
|
use Chill\TicketBundle\Entity\PersonHistory;
|
||||||
use Chill\TicketBundle\Entity\Ticket;
|
use Chill\TicketBundle\Entity\Ticket;
|
||||||
|
use Chill\TicketBundle\Event\PersonsUpdateEvent;
|
||||||
|
use Chill\TicketBundle\Event\TicketUpdateEvent;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Component\Clock\ClockInterface;
|
use Symfony\Component\Clock\ClockInterface;
|
||||||
use Symfony\Component\Security\Core\Security;
|
use Symfony\Component\Security\Core\Security;
|
||||||
|
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||||
|
|
||||||
final readonly class SetPersonsCommandHandler
|
final readonly class SetPersonsCommandHandler
|
||||||
{
|
{
|
||||||
@@ -25,10 +28,13 @@ final readonly class SetPersonsCommandHandler
|
|||||||
private ClockInterface $clock,
|
private ClockInterface $clock,
|
||||||
private EntityManagerInterface $entityManager,
|
private EntityManagerInterface $entityManager,
|
||||||
private Security $security,
|
private Security $security,
|
||||||
|
private EventDispatcherInterface $eventDispatcher,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function handle(Ticket $ticket, SetPersonsCommand $command): void
|
public function handle(Ticket $ticket, SetPersonsCommand $command): void
|
||||||
{
|
{
|
||||||
|
$event = new PersonsUpdateEvent($ticket);
|
||||||
|
|
||||||
// remove existing addresses which are not in the new addresses
|
// remove existing addresses which are not in the new addresses
|
||||||
foreach ($ticket->getPersonHistories() as $personHistory) {
|
foreach ($ticket->getPersonHistories() as $personHistory) {
|
||||||
if (null !== $personHistory->getEndDate()) {
|
if (null !== $personHistory->getEndDate()) {
|
||||||
@@ -40,6 +46,7 @@ final readonly class SetPersonsCommandHandler
|
|||||||
if (($user = $this->security->getUser()) instanceof User) {
|
if (($user = $this->security->getUser()) instanceof User) {
|
||||||
$personHistory->setRemovedBy($user);
|
$personHistory->setRemovedBy($user);
|
||||||
}
|
}
|
||||||
|
$event->personsRemoved[] = $personHistory->getPerson();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,6 +58,11 @@ final readonly class SetPersonsCommandHandler
|
|||||||
|
|
||||||
$history = new PersonHistory($person, $ticket, $this->clock->now());
|
$history = new PersonHistory($person, $ticket, $this->clock->now());
|
||||||
$this->entityManager->persist($history);
|
$this->entityManager->persist($history);
|
||||||
|
$event->personsAdded[] = $person;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($event->hasChanges()) {
|
||||||
|
$this->eventDispatcher->dispatch($event, TicketUpdateEvent::class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\TicketBundle\Event;
|
||||||
|
|
||||||
|
use Chill\PersonBundle\Entity\Person;
|
||||||
|
use Chill\TicketBundle\Entity\Ticket;
|
||||||
|
|
||||||
|
class PersonsUpdateEvent extends TicketUpdateEvent
|
||||||
|
{
|
||||||
|
public function __construct(Ticket $ticket)
|
||||||
|
{
|
||||||
|
parent::__construct(TicketUpdateKindEnum::UPDATE_PERSONS, $ticket);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var list<Person>
|
||||||
|
*/
|
||||||
|
public $personsAdded = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var list<Person>
|
||||||
|
*/
|
||||||
|
public $personsRemoved = [];
|
||||||
|
|
||||||
|
public function hasChanges(): bool
|
||||||
|
{
|
||||||
|
return count($this->personsAdded) > 0 || count($this->personsRemoved) > 0;
|
||||||
|
}
|
||||||
|
}
|
22
src/Bundle/ChillTicketBundle/src/Event/TicketUpdateEvent.php
Normal file
22
src/Bundle/ChillTicketBundle/src/Event/TicketUpdateEvent.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\TicketBundle\Event;
|
||||||
|
|
||||||
|
use Chill\TicketBundle\Entity\Ticket;
|
||||||
|
|
||||||
|
abstract class TicketUpdateEvent
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public readonly TicketUpdateKindEnum $updateKind,
|
||||||
|
public readonly Ticket $ticket,
|
||||||
|
) {}
|
||||||
|
}
|
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\TicketBundle\Event;
|
||||||
|
|
||||||
|
enum TicketUpdateKindEnum: string
|
||||||
|
{
|
||||||
|
case UPDATE_ADDRESSEE = 'UPDATE_ADDRESSEE';
|
||||||
|
case ADD_COMMENT = 'ADD_COMMENT';
|
||||||
|
case TOGGLE_EMERGENCY = 'TOGGLE_EMERGENCY';
|
||||||
|
case TOGGLE_STATE = 'TOGGLE_STATE';
|
||||||
|
case UPDATE_MOTIVE = 'UPDATE_MOTIVE';
|
||||||
|
case UPDATE_CALLER = 'UPDATE_CALLER';
|
||||||
|
case UPDATE_PERSONS = 'UPDATE_PERSONS';
|
||||||
|
}
|
@@ -17,12 +17,15 @@ use Chill\TicketBundle\Action\Ticket\Handler\SetPersonsCommandHandler;
|
|||||||
use Chill\TicketBundle\Action\Ticket\SetPersonsCommand;
|
use Chill\TicketBundle\Action\Ticket\SetPersonsCommand;
|
||||||
use Chill\TicketBundle\Entity\PersonHistory;
|
use Chill\TicketBundle\Entity\PersonHistory;
|
||||||
use Chill\TicketBundle\Entity\Ticket;
|
use Chill\TicketBundle\Entity\Ticket;
|
||||||
|
use Chill\TicketBundle\Event\PersonsUpdateEvent;
|
||||||
|
use Chill\TicketBundle\Event\TicketUpdateEvent;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Prophecy\Argument;
|
use Prophecy\Argument;
|
||||||
use Prophecy\PhpUnit\ProphecyTrait;
|
use Prophecy\PhpUnit\ProphecyTrait;
|
||||||
use Symfony\Component\Clock\MockClock;
|
use Symfony\Component\Clock\MockClock;
|
||||||
use Symfony\Component\Security\Core\Security;
|
use Symfony\Component\Security\Core\Security;
|
||||||
|
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
@@ -42,7 +45,16 @@ final class SetPersonsCommandHandlerTest extends TestCase
|
|||||||
$entityManager->persist(Argument::that(fn ($arg) => $arg instanceof PersonHistory && $arg->getPerson() === $person1))->shouldBeCalledOnce();
|
$entityManager->persist(Argument::that(fn ($arg) => $arg instanceof PersonHistory && $arg->getPerson() === $person1))->shouldBeCalledOnce();
|
||||||
$entityManager->persist(Argument::that(fn ($arg) => $arg instanceof PersonHistory && $arg->getPerson() === $group1))->shouldBeCalledOnce();
|
$entityManager->persist(Argument::that(fn ($arg) => $arg instanceof PersonHistory && $arg->getPerson() === $group1))->shouldBeCalledOnce();
|
||||||
|
|
||||||
$handler = $this->buildHandler($entityManager->reveal());
|
$eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
|
||||||
|
$eventDispatcher->dispatch(
|
||||||
|
Argument::that(fn ($arg) => $arg instanceof PersonsUpdateEvent
|
||||||
|
&& in_array($person1, $arg->personsAdded, true)
|
||||||
|
&& in_array($group1, $arg->personsAdded, true)
|
||||||
|
&& [] === $arg->personsRemoved),
|
||||||
|
TicketUpdateEvent::class
|
||||||
|
)->shouldBeCalled();
|
||||||
|
|
||||||
|
$handler = $this->buildHandler($entityManager->reveal(), $eventDispatcher->reveal());
|
||||||
|
|
||||||
$handler->handle($ticket, $command);
|
$handler->handle($ticket, $command);
|
||||||
|
|
||||||
@@ -59,7 +71,15 @@ final class SetPersonsCommandHandlerTest extends TestCase
|
|||||||
$entityManager = $this->prophesize(EntityManagerInterface::class);
|
$entityManager = $this->prophesize(EntityManagerInterface::class);
|
||||||
$entityManager->persist(Argument::that(fn ($arg) => $arg instanceof PersonHistory && $arg->getPerson() === $person))->shouldNotBeCalled();
|
$entityManager->persist(Argument::that(fn ($arg) => $arg instanceof PersonHistory && $arg->getPerson() === $person))->shouldNotBeCalled();
|
||||||
|
|
||||||
$handler = $this->buildHandler($entityManager->reveal());
|
$eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
|
||||||
|
$eventDispatcher->dispatch(
|
||||||
|
Argument::that(
|
||||||
|
fn ($arg) => $arg instanceof PersonsUpdateEvent
|
||||||
|
),
|
||||||
|
TicketUpdateEvent::class
|
||||||
|
)->shouldNotBeCalled();
|
||||||
|
|
||||||
|
$handler = $this->buildHandler($entityManager->reveal(), $eventDispatcher->reveal());
|
||||||
|
|
||||||
$handler->handle($ticket, $command);
|
$handler->handle($ticket, $command);
|
||||||
|
|
||||||
@@ -78,7 +98,17 @@ final class SetPersonsCommandHandlerTest extends TestCase
|
|||||||
$entityManager = $this->prophesize(EntityManagerInterface::class);
|
$entityManager = $this->prophesize(EntityManagerInterface::class);
|
||||||
$entityManager->persist(Argument::that(fn ($arg) => $arg instanceof PersonHistory && $arg->getPerson() === $person2))->shouldBeCalled();
|
$entityManager->persist(Argument::that(fn ($arg) => $arg instanceof PersonHistory && $arg->getPerson() === $person2))->shouldBeCalled();
|
||||||
|
|
||||||
$handler = $this->buildHandler($entityManager->reveal());
|
$eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
|
||||||
|
$eventDispatcher->dispatch(
|
||||||
|
Argument::that(
|
||||||
|
fn ($arg) => $arg instanceof PersonsUpdateEvent
|
||||||
|
&& in_array($person, $arg->personsRemoved, true) && 1 === count($arg->personsRemoved)
|
||||||
|
&& in_array($person2, $arg->personsAdded, true) && 1 === count($arg->personsAdded)
|
||||||
|
),
|
||||||
|
TicketUpdateEvent::class
|
||||||
|
)->shouldBeCalled();
|
||||||
|
|
||||||
|
$handler = $this->buildHandler($entityManager->reveal(), $eventDispatcher->reveal());
|
||||||
|
|
||||||
$handler->handle($ticket, $command);
|
$handler->handle($ticket, $command);
|
||||||
|
|
||||||
@@ -95,18 +125,28 @@ final class SetPersonsCommandHandlerTest extends TestCase
|
|||||||
$entityManager = $this->prophesize(EntityManagerInterface::class);
|
$entityManager = $this->prophesize(EntityManagerInterface::class);
|
||||||
$entityManager->persist(Argument::that(fn ($arg) => $arg instanceof PersonHistory && $arg->getPerson() === $person))->shouldBeCalledOnce();
|
$entityManager->persist(Argument::that(fn ($arg) => $arg instanceof PersonHistory && $arg->getPerson() === $person))->shouldBeCalledOnce();
|
||||||
|
|
||||||
$handler = $this->buildHandler($entityManager->reveal());
|
$eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
|
||||||
|
$eventDispatcher->dispatch(
|
||||||
|
Argument::that(
|
||||||
|
fn ($arg) => $arg instanceof PersonsUpdateEvent
|
||||||
|
&& in_array($person, $arg->personsAdded, true) && 1 === count($arg->personsAdded)
|
||||||
|
&& [] === $arg->personsRemoved
|
||||||
|
),
|
||||||
|
TicketUpdateEvent::class
|
||||||
|
)->shouldBeCalled();
|
||||||
|
|
||||||
|
$handler = $this->buildHandler($entityManager->reveal(), $eventDispatcher->reveal());
|
||||||
|
|
||||||
$handler->handle($ticket, $command);
|
$handler->handle($ticket, $command);
|
||||||
|
|
||||||
self::assertCount(1, $ticket->getPersons());
|
self::assertCount(1, $ticket->getPersons());
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildHandler(EntityManagerInterface $entityManager): SetPersonsCommandHandler
|
private function buildHandler(EntityManagerInterface $entityManager, EventDispatcherInterface $eventDispatcher): SetPersonsCommandHandler
|
||||||
{
|
{
|
||||||
$security = $this->prophesize(Security::class);
|
$security = $this->prophesize(Security::class);
|
||||||
$security->getUser()->willReturn(new User());
|
$security->getUser()->willReturn(new User());
|
||||||
|
|
||||||
return new SetPersonsCommandHandler(new MockClock(), $entityManager, $security->reveal());
|
return new SetPersonsCommandHandler(new MockClock(), $entityManager, $security->reveal(), $eventDispatcher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user