diff --git a/src/Symfony/Component/Workflow/CHANGELOG.md b/src/Symfony/Component/Workflow/CHANGELOG.md index c3869c0424..5a32b915e5 100644 --- a/src/Symfony/Component/Workflow/CHANGELOG.md +++ b/src/Symfony/Component/Workflow/CHANGELOG.md @@ -6,6 +6,7 @@ CHANGELOG * Trigger `entered` event for subject entering in the Workflow for the first time. * Added a context to `Workflow::apply()`. The `MethodMarkingStore` could be used to leverage this feature. + * The `TransitionEvent` is able to modify the context. * Add style to transitions by declaring metadata: use Symfony\Component\Workflow\Definition; diff --git a/src/Symfony/Component/Workflow/Event/TransitionEvent.php b/src/Symfony/Component/Workflow/Event/TransitionEvent.php index d45583fc1e..424518453d 100644 --- a/src/Symfony/Component/Workflow/Event/TransitionEvent.php +++ b/src/Symfony/Component/Workflow/Event/TransitionEvent.php @@ -13,4 +13,15 @@ namespace Symfony\Component\Workflow\Event; class TransitionEvent extends Event { + private $context; + + public function setContext(array $context) + { + $this->context = $context; + } + + public function getContext(): array + { + return $this->context; + } } diff --git a/src/Symfony/Component/Workflow/Tests/Subject.php b/src/Symfony/Component/Workflow/Tests/Subject.php index fafb167ee7..944cb228d6 100644 --- a/src/Symfony/Component/Workflow/Tests/Subject.php +++ b/src/Symfony/Component/Workflow/Tests/Subject.php @@ -5,10 +5,12 @@ namespace Symfony\Component\Workflow\Tests; final class Subject { private $marking; + private $context; public function __construct($marking = null) { $this->marking = $marking; + $this->context = []; } public function getMarking() @@ -16,8 +18,14 @@ final class Subject return $this->marking; } - public function setMarking($marking) + public function setMarking($marking, array $context = []) { $this->marking = $marking; + $this->context = $context; + } + + public function getContext(): array + { + return $this->context; } } diff --git a/src/Symfony/Component/Workflow/Tests/WorkflowTest.php b/src/Symfony/Component/Workflow/Tests/WorkflowTest.php index 8762656a45..eb49b8d5fd 100644 --- a/src/Symfony/Component/Workflow/Tests/WorkflowTest.php +++ b/src/Symfony/Component/Workflow/Tests/WorkflowTest.php @@ -7,6 +7,7 @@ use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Workflow\Definition; use Symfony\Component\Workflow\Event\Event; use Symfony\Component\Workflow\Event\GuardEvent; +use Symfony\Component\Workflow\Event\TransitionEvent; use Symfony\Component\Workflow\Exception\NotEnabledTransitionException; use Symfony\Component\Workflow\Marking; use Symfony\Component\Workflow\MarkingStore\MarkingStoreInterface; @@ -418,6 +419,21 @@ class WorkflowTest extends TestCase $this->assertSame($eventNameExpected, $eventDispatcher->dispatchedEvents); } + public function testApplyWithContext() + { + $definition = $this->createComplexWorkflowDefinition(); + $subject = new Subject(); + $eventDispatcher = new EventDispatcher(); + $eventDispatcher->addListener('workflow.transition', function (TransitionEvent $event) { + $event->setContext(array_merge($event->getContext(), ['user' => 'admin'])); + }); + $workflow = new Workflow($definition, new MethodMarkingStore(), $eventDispatcher); + + $workflow->apply($subject, 't1', ['foo' => 'bar']); + + $this->assertSame(['foo' => 'bar', 'user' => 'admin'], $subject->getContext()); + } + public function testEventName() { $definition = $this->createComplexWorkflowDefinition(); diff --git a/src/Symfony/Component/Workflow/Workflow.php b/src/Symfony/Component/Workflow/Workflow.php index 188d69e7d3..e3df8cb0d0 100644 --- a/src/Symfony/Component/Workflow/Workflow.php +++ b/src/Symfony/Component/Workflow/Workflow.php @@ -176,7 +176,7 @@ class Workflow implements WorkflowInterface $this->leave($subject, $transition, $marking); - $this->transition($subject, $transition, $marking); + $context = $this->transition($subject, $transition, $marking, $context); $this->enter($subject, $transition, $marking); @@ -308,17 +308,20 @@ class Workflow implements WorkflowInterface } } - private function transition($subject, Transition $transition, Marking $marking): void + private function transition($subject, Transition $transition, Marking $marking, array $context): array { if (null === $this->dispatcher) { - return; + return $context; } $event = new TransitionEvent($subject, $marking, $transition, $this); + $event->setContext($context); $this->dispatcher->dispatch($event, WorkflowEvents::TRANSITION); $this->dispatcher->dispatch($event, sprintf('workflow.%s.transition', $this->name)); $this->dispatcher->dispatch($event, sprintf('workflow.%s.transition.%s', $this->name, $transition->getName())); + + return $event->getContext(); } private function enter($subject, Transition $transition, Marking $marking): void