Added Context to Workflow Event
There's also a default context for the initial marking event.
This commit is contained in:
parent
812a4d5a27
commit
bfe07dda83
@ -21,6 +21,7 @@ use Twig\TwigFunction;
|
||||
* WorkflowExtension.
|
||||
*
|
||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||
* @author Carlos Pereira De Amorim <carlos@shauri.fr>
|
||||
*/
|
||||
final class WorkflowExtension extends AbstractExtension
|
||||
{
|
||||
|
@ -5,6 +5,8 @@ CHANGELOG
|
||||
-----
|
||||
|
||||
* Added `Workflow::getEnabledTransition()` to easily retrieve a specific transition object
|
||||
* Added context to the event dispatched
|
||||
* Added default context to the Initial Marking
|
||||
|
||||
5.1.0
|
||||
-----
|
||||
|
@ -19,20 +19,23 @@ use Symfony\Contracts\EventDispatcher\Event as BaseEvent;
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||
* @author Carlos Pereira De Amorim <carlos@shauri.fr>
|
||||
*/
|
||||
class Event extends BaseEvent
|
||||
{
|
||||
protected $context;
|
||||
private $subject;
|
||||
private $marking;
|
||||
private $transition;
|
||||
private $workflow;
|
||||
|
||||
public function __construct(object $subject, Marking $marking, Transition $transition = null, WorkflowInterface $workflow = null)
|
||||
public function __construct(object $subject, Marking $marking, Transition $transition = null, WorkflowInterface $workflow = null, array $context = [])
|
||||
{
|
||||
$this->subject = $subject;
|
||||
$this->marking = $marking;
|
||||
$this->transition = $transition;
|
||||
$this->workflow = $workflow;
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
public function getMarking()
|
||||
@ -64,4 +67,9 @@ class Event extends BaseEvent
|
||||
{
|
||||
return $this->workflow->getMetadataStore()->getMetadata($key, $subject);
|
||||
}
|
||||
|
||||
public function getContext(): array
|
||||
{
|
||||
return $this->context;
|
||||
}
|
||||
}
|
||||
|
@ -13,15 +13,8 @@ namespace Symfony\Component\Workflow\Event;
|
||||
|
||||
final class TransitionEvent extends Event
|
||||
{
|
||||
private $context;
|
||||
|
||||
public function setContext(array $context): void
|
||||
{
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
public function getContext(): array
|
||||
{
|
||||
return $this->context;
|
||||
}
|
||||
}
|
||||
|
@ -392,6 +392,7 @@ class WorkflowTest extends TestCase
|
||||
$eventNameExpected = [
|
||||
'workflow.entered',
|
||||
'workflow.workflow_name.entered',
|
||||
'workflow.workflow_name.entered.a',
|
||||
'workflow.guard',
|
||||
'workflow.workflow_name.guard',
|
||||
'workflow.workflow_name.guard.t1',
|
||||
@ -463,6 +464,7 @@ class WorkflowTest extends TestCase
|
||||
$eventNameExpected = [
|
||||
'workflow.entered',
|
||||
'workflow.workflow_name.entered',
|
||||
'workflow.workflow_name.entered.a',
|
||||
'workflow.guard',
|
||||
'workflow.workflow_name.guard',
|
||||
'workflow.workflow_name.guard.a-b',
|
||||
@ -533,6 +535,58 @@ class WorkflowTest extends TestCase
|
||||
$workflow->apply($subject, 't1');
|
||||
}
|
||||
|
||||
public function testEventContext()
|
||||
{
|
||||
$definition = $this->createComplexWorkflowDefinition();
|
||||
$subject = new Subject();
|
||||
$dispatcher = new EventDispatcher();
|
||||
$name = 'workflow_name';
|
||||
$context = ['context'];
|
||||
$workflow = new Workflow($definition, new MethodMarkingStore(), $dispatcher, $name);
|
||||
|
||||
$assertWorkflowContext = function (Event $event) use ($context) {
|
||||
$this->assertEquals($context, $event->getContext());
|
||||
};
|
||||
|
||||
$eventNames = [
|
||||
'workflow.leave',
|
||||
'workflow.transition',
|
||||
'workflow.enter',
|
||||
'workflow.entered',
|
||||
'workflow.announce',
|
||||
];
|
||||
|
||||
foreach ($eventNames as $eventName) {
|
||||
$dispatcher->addListener($eventName, $assertWorkflowContext);
|
||||
}
|
||||
|
||||
$workflow->apply($subject, 't1', $context);
|
||||
}
|
||||
|
||||
public function testEventDefaultInitialContext()
|
||||
{
|
||||
$definition = $this->createComplexWorkflowDefinition();
|
||||
$subject = new Subject();
|
||||
$dispatcher = new EventDispatcher();
|
||||
$name = 'workflow_name';
|
||||
$context = Workflow::DEFAULT_INITIAL_CONTEXT;
|
||||
$workflow = new Workflow($definition, new MethodMarkingStore(), $dispatcher, $name);
|
||||
|
||||
$assertWorkflowContext = function (Event $event) use ($context) {
|
||||
$this->assertEquals($context, $event->getContext());
|
||||
};
|
||||
|
||||
$eventNames = [
|
||||
'workflow.workflow_name.entered.a',
|
||||
];
|
||||
|
||||
foreach ($eventNames as $eventName) {
|
||||
$dispatcher->addListener($eventName, $assertWorkflowContext);
|
||||
}
|
||||
|
||||
$workflow->apply($subject, 't1');
|
||||
}
|
||||
|
||||
public function testMarkingStateOnApplyWithEventDispatcher()
|
||||
{
|
||||
$definition = new Definition(range('a', 'f'), [new Transition('t', range('a', 'c'), range('d', 'f'))]);
|
||||
|
@ -30,10 +30,12 @@ use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
|
||||
* @author Carlos Pereira De Amorim <carlos@shauri.fr>
|
||||
*/
|
||||
class Workflow implements WorkflowInterface
|
||||
{
|
||||
public const DISABLE_ANNOUNCE_EVENT = 'workflow_disable_announce_event';
|
||||
public const DEFAULT_INITIAL_CONTEXT = ['initial' => true];
|
||||
|
||||
private $definition;
|
||||
private $markingStore;
|
||||
@ -51,7 +53,7 @@ class Workflow implements WorkflowInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMarking(object $subject)
|
||||
public function getMarking(object $subject, array $context = [])
|
||||
{
|
||||
$marking = $this->markingStore->getMarking($subject);
|
||||
|
||||
@ -71,7 +73,11 @@ class Workflow implements WorkflowInterface
|
||||
// update the subject with the new marking
|
||||
$this->markingStore->setMarking($subject, $marking);
|
||||
|
||||
$this->entered($subject, null, $marking);
|
||||
if (!$context) {
|
||||
$context = self::DEFAULT_INITIAL_CONTEXT;
|
||||
}
|
||||
|
||||
$this->entered($subject, null, $marking, $context);
|
||||
}
|
||||
|
||||
// check that the subject has a known place
|
||||
@ -154,7 +160,7 @@ class Workflow implements WorkflowInterface
|
||||
*/
|
||||
public function apply(object $subject, string $transitionName, array $context = [])
|
||||
{
|
||||
$marking = $this->getMarking($subject);
|
||||
$marking = $this->getMarking($subject, $context);
|
||||
|
||||
$transitionExist = false;
|
||||
$approvedTransitions = [];
|
||||
@ -197,20 +203,20 @@ class Workflow implements WorkflowInterface
|
||||
}
|
||||
|
||||
foreach ($approvedTransitions as $transition) {
|
||||
$this->leave($subject, $transition, $marking);
|
||||
$this->leave($subject, $transition, $marking, $context);
|
||||
|
||||
$context = $this->transition($subject, $transition, $marking, $context);
|
||||
|
||||
$this->enter($subject, $transition, $marking);
|
||||
$this->enter($subject, $transition, $marking, $context);
|
||||
|
||||
$this->markingStore->setMarking($subject, $marking, $context);
|
||||
|
||||
$this->entered($subject, $transition, $marking);
|
||||
$this->entered($subject, $transition, $marking, $context);
|
||||
|
||||
$this->completed($subject, $transition, $marking);
|
||||
$this->completed($subject, $transition, $marking, $context);
|
||||
|
||||
if (!($context[self::DISABLE_ANNOUNCE_EVENT] ?? false)) {
|
||||
$this->announce($subject, $transition, $marking);
|
||||
$this->announce($subject, $transition, $marking, $context);
|
||||
}
|
||||
}
|
||||
|
||||
@ -324,12 +330,12 @@ class Workflow implements WorkflowInterface
|
||||
return $event;
|
||||
}
|
||||
|
||||
private function leave(object $subject, Transition $transition, Marking $marking): void
|
||||
private function leave(object $subject, Transition $transition, Marking $marking, array $context = []): void
|
||||
{
|
||||
$places = $transition->getFroms();
|
||||
|
||||
if (null !== $this->dispatcher) {
|
||||
$event = new LeaveEvent($subject, $marking, $transition, $this);
|
||||
$event = new LeaveEvent($subject, $marking, $transition, $this, $context);
|
||||
|
||||
$this->dispatcher->dispatch($event, WorkflowEvents::LEAVE);
|
||||
$this->dispatcher->dispatch($event, sprintf('workflow.%s.leave', $this->name));
|
||||
@ -350,8 +356,7 @@ class Workflow implements WorkflowInterface
|
||||
return $context;
|
||||
}
|
||||
|
||||
$event = new TransitionEvent($subject, $marking, $transition, $this);
|
||||
$event->setContext($context);
|
||||
$event = new TransitionEvent($subject, $marking, $transition, $this, $context);
|
||||
|
||||
$this->dispatcher->dispatch($event, WorkflowEvents::TRANSITION);
|
||||
$this->dispatcher->dispatch($event, sprintf('workflow.%s.transition', $this->name));
|
||||
@ -360,12 +365,12 @@ class Workflow implements WorkflowInterface
|
||||
return $event->getContext();
|
||||
}
|
||||
|
||||
private function enter(object $subject, Transition $transition, Marking $marking): void
|
||||
private function enter(object $subject, Transition $transition, Marking $marking, array $context): void
|
||||
{
|
||||
$places = $transition->getTos();
|
||||
|
||||
if (null !== $this->dispatcher) {
|
||||
$event = new EnterEvent($subject, $marking, $transition, $this);
|
||||
$event = new EnterEvent($subject, $marking, $transition, $this, $context);
|
||||
|
||||
$this->dispatcher->dispatch($event, WorkflowEvents::ENTER);
|
||||
$this->dispatcher->dispatch($event, sprintf('workflow.%s.enter', $this->name));
|
||||
@ -380,13 +385,13 @@ class Workflow implements WorkflowInterface
|
||||
}
|
||||
}
|
||||
|
||||
private function entered(object $subject, ?Transition $transition, Marking $marking): void
|
||||
private function entered(object $subject, ?Transition $transition, Marking $marking, array $context): void
|
||||
{
|
||||
if (null === $this->dispatcher) {
|
||||
return;
|
||||
}
|
||||
|
||||
$event = new EnteredEvent($subject, $marking, $transition, $this);
|
||||
$event = new EnteredEvent($subject, $marking, $transition, $this, $context);
|
||||
|
||||
$this->dispatcher->dispatch($event, WorkflowEvents::ENTERED);
|
||||
$this->dispatcher->dispatch($event, sprintf('workflow.%s.entered', $this->name));
|
||||
@ -395,29 +400,33 @@ class Workflow implements WorkflowInterface
|
||||
foreach ($transition->getTos() as $place) {
|
||||
$this->dispatcher->dispatch($event, sprintf('workflow.%s.entered.%s', $this->name, $place));
|
||||
}
|
||||
} elseif (!empty($this->definition->getInitialPlaces())) {
|
||||
foreach ($this->definition->getInitialPlaces() as $place) {
|
||||
$this->dispatcher->dispatch($event, sprintf('workflow.%s.entered.%s', $this->name, $place));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function completed(object $subject, Transition $transition, Marking $marking): void
|
||||
private function completed(object $subject, Transition $transition, Marking $marking, array $context): void
|
||||
{
|
||||
if (null === $this->dispatcher) {
|
||||
return;
|
||||
}
|
||||
|
||||
$event = new CompletedEvent($subject, $marking, $transition, $this);
|
||||
$event = new CompletedEvent($subject, $marking, $transition, $this, $context);
|
||||
|
||||
$this->dispatcher->dispatch($event, WorkflowEvents::COMPLETED);
|
||||
$this->dispatcher->dispatch($event, sprintf('workflow.%s.completed', $this->name));
|
||||
$this->dispatcher->dispatch($event, sprintf('workflow.%s.completed.%s', $this->name, $transition->getName()));
|
||||
}
|
||||
|
||||
private function announce(object $subject, Transition $initialTransition, Marking $marking): void
|
||||
private function announce(object $subject, Transition $initialTransition, Marking $marking, array $context): void
|
||||
{
|
||||
if (null === $this->dispatcher) {
|
||||
return;
|
||||
}
|
||||
|
||||
$event = new AnnounceEvent($subject, $marking, $initialTransition, $this);
|
||||
$event = new AnnounceEvent($subject, $marking, $initialTransition, $this, $context);
|
||||
|
||||
$this->dispatcher->dispatch($event, WorkflowEvents::ANNOUNCE);
|
||||
$this->dispatcher->dispatch($event, sprintf('workflow.%s.announce', $this->name));
|
||||
|
Reference in New Issue
Block a user