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\Entity\EmergencyStatusHistory;
use Chill\TicketBundle\Entity\Ticket;
use Chill\TicketBundle\Event\EmergencyStatusUpdateEvent;
use Chill\TicketBundle\Event\TicketUpdateEvent;
use Symfony\Component\Clock\ClockInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
/**
* Handler for changing the emergency status of a ticket.
*/
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
{
@@ -30,6 +36,8 @@ class ChangeEmergencyStateCommandHandler
return $ticket;
}
$previous = $ticket->getEmergencyStatus();
// End the current emergency status history (if any)
foreach ($ticket->getEmergencyStatusHistories() as $emergencyStatusHistory) {
if (null === $emergencyStatusHistory->getEndDate()) {
@@ -44,6 +52,12 @@ class ChangeEmergencyStateCommandHandler
$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;
}
}

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\EmergencyStatusHistory;
use Chill\TicketBundle\Entity\Ticket;
use Chill\TicketBundle\Event\EmergencyStatusUpdateEvent;
use Chill\TicketBundle\Event\TicketUpdateEvent;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Symfony\Component\Clock\MockClock;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
/**
* @internal
@@ -36,7 +40,10 @@ final class ChangeEmergencyStateCommandHandlerTest extends TestCase
// Create a YES emergency status history
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);
$result = $handler->__invoke($ticket, $command);
@@ -57,7 +64,17 @@ final class ChangeEmergencyStateCommandHandlerTest extends TestCase
// Create a YES emergency status history
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);
$result = $handler->__invoke($ticket, $command);
@@ -90,7 +107,17 @@ final class ChangeEmergencyStateCommandHandlerTest extends TestCase
// Create a NO emergency status history
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);
$result = $handler->__invoke($ticket, $command);