<?php
declare(strict_types=1);
namespace App\Order\Workflow;
use App\Order\Doctrine\Entity\Detail;
use App\Order\Doctrine\Entity\Order;
use Doctrine\Common\Collections\Collection;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Workflow\Event\Event;
use Symfony\Component\Workflow\Event\GuardEvent;
use Symfony\Component\Workflow\WorkflowInterface;
final class OrderSubscriber implements EventSubscriberInterface
{
public function __construct(private WorkflowInterface $detailStateMachine)
{
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents(): array
{
return [
'workflow.order.completed' => ['onCompleted'],
'workflow.order.completed.cancel' => ['onCompletedCancel'],
'workflow.order.guard.process' => ['guardProcess'],
];
}
public function guardProcess(GuardEvent $event): void
{
/** @var Order $order */
$order = $event->getSubject();
if (
$order->getDetailsToDeliver()->count() > 0
|| $order->getDetailsToShip()->count() > 0
|| $order->getDetailsToProcess()->count() > 0
) {
$event->setBlocked(true);
}
}
public function onCompletedCancel(Event $event): void
{
/** @var Order $order */
$order = $event->getSubject();
/** @var Collection<int, Detail> $detailsToCancel */
$detailsToCancel = $order->getDetails()
->filter(fn (Detail $detail) => $this->detailStateMachine->can($detail, 'cancel'));
foreach ($detailsToCancel as $detail) {
$this->detailStateMachine->apply($detail, 'cancel');
}
$order->addStateHistory($order->getState());
}
public function onCompleted(Event $event): void
{
/** @var Order $order */
$order = $event->getSubject();
$order->addStateHistory($order->getState());
}
}