mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-10-17 18:52:49 +00:00
Merge branch 'ticket-app-master' into ticket/64-identifiants-person
This commit is contained in:
@@ -66,6 +66,7 @@ framework:
|
|||||||
'Chill\MainBundle\Export\Messenger\ExportRequestGenerationMessage': priority
|
'Chill\MainBundle\Export\Messenger\ExportRequestGenerationMessage': priority
|
||||||
'Chill\MainBundle\Export\Messenger\RemoveExportGenerationMessage': async
|
'Chill\MainBundle\Export\Messenger\RemoveExportGenerationMessage': async
|
||||||
'Chill\MainBundle\Notification\Email\NotificationEmailMessages\ScheduleDailyNotificationDigestMessage': async
|
'Chill\MainBundle\Notification\Email\NotificationEmailMessages\ScheduleDailyNotificationDigestMessage': async
|
||||||
|
'Chill\TicketBundle\Messenger\PostTicketUpdateMessage': async
|
||||||
# end of routes added by chill-bundles recipes
|
# end of routes added by chill-bundles recipes
|
||||||
# Route your messages to the transports
|
# Route your messages to the transports
|
||||||
# 'App\Message\YourMessage': async
|
# 'App\Message\YourMessage': async
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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,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);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,52 @@
|
|||||||
|
<?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\EventSubscriber;
|
||||||
|
|
||||||
|
use Chill\TicketBundle\Event\TicketUpdateEvent;
|
||||||
|
use Chill\TicketBundle\Messenger\PostTicketUpdateMessage;
|
||||||
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
|
use Symfony\Component\HttpKernel\Event\TerminateEvent;
|
||||||
|
use Symfony\Component\HttpKernel\KernelEvents;
|
||||||
|
use Symfony\Component\Messenger\MessageBusInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe to TicketUpdateEvents and dispatch a message for each one when the kernel terminates.
|
||||||
|
*/
|
||||||
|
final class GeneratePostUpdateTicketEventSubscriber implements EventSubscriberInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var list<PostTicketUpdateMessage>
|
||||||
|
*/
|
||||||
|
private array $toDispatch = [];
|
||||||
|
|
||||||
|
public function __construct(private readonly MessageBusInterface $messageBus) {}
|
||||||
|
|
||||||
|
public static function getSubscribedEvents(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
TicketUpdateEvent::class => ['onTicketUpdate', 0],
|
||||||
|
KernelEvents::TERMINATE => ['onKernelTerminate', 8096],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onTicketUpdate(TicketUpdateEvent $event): void
|
||||||
|
{
|
||||||
|
$this->toDispatch[] = new PostTicketUpdateMessage($event->ticket, $event->updateKind);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onKernelTerminate(TerminateEvent $event): void
|
||||||
|
{
|
||||||
|
foreach ($this->toDispatch as $message) {
|
||||||
|
$this->messageBus->dispatch($message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
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;
|
||||||
|
}
|
||||||
|
}
|
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,29 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event triggered asynchronously after a ticket has been updated.
|
||||||
|
*
|
||||||
|
* This event is trigged by PostTicketUpdateMessageHandler, using Messenger component.
|
||||||
|
*
|
||||||
|
* To use a synchronous event, see @see{TicketUpdateEvent}
|
||||||
|
*/
|
||||||
|
class PostTicketUpdateEvent
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public readonly TicketUpdateKindEnum $updateKind,
|
||||||
|
public readonly Ticket $ticket,
|
||||||
|
) {}
|
||||||
|
}
|
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';
|
||||||
|
}
|
@@ -0,0 +1,37 @@
|
|||||||
|
<?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\Messenger\Handler;
|
||||||
|
|
||||||
|
use Chill\TicketBundle\Event\PostTicketUpdateEvent;
|
||||||
|
use Chill\TicketBundle\Messenger\PostTicketUpdateMessage;
|
||||||
|
use Chill\TicketBundle\Repository\TicketRepositoryInterface;
|
||||||
|
use Symfony\Component\Messenger\Exception\UnrecoverableMessageHandlingException;
|
||||||
|
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||||
|
|
||||||
|
final readonly class PostTicketUpdateMessageHandler
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private EventDispatcherInterface $eventDispatcher,
|
||||||
|
private TicketRepositoryInterface $ticketRepository,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function __invoke(PostTicketUpdateMessage $event): void
|
||||||
|
{
|
||||||
|
$ticket = $this->ticketRepository->find($event->ticketId);
|
||||||
|
|
||||||
|
if (null === $ticket) {
|
||||||
|
throw new UnrecoverableMessageHandlingException('Ticket not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->eventDispatcher->dispatch(new PostTicketUpdateEvent($event->updateKind, $ticket));
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,27 @@
|
|||||||
|
<?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\Messenger;
|
||||||
|
|
||||||
|
use Chill\TicketBundle\Entity\Ticket;
|
||||||
|
use Chill\TicketBundle\Event\TicketUpdateKindEnum;
|
||||||
|
|
||||||
|
final readonly class PostTicketUpdateMessage
|
||||||
|
{
|
||||||
|
public readonly int $ticketId;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
Ticket $ticket,
|
||||||
|
public TicketUpdateKindEnum $updateKind,
|
||||||
|
) {
|
||||||
|
$this->ticketId = $ticket->getId();
|
||||||
|
}
|
||||||
|
}
|
@@ -17,6 +17,9 @@ services:
|
|||||||
tags:
|
tags:
|
||||||
- controller.service_arguments
|
- controller.service_arguments
|
||||||
|
|
||||||
|
Chill\TicketBundle\Event\EventSubscriber\:
|
||||||
|
resource: '../Event/EventSubscriber/'
|
||||||
|
|
||||||
Chill\TicketBundle\Repository\:
|
Chill\TicketBundle\Repository\:
|
||||||
resource: '../Repository/'
|
resource: '../Repository/'
|
||||||
|
|
||||||
@@ -35,6 +38,9 @@ services:
|
|||||||
Chill\TicketBundle\Menu\:
|
Chill\TicketBundle\Menu\:
|
||||||
resource: '../Menu/'
|
resource: '../Menu/'
|
||||||
|
|
||||||
|
Chill\TicketBundle\Messenger\Handler\:
|
||||||
|
resource: '../Messenger/Handler'
|
||||||
|
|
||||||
Chill\TicketBundle\Validation\:
|
Chill\TicketBundle\Validation\:
|
||||||
resource: '../Validation/'
|
resource: '../Validation/'
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
|
@@ -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,16 @@ 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(fn ($event) => $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 +99,17 @@ 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(fn ($event) => $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 +132,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 +163,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 +200,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
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,58 @@
|
|||||||
|
<?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\tests\Event\EventSubscriber;
|
||||||
|
|
||||||
|
use Chill\TicketBundle\Entity\Ticket;
|
||||||
|
use Chill\TicketBundle\Event\EventSubscriber\GeneratePostUpdateTicketEventSubscriber;
|
||||||
|
use Chill\TicketBundle\Event\TicketUpdateEvent;
|
||||||
|
use Chill\TicketBundle\Event\TicketUpdateKindEnum;
|
||||||
|
use Chill\TicketBundle\Messenger\PostTicketUpdateMessage;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Prophecy\Argument;
|
||||||
|
use Prophecy\PhpUnit\ProphecyTrait;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Symfony\Component\HttpKernel\Event\TerminateEvent;
|
||||||
|
use Symfony\Component\HttpKernel\KernelInterface;
|
||||||
|
use Symfony\Component\Messenger\Envelope;
|
||||||
|
use Symfony\Component\Messenger\MessageBusInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \Chill\TicketBundle\Event\EventSubscriber\GeneratePostUpdateTicketEventSubscriber
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class GeneratePostUpdateTicketEventSubscriberTest extends TestCase
|
||||||
|
{
|
||||||
|
use ProphecyTrait;
|
||||||
|
|
||||||
|
public function testOnTicketUpdate(): void
|
||||||
|
{
|
||||||
|
$ticket = new Ticket();
|
||||||
|
$reflection = new \ReflectionClass(Ticket::class);
|
||||||
|
$idProperty = $reflection->getProperty('id');
|
||||||
|
$idProperty->setValue($ticket, 1);
|
||||||
|
$event = new class (TicketUpdateKindEnum::UPDATE_MOTIVE, $ticket) extends TicketUpdateEvent {};
|
||||||
|
|
||||||
|
$messageBus = $this->prophesize(MessageBusInterface::class);
|
||||||
|
$messageBus->dispatch(Argument::that(fn ($arg) => $arg instanceof PostTicketUpdateMessage && TicketUpdateKindEnum::UPDATE_MOTIVE === $arg->updateKind && 1 === $arg->ticketId))
|
||||||
|
->will(fn ($args) => new Envelope($args[0]))
|
||||||
|
->shouldBeCalled();
|
||||||
|
|
||||||
|
$eventSubscriber = new GeneratePostUpdateTicketEventSubscriber($messageBus->reveal());
|
||||||
|
$eventSubscriber->onTicketUpdate($event);
|
||||||
|
|
||||||
|
$kernel = $this->prophesize(KernelInterface::class);
|
||||||
|
$terminate = new TerminateEvent($kernel->reveal(), new Request(), new Response());
|
||||||
|
$eventSubscriber->onKernelTerminate($terminate);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,92 @@
|
|||||||
|
<?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\tests\Messenger\Handler;
|
||||||
|
|
||||||
|
use Chill\TicketBundle\Entity\Ticket;
|
||||||
|
use Chill\TicketBundle\Event\PostTicketUpdateEvent;
|
||||||
|
use Chill\TicketBundle\Event\TicketUpdateKindEnum;
|
||||||
|
use Chill\TicketBundle\Messenger\PostTicketUpdateMessage;
|
||||||
|
use Chill\TicketBundle\Messenger\Handler\PostTicketUpdateMessageHandler;
|
||||||
|
use Chill\TicketBundle\Repository\TicketRepositoryInterface;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Prophecy\Argument;
|
||||||
|
use Prophecy\PhpUnit\ProphecyTrait;
|
||||||
|
use Symfony\Component\Messenger\Exception\UnrecoverableMessageHandlingException;
|
||||||
|
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \Chill\TicketBundle\Messenger\Handler\PostTicketUpdateMessageHandler
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class PostTicketUpdateMessageHandlerTest extends TestCase
|
||||||
|
{
|
||||||
|
use ProphecyTrait;
|
||||||
|
|
||||||
|
public function testDispatchesEventWhenTicketExists(): void
|
||||||
|
{
|
||||||
|
// Arrange: a Ticket with an ID
|
||||||
|
$ticket = new Ticket();
|
||||||
|
$reflection = new \ReflectionClass(Ticket::class);
|
||||||
|
$idProperty = $reflection->getProperty('id');
|
||||||
|
$idProperty->setValue($ticket, 123);
|
||||||
|
|
||||||
|
$message = new PostTicketUpdateMessage($ticket, TicketUpdateKindEnum::UPDATE_MOTIVE);
|
||||||
|
|
||||||
|
// Mock repository to return the Ticket when searching by id
|
||||||
|
$ticketRepository = $this->prophesize(TicketRepositoryInterface::class);
|
||||||
|
$ticketRepository->find(123)->willReturn($ticket)->shouldBeCalledOnce();
|
||||||
|
|
||||||
|
// Expect the dispatcher to dispatch a PostTicketUpdateEvent with correct data
|
||||||
|
$eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
|
||||||
|
$eventDispatcher
|
||||||
|
->dispatch(Argument::that(fn ($event) => $event instanceof PostTicketUpdateEvent
|
||||||
|
&& TicketUpdateKindEnum::UPDATE_MOTIVE === $event->updateKind
|
||||||
|
&& $event->ticket === $ticket))
|
||||||
|
->will(fn ($args) => $args[0])
|
||||||
|
->shouldBeCalledOnce();
|
||||||
|
|
||||||
|
$handler = new PostTicketUpdateMessageHandler($eventDispatcher->reveal(), $ticketRepository->reveal());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
$handler($message);
|
||||||
|
|
||||||
|
// Assert: expectations asserted by Prophecy
|
||||||
|
self::assertTrue(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testThrowsWhenTicketNotFound(): void
|
||||||
|
{
|
||||||
|
// Arrange: a Ticket with an ID for the message, but repository will return null
|
||||||
|
$ticket = new Ticket();
|
||||||
|
$reflection = new \ReflectionClass(Ticket::class);
|
||||||
|
$idProperty = $reflection->getProperty('id');
|
||||||
|
$idProperty->setValue($ticket, 999);
|
||||||
|
|
||||||
|
$message = new PostTicketUpdateMessage($ticket, TicketUpdateKindEnum::UPDATE_MOTIVE);
|
||||||
|
|
||||||
|
$ticketRepository = $this->prophesize(TicketRepositoryInterface::class);
|
||||||
|
$ticketRepository->find(999)->willReturn(null)->shouldBeCalledOnce();
|
||||||
|
|
||||||
|
$eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
|
||||||
|
$eventDispatcher->dispatch(Argument::any())->shouldNotBeCalled();
|
||||||
|
|
||||||
|
$handler = new PostTicketUpdateMessageHandler($eventDispatcher->reveal(), $ticketRepository->reveal());
|
||||||
|
|
||||||
|
// Assert: exception is thrown
|
||||||
|
$this->expectException(UnrecoverableMessageHandlingException::class);
|
||||||
|
$this->expectExceptionMessage('Ticket not found');
|
||||||
|
|
||||||
|
// Act
|
||||||
|
$handler($message);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user