mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-10-17 10:42:48 +00:00
Add MotiveUpdateEvent
and integrate dispatch logic in ReplaceMotiveCommandHandler
- Introduced `MotiveUpdateEvent` to encapsulate motive updates for tickets. - Modified `ReplaceMotiveCommandHandler` to dispatch the new event when motives are updated. - Updated tests to validate `MotiveUpdateEvent` dispatching.
This commit is contained in:
@@ -15,8 +15,11 @@ use Chill\TicketBundle\Action\Ticket\ChangeEmergencyStateCommand;
|
|||||||
use Chill\TicketBundle\Action\Ticket\ReplaceMotiveCommand;
|
use Chill\TicketBundle\Action\Ticket\ReplaceMotiveCommand;
|
||||||
use Chill\TicketBundle\Entity\MotiveHistory;
|
use Chill\TicketBundle\Entity\MotiveHistory;
|
||||||
use Chill\TicketBundle\Entity\Ticket;
|
use Chill\TicketBundle\Entity\Ticket;
|
||||||
|
use Chill\TicketBundle\Event\MotiveUpdateEvent;
|
||||||
|
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\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||||
|
|
||||||
class ReplaceMotiveCommandHandler
|
class ReplaceMotiveCommandHandler
|
||||||
{
|
{
|
||||||
@@ -24,6 +27,7 @@ class ReplaceMotiveCommandHandler
|
|||||||
private readonly ClockInterface $clock,
|
private readonly ClockInterface $clock,
|
||||||
private readonly EntityManagerInterface $entityManager,
|
private readonly EntityManagerInterface $entityManager,
|
||||||
private readonly ChangeEmergencyStateCommandHandler $changeEmergencyStateCommandHandler,
|
private readonly ChangeEmergencyStateCommandHandler $changeEmergencyStateCommandHandler,
|
||||||
|
private readonly EventDispatcherInterface $eventDispatcher,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function handle(Ticket $ticket, ReplaceMotiveCommand $command): void
|
public function handle(Ticket $ticket, ReplaceMotiveCommand $command): void
|
||||||
@@ -32,6 +36,8 @@ class ReplaceMotiveCommandHandler
|
|||||||
throw new \InvalidArgumentException('The new motive cannot be null');
|
throw new \InvalidArgumentException('The new motive cannot be null');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$event = new MotiveUpdateEvent($ticket);
|
||||||
|
|
||||||
// will add if there are no existing motive
|
// will add if there are no existing motive
|
||||||
$readyToAdd = 0 === count($ticket->getMotiveHistories());
|
$readyToAdd = 0 === count($ticket->getMotiveHistories());
|
||||||
|
|
||||||
@@ -45,6 +51,8 @@ class ReplaceMotiveCommandHandler
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// collect previous active motives before closing
|
||||||
|
$event->previousMotive = $history->getMotive();
|
||||||
$history->setEndDate($this->clock->now());
|
$history->setEndDate($this->clock->now());
|
||||||
$readyToAdd = true;
|
$readyToAdd = true;
|
||||||
}
|
}
|
||||||
@@ -52,6 +60,7 @@ class ReplaceMotiveCommandHandler
|
|||||||
if ($readyToAdd) {
|
if ($readyToAdd) {
|
||||||
$history = new MotiveHistory($command->motive, $ticket, $this->clock->now());
|
$history = new MotiveHistory($command->motive, $ticket, $this->clock->now());
|
||||||
$this->entityManager->persist($history);
|
$this->entityManager->persist($history);
|
||||||
|
$event->newMotive = $command->motive;
|
||||||
|
|
||||||
// Check if the motive has makeTicketEmergency set and update the ticket's emergency status if needed
|
// Check if the motive has makeTicketEmergency set and update the ticket's emergency status if needed
|
||||||
if ($command->motive->isMakeTicketEmergency()) {
|
if ($command->motive->isMakeTicketEmergency()) {
|
||||||
@@ -59,5 +68,9 @@ class ReplaceMotiveCommandHandler
|
|||||||
($this->changeEmergencyStateCommandHandler)($ticket, $changeEmergencyCommand);
|
($this->changeEmergencyStateCommandHandler)($ticket, $changeEmergencyCommand);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($event->hasChanges()) {
|
||||||
|
$this->eventDispatcher->dispatch($event, TicketUpdateEvent::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
31
src/Bundle/ChillTicketBundle/src/Event/MotiveUpdateEvent.php
Normal file
31
src/Bundle/ChillTicketBundle/src/Event/MotiveUpdateEvent.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?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\Motive;
|
||||||
|
use Chill\TicketBundle\Entity\Ticket;
|
||||||
|
|
||||||
|
final class MotiveUpdateEvent extends TicketUpdateEvent
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
Ticket $ticket,
|
||||||
|
public ?Motive $previousMotive = null,
|
||||||
|
public ?Motive $newMotive = null,
|
||||||
|
) {
|
||||||
|
parent::__construct(TicketUpdateKindEnum::UPDATE_MOTIVE, $ticket);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasChanges(): bool
|
||||||
|
{
|
||||||
|
return null !== $this->newMotive || null !== $this->previousMotive;
|
||||||
|
}
|
||||||
|
}
|
@@ -19,16 +19,19 @@ use Chill\TicketBundle\Entity\EmergencyStatusEnum;
|
|||||||
use Chill\TicketBundle\Entity\Motive;
|
use Chill\TicketBundle\Entity\Motive;
|
||||||
use Chill\TicketBundle\Entity\MotiveHistory;
|
use Chill\TicketBundle\Entity\MotiveHistory;
|
||||||
use Chill\TicketBundle\Entity\Ticket;
|
use Chill\TicketBundle\Entity\Ticket;
|
||||||
|
use Chill\TicketBundle\Event\MotiveUpdateEvent;
|
||||||
|
use Chill\TicketBundle\Event\TicketUpdateEvent;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Prophecy\Argument;
|
use Prophecy\Argument;
|
||||||
use Prophecy\PhpUnit\ProphecyTrait;
|
use Prophecy\PhpUnit\ProphecyTrait;
|
||||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||||
use Symfony\Component\Clock\MockClock;
|
use Symfony\Component\Clock\MockClock;
|
||||||
|
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*
|
*
|
||||||
* @coversNothing
|
* @covers \Chill\TicketBundle\Action\Ticket\Handler\ReplaceMotiveCommandHandler
|
||||||
*/
|
*/
|
||||||
final class ReplaceMotiveCommandHandlerTest extends KernelTestCase
|
final class ReplaceMotiveCommandHandlerTest extends KernelTestCase
|
||||||
{
|
{
|
||||||
@@ -37,14 +40,18 @@ final class ReplaceMotiveCommandHandlerTest extends KernelTestCase
|
|||||||
private function buildHandler(
|
private function buildHandler(
|
||||||
EntityManagerInterface $entityManager,
|
EntityManagerInterface $entityManager,
|
||||||
?ChangeEmergencyStateCommandHandler $changeEmergencyStateCommandHandler = null,
|
?ChangeEmergencyStateCommandHandler $changeEmergencyStateCommandHandler = null,
|
||||||
|
?EventDispatcherInterface $eventDispatcher = null,
|
||||||
): ReplaceMotiveCommandHandler {
|
): ReplaceMotiveCommandHandler {
|
||||||
$clock = new MockClock();
|
$clock = new MockClock();
|
||||||
|
|
||||||
if (null === $changeEmergencyStateCommandHandler) {
|
if (null === $changeEmergencyStateCommandHandler) {
|
||||||
$changeEmergencyStateCommandHandler = $this->prophesize(ChangeEmergencyStateCommandHandler::class)->reveal();
|
$changeEmergencyStateCommandHandler = $this->prophesize(ChangeEmergencyStateCommandHandler::class)->reveal();
|
||||||
}
|
}
|
||||||
|
if (null === $eventDispatcher) {
|
||||||
|
$eventDispatcher = $this->prophesize(EventDispatcherInterface::class)->reveal();
|
||||||
|
}
|
||||||
|
|
||||||
return new ReplaceMotiveCommandHandler($clock, $entityManager, $changeEmergencyStateCommandHandler);
|
return new ReplaceMotiveCommandHandler($clock, $entityManager, $changeEmergencyStateCommandHandler, $eventDispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testHandleOnTicketWithoutMotive(): void
|
public function testHandleOnTicketWithoutMotive(): void
|
||||||
@@ -61,7 +68,18 @@ final class ReplaceMotiveCommandHandlerTest extends KernelTestCase
|
|||||||
return $arg->getMotive() === $motive;
|
return $arg->getMotive() === $motive;
|
||||||
}))->shouldBeCalled();
|
}))->shouldBeCalled();
|
||||||
|
|
||||||
$handler = $this->buildHandler($entityManager->reveal());
|
$eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
|
||||||
|
$eventDispatcher->dispatch(
|
||||||
|
Argument::that(function ($event) use ($motive) {
|
||||||
|
return $event instanceof MotiveUpdateEvent
|
||||||
|
&& $event->newMotive === $motive
|
||||||
|
&& null === $event->previousMotive
|
||||||
|
&& $event->hasChanges();
|
||||||
|
}),
|
||||||
|
TicketUpdateEvent::class
|
||||||
|
)->shouldBeCalled();
|
||||||
|
|
||||||
|
$handler = $this->buildHandler($entityManager->reveal(), null, $eventDispatcher->reveal());
|
||||||
|
|
||||||
$handler->handle($ticket, new ReplaceMotiveCommand($motive));
|
$handler->handle($ticket, new ReplaceMotiveCommand($motive));
|
||||||
|
|
||||||
@@ -83,7 +101,19 @@ final class ReplaceMotiveCommandHandlerTest extends KernelTestCase
|
|||||||
return $arg->getMotive() === $motive;
|
return $arg->getMotive() === $motive;
|
||||||
}))->shouldBeCalled();
|
}))->shouldBeCalled();
|
||||||
|
|
||||||
$handler = $this->buildHandler($entityManager->reveal());
|
$previous = $history->getMotive();
|
||||||
|
$eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
|
||||||
|
$eventDispatcher->dispatch(
|
||||||
|
Argument::that(function ($event) use ($motive, $previous) {
|
||||||
|
return $event instanceof MotiveUpdateEvent
|
||||||
|
&& $event->newMotive === $motive
|
||||||
|
&& $previous === $event->previousMotive
|
||||||
|
&& $event->hasChanges();
|
||||||
|
}),
|
||||||
|
TicketUpdateEvent::class
|
||||||
|
)->shouldBeCalled();
|
||||||
|
|
||||||
|
$handler = $this->buildHandler($entityManager->reveal(), null, $eventDispatcher->reveal());
|
||||||
|
|
||||||
$handler->handle($ticket, new ReplaceMotiveCommand($motive));
|
$handler->handle($ticket, new ReplaceMotiveCommand($motive));
|
||||||
|
|
||||||
@@ -106,7 +136,10 @@ final class ReplaceMotiveCommandHandlerTest extends KernelTestCase
|
|||||||
return $arg->getMotive() === $motive;
|
return $arg->getMotive() === $motive;
|
||||||
}))->shouldNotBeCalled();
|
}))->shouldNotBeCalled();
|
||||||
|
|
||||||
$handler = $this->buildHandler($entityManager->reveal());
|
$eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
|
||||||
|
$eventDispatcher->dispatch(Argument::any(), TicketUpdateEvent::class)->shouldNotBeCalled();
|
||||||
|
|
||||||
|
$handler = $this->buildHandler($entityManager->reveal(), null, $eventDispatcher->reveal());
|
||||||
|
|
||||||
$handler->handle($ticket, new ReplaceMotiveCommand($motive));
|
$handler->handle($ticket, new ReplaceMotiveCommand($motive));
|
||||||
|
|
||||||
@@ -134,10 +167,15 @@ final class ReplaceMotiveCommandHandlerTest extends KernelTestCase
|
|||||||
Argument::that(fn (ChangeEmergencyStateCommand $command) => EmergencyStatusEnum::YES === $command->newEmergencyStatus)
|
Argument::that(fn (ChangeEmergencyStateCommand $command) => EmergencyStatusEnum::YES === $command->newEmergencyStatus)
|
||||||
)->shouldBeCalled();
|
)->shouldBeCalled();
|
||||||
|
|
||||||
|
// Expect event dispatch for motive update
|
||||||
|
$eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
|
||||||
|
$eventDispatcher->dispatch(Argument::type(MotiveUpdateEvent::class), TicketUpdateEvent::class)->shouldBeCalled();
|
||||||
|
|
||||||
// Create the handler with our mocks
|
// Create the handler with our mocks
|
||||||
$handler = $this->buildHandler(
|
$handler = $this->buildHandler(
|
||||||
$entityManager->reveal(),
|
$entityManager->reveal(),
|
||||||
$changeEmergencyStateCommandHandler->reveal()
|
$changeEmergencyStateCommandHandler->reveal(),
|
||||||
|
$eventDispatcher->reveal()
|
||||||
);
|
);
|
||||||
|
|
||||||
// Handle the command
|
// Handle the command
|
||||||
@@ -166,10 +204,15 @@ final class ReplaceMotiveCommandHandlerTest extends KernelTestCase
|
|||||||
Argument::cetera()
|
Argument::cetera()
|
||||||
)->shouldNotBeCalled();
|
)->shouldNotBeCalled();
|
||||||
|
|
||||||
|
// Expect event dispatch for motive update
|
||||||
|
$eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
|
||||||
|
$eventDispatcher->dispatch(Argument::type(MotiveUpdateEvent::class), TicketUpdateEvent::class)->shouldBeCalled();
|
||||||
|
|
||||||
// Create the handler with our mocks
|
// Create the handler with our mocks
|
||||||
$handler = $this->buildHandler(
|
$handler = $this->buildHandler(
|
||||||
$entityManager->reveal(),
|
$entityManager->reveal(),
|
||||||
$changeEmergencyStateCommandHandler->reveal()
|
$changeEmergencyStateCommandHandler->reveal(),
|
||||||
|
$eventDispatcher->reveal()
|
||||||
);
|
);
|
||||||
|
|
||||||
// Handle the command
|
// Handle the command
|
||||||
|
Reference in New Issue
Block a user