<?php
namespace App\Service;
use App\Entity\Dto;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Workflow\Definition;
use Symfony\Component\Workflow\MarkingStore\MethodMarkingStore;
use Symfony\Component\Workflow\Metadata\InMemoryMetadataStore;
use Symfony\Component\Workflow\Registry;
use Symfony\Component\Workflow\StateMachine;
use Symfony\Component\Workflow\SupportStrategy\InstanceOfSupportStrategy;
use Symfony\Component\Workflow\Transition;
use Symfony\Component\Workflow\Validator\StateMachineValidator;
class EntityToStateMachine
{
public const METADATA_DTO = 'dto';
private EventDispatcherInterface $dispatcher;
private Registry $registry;
public function __construct(
EventDispatcherInterface $dispatcher,
Registry $registry
)
{
$this->dispatcher = $dispatcher;
$this->registry = $registry;
}
public function getStateMachine(Dto $dto, $subject = null): StateMachine
{
$markingStore = new MethodMarkingStore(true, 'currentPlace');
$states = $this->getStates($dto);
$initialPlace = $dto->getInitialPlace();
$stateTransitions = $this->getTransitions($dto);
$metaData = (new InMemoryMetadataStore([
self::METADATA_DTO => $dto,
]));
// No validation is done upon initialization
$definition = new Definition(
$states,
$stateTransitions,
$initialPlace->getUniqueId(),
$metaData
);
// Throws InvalidDefinitionException in case of an invalid definition
(new StateMachineValidator())->validate($definition, $dto->getSlug());
$stateMachine = new StateMachine(
$definition,
$markingStore,
$this->dispatcher,
$dto->getSlug(),
null
);
$this->registry->addWorkflow($stateMachine, new InstanceOfSupportStrategy(WorkflowInterface::class));
if ($subject) {
if(null === $subject->getCurrentPlace()){
$subject->setCurrentPlace($initialPlace->getUniqueId());
}
$stateMachine->getMarking($subject);
}
return $stateMachine;
}
private function getStates(Dto $dto): array
{
return array_map(static function ($place) {
return $place->getUniqueId();
}, $dto->getPlaces());
}
private function getTransitions(Dto $dto): array
{
return array_map(static function ($transition) {
$from = $transition->getFromPlace()->getUniqueId();
$to = $transition->getToPlace()->getUniqueId();
return new Transition(
$transition->getUniqueId(),
[$from],
[$to]
);
}, $dto->getTransitions());
}
}