Add EmergencyStatusUpdateEvent and dispatch logic for emergency status changes

- Introduced `EmergencyStatusUpdateEvent` extending `TicketUpdateEvent` to handle emergency status updates.
- Modified `ChangeEmergencyStateCommandHandler` to dispatch the new event when the emergency status is toggled.
- Updated tests to validate event dispatching for emergency status changes.
This commit is contained in:
2025-10-15 15:18:57 +02:00
parent e09676e88b
commit 9a7af3b0c9
3 changed files with 71 additions and 4 deletions

View File

@@ -14,14 +14,20 @@ namespace Chill\TicketBundle\Action\Ticket\Handler;
use Chill\TicketBundle\Action\Ticket\ChangeEmergencyStateCommand; use Chill\TicketBundle\Action\Ticket\ChangeEmergencyStateCommand;
use Chill\TicketBundle\Entity\EmergencyStatusHistory; use Chill\TicketBundle\Entity\EmergencyStatusHistory;
use Chill\TicketBundle\Entity\Ticket; use Chill\TicketBundle\Entity\Ticket;
use Chill\TicketBundle\Event\EmergencyStatusUpdateEvent;
use Chill\TicketBundle\Event\TicketUpdateEvent;
use Symfony\Component\Clock\ClockInterface; use Symfony\Component\Clock\ClockInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
/** /**
* Handler for changing the emergency status of a ticket. * Handler for changing the emergency status of a ticket.
*/ */
class ChangeEmergencyStateCommandHandler class ChangeEmergencyStateCommandHandler
{ {
public function __construct(private readonly ClockInterface $clock) {} public function __construct(
private readonly ClockInterface $clock,
private readonly EventDispatcherInterface $eventDispatcher,
) {}
public function __invoke(Ticket $ticket, ChangeEmergencyStateCommand $command): Ticket public function __invoke(Ticket $ticket, ChangeEmergencyStateCommand $command): Ticket
{ {
@@ -30,6 +36,8 @@ class ChangeEmergencyStateCommandHandler
return $ticket; return $ticket;
} }
$previous = $ticket->getEmergencyStatus();
// End the current emergency status history (if any) // End the current emergency status history (if any)
foreach ($ticket->getEmergencyStatusHistories() as $emergencyStatusHistory) { foreach ($ticket->getEmergencyStatusHistories() as $emergencyStatusHistory) {
if (null === $emergencyStatusHistory->getEndDate()) { if (null === $emergencyStatusHistory->getEndDate()) {
@@ -44,6 +52,12 @@ class ChangeEmergencyStateCommandHandler
$this->clock->now(), $this->clock->now(),
); );
// Dispatch event about the toggle
if (null !== $previous) {
$event = new EmergencyStatusUpdateEvent($ticket, $previous, $command->newEmergencyStatus);
$this->eventDispatcher->dispatch($event, TicketUpdateEvent::class);
}
return $ticket; return $ticket;
} }
} }

View File

@@ -0,0 +1,26 @@
<?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\EmergencyStatusEnum;
use Chill\TicketBundle\Entity\Ticket;
final class EmergencyStatusUpdateEvent extends TicketUpdateEvent
{
public function __construct(
Ticket $ticket,
public EmergencyStatusEnum $previousEmergencyStatus,
public EmergencyStatusEnum $newEmergencyStatus,
) {
parent::__construct(TicketUpdateKindEnum::TOGGLE_EMERGENCY, $ticket);
}
}

View File

@@ -16,9 +16,13 @@ use Chill\TicketBundle\Action\Ticket\Handler\ChangeEmergencyStateCommandHandler;
use Chill\TicketBundle\Entity\EmergencyStatusEnum; use Chill\TicketBundle\Entity\EmergencyStatusEnum;
use Chill\TicketBundle\Entity\EmergencyStatusHistory; use Chill\TicketBundle\Entity\EmergencyStatusHistory;
use Chill\TicketBundle\Entity\Ticket; use Chill\TicketBundle\Entity\Ticket;
use Chill\TicketBundle\Event\EmergencyStatusUpdateEvent;
use Chill\TicketBundle\Event\TicketUpdateEvent;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\PhpUnit\ProphecyTrait;
use Symfony\Component\Clock\MockClock; use Symfony\Component\Clock\MockClock;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
/** /**
* @internal * @internal
@@ -36,7 +40,10 @@ final class ChangeEmergencyStateCommandHandlerTest extends TestCase
// Create a YES emergency status history // Create a YES emergency status history
new EmergencyStatusHistory(EmergencyStatusEnum::YES, $ticket); new EmergencyStatusHistory(EmergencyStatusEnum::YES, $ticket);
$handler = new ChangeEmergencyStateCommandHandler(new MockClock()); $eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
$eventDispatcher->dispatch(Argument::type(EmergencyStatusUpdateEvent::class), TicketUpdateEvent::class)->shouldNotBeCalled();
$handler = new ChangeEmergencyStateCommandHandler(new MockClock(), $eventDispatcher->reveal());
$command = new ChangeEmergencyStateCommand(EmergencyStatusEnum::YES); $command = new ChangeEmergencyStateCommand(EmergencyStatusEnum::YES);
$result = $handler->__invoke($ticket, $command); $result = $handler->__invoke($ticket, $command);
@@ -57,7 +64,17 @@ final class ChangeEmergencyStateCommandHandlerTest extends TestCase
// Create a YES emergency status history // Create a YES emergency status history
new EmergencyStatusHistory(EmergencyStatusEnum::YES, $ticket); new EmergencyStatusHistory(EmergencyStatusEnum::YES, $ticket);
$handler = new ChangeEmergencyStateCommandHandler(new MockClock()); $eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
$eventDispatcher->dispatch(
Argument::that(
fn ($e) => $e instanceof EmergencyStatusUpdateEvent
&& EmergencyStatusEnum::YES === $e->previousEmergencyStatus
&& EmergencyStatusEnum::NO === $e->newEmergencyStatus
),
TicketUpdateEvent::class
)->shouldBeCalled();
$handler = new ChangeEmergencyStateCommandHandler(new MockClock(), $eventDispatcher->reveal());
$command = new ChangeEmergencyStateCommand(EmergencyStatusEnum::NO); $command = new ChangeEmergencyStateCommand(EmergencyStatusEnum::NO);
$result = $handler->__invoke($ticket, $command); $result = $handler->__invoke($ticket, $command);
@@ -90,7 +107,17 @@ final class ChangeEmergencyStateCommandHandlerTest extends TestCase
// Create a NO emergency status history // Create a NO emergency status history
new EmergencyStatusHistory(EmergencyStatusEnum::NO, $ticket); new EmergencyStatusHistory(EmergencyStatusEnum::NO, $ticket);
$handler = new ChangeEmergencyStateCommandHandler(new MockClock()); $eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
$eventDispatcher->dispatch(
Argument::that(
fn ($e) => $e instanceof EmergencyStatusUpdateEvent
&& EmergencyStatusEnum::NO === $e->previousEmergencyStatus
&& EmergencyStatusEnum::YES === $e->newEmergencyStatus
),
TicketUpdateEvent::class
)->shouldBeCalled();
$handler = new ChangeEmergencyStateCommandHandler(new MockClock(), $eventDispatcher->reveal());
$command = new ChangeEmergencyStateCommand(EmergencyStatusEnum::YES); $command = new ChangeEmergencyStateCommand(EmergencyStatusEnum::YES);
$result = $handler->__invoke($ticket, $command); $result = $handler->__invoke($ticket, $command);