diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow.php
index 134bb6d33487..6eae2b16c411 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow.php
@@ -25,6 +25,7 @@
abstract_arg('marking store'),
service('event_dispatcher')->ignoreOnInvalid(),
abstract_arg('workflow name'),
+ abstract_arg('events to dispatch'),
])
->abstract()
->public()
@@ -34,6 +35,7 @@
abstract_arg('marking store'),
service('event_dispatcher')->ignoreOnInvalid(),
abstract_arg('workflow name'),
+ abstract_arg('events to dispatch'),
])
->abstract()
->public()
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_no_events_to_dispatch.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_no_events_to_dispatch.php
new file mode 100644
index 000000000000..0ae6ac69ee7c
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_no_events_to_dispatch.php
@@ -0,0 +1,42 @@
+loadFromExtension('framework', [
+ 'workflows' => [
+ 'my_workflow' => [
+ 'type' => 'state_machine',
+ 'marking_store' => [
+ 'type' => 'method',
+ 'property' => 'state'
+ ],
+ 'supports' => [
+ FrameworkExtensionTest::class,
+ ],
+ 'events_to_dispatch' => [],
+ 'places' => [
+ 'one',
+ 'two',
+ 'three',
+ ],
+ 'transitions' => [
+ 'count_to_two' => [
+ 'from' => [
+ 'one',
+ ],
+ 'to' => [
+ 'two',
+ ],
+ ],
+ 'count_to_three' => [
+ 'from' => [
+ 'two',
+ ],
+ 'to' => [
+ 'three'
+ ]
+ ]
+ ],
+ ],
+ ],
+]);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_specified_events_to_dispatch.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_specified_events_to_dispatch.php
new file mode 100644
index 000000000000..259ee5087ff2
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_specified_events_to_dispatch.php
@@ -0,0 +1,45 @@
+loadFromExtension('framework', [
+ 'workflows' => [
+ 'my_workflow' => [
+ 'type' => 'state_machine',
+ 'marking_store' => [
+ 'type' => 'method',
+ 'property' => 'state'
+ ],
+ 'supports' => [
+ FrameworkExtensionTest::class,
+ ],
+ 'events_to_dispatch' => [
+ 'workflow.leave',
+ 'workflow.completed',
+ ],
+ 'places' => [
+ 'one',
+ 'two',
+ 'three',
+ ],
+ 'transitions' => [
+ 'count_to_two' => [
+ 'from' => [
+ 'one',
+ ],
+ 'to' => [
+ 'two',
+ ],
+ ],
+ 'count_to_three' => [
+ 'from' => [
+ 'two',
+ ],
+ 'to' => [
+ 'three'
+ ]
+ ]
+ ],
+ ],
+ ],
+]);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_no_events_to_dispatch.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_no_events_to_dispatch.xml
new file mode 100644
index 000000000000..2f563da4bf96
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_no_events_to_dispatch.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+ one
+
+ Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest
+
+
+
+
+
+ one
+ two
+
+
+ two
+ three
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_specified_events_to_dispatch.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_specified_events_to_dispatch.xml
new file mode 100644
index 000000000000..d442828f8cfb
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_specified_events_to_dispatch.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+ one
+
+ Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest
+ workflow.leave
+ workflow.completed
+
+
+
+
+ one
+ two
+
+
+ two
+ three
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_no_events_to_dispatch.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_no_events_to_dispatch.yml
new file mode 100644
index 000000000000..e0a281f27db4
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_no_events_to_dispatch.yml
@@ -0,0 +1,22 @@
+framework:
+ workflows:
+ my_workflow:
+ type: state_machine
+ initial_marking: one
+ events_to_dispatch: []
+ marking_store:
+ type: method
+ property: state
+ supports:
+ - Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest
+ places:
+ - one
+ - two
+ - three
+ transitions:
+ count_to_two:
+ from: one
+ to: two
+ count_to_three:
+ from: two
+ to: three
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_specified_events_to_dispatch.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_specified_events_to_dispatch.yml
new file mode 100644
index 000000000000..d5ff3d5e5fe0
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_specified_events_to_dispatch.yml
@@ -0,0 +1,22 @@
+framework:
+ workflows:
+ my_workflow:
+ type: state_machine
+ initial_marking: one
+ events_to_dispatch: ['workflow.leave', 'workflow.completed']
+ marking_store:
+ type: method
+ property: state
+ supports:
+ - Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest
+ places:
+ - one
+ - two
+ - three
+ transitions:
+ count_to_two:
+ from: one
+ to: two
+ count_to_three:
+ from: two
+ to: three
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
index cfe9f555e77b..7818d3c9c798 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
@@ -55,6 +55,7 @@
use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass;
use Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader;
use Symfony\Component\Workflow;
+use Symfony\Component\Workflow\WorkflowEvents;
abstract class FrameworkExtensionTest extends TestCase
{
@@ -216,6 +217,8 @@ public function testWorkflows()
$this->assertTrue($container->hasDefinition('workflow.article'), 'Workflow is registered as a service');
$this->assertSame('workflow.abstract', $container->getDefinition('workflow.article')->getParent());
+ $this->assertNull($container->getDefinition('workflow.article')->getArgument('index_4'), 'Workflows has eventsToDispatch=null');
+
$this->assertTrue($container->hasDefinition('workflow.article.definition'), 'Workflow definition is registered as a service');
$workflowDefinition = $container->getDefinition('workflow.article.definition');
@@ -423,6 +426,24 @@ public function testWorkflowsNamedExplicitlyEnabled()
$this->assertTrue($container->hasDefinition('workflow.workflows.definition'));
}
+ public function testWorkflowsWithNoDispatchedEvents()
+ {
+ $container = $this->createContainerFromFile('workflow_with_no_events_to_dispatch');
+
+ $eventsToDispatch = $container->getDefinition('state_machine.my_workflow')->getArgument('index_4');
+
+ $this->assertSame([], $eventsToDispatch);
+ }
+
+ public function testWorkflowsWithSpecifiedDispatchedEvents()
+ {
+ $container = $this->createContainerFromFile('workflow_with_specified_events_to_dispatch');
+
+ $eventsToDispatch = $container->getDefinition('state_machine.my_workflow')->getArgument('index_4');
+
+ $this->assertSame([WorkflowEvents::LEAVE, WorkflowEvents::COMPLETED], $eventsToDispatch);
+ }
+
public function testEnabledPhpErrorsConfig()
{
$container = $this->createContainerFromFile('php_errors_enabled');
diff --git a/src/Symfony/Component/Workflow/CHANGELOG.md b/src/Symfony/Component/Workflow/CHANGELOG.md
index 263f2db5e803..3d44a3b6e83f 100644
--- a/src/Symfony/Component/Workflow/CHANGELOG.md
+++ b/src/Symfony/Component/Workflow/CHANGELOG.md
@@ -8,6 +8,7 @@ CHANGELOG
* Added context to the event dispatched
* Dispatch an event when the subject enters in the workflow for the very first time
* Added a default context to the previous event
+ * Added support for specifying which events should be dispatched when calling `workflow->apply()`
5.1.0
-----
diff --git a/src/Symfony/Component/Workflow/Tests/WorkflowTest.php b/src/Symfony/Component/Workflow/Tests/WorkflowTest.php
index 85543f928686..1c6a3ebd0327 100644
--- a/src/Symfony/Component/Workflow/Tests/WorkflowTest.php
+++ b/src/Symfony/Component/Workflow/Tests/WorkflowTest.php
@@ -16,6 +16,7 @@
use Symfony\Component\Workflow\Transition;
use Symfony\Component\Workflow\TransitionBlocker;
use Symfony\Component\Workflow\Workflow;
+use Symfony\Component\Workflow\WorkflowEvents;
class WorkflowTest extends TestCase
{
@@ -451,6 +452,81 @@ public function testApplyWithEventDispatcherForAnnounce(bool $fired, array $cont
}
}
+ public function testApplyDispatchesWithDisableEventInContext()
+ {
+ $transitions[] = new Transition('a-b', 'a', 'b');
+ $transitions[] = new Transition('a-c', 'a', 'c');
+ $definition = new Definition(['a', 'b', 'c'], $transitions);
+
+ $subject = new Subject();
+ $eventDispatcher = new EventDispatcherMock();
+ $workflow = new Workflow($definition, new MethodMarkingStore(), $eventDispatcher, 'workflow_name');
+
+ $eventNameExpected = [
+ 'workflow.guard',
+ 'workflow.workflow_name.guard',
+ 'workflow.workflow_name.guard.a-b',
+ 'workflow.transition',
+ 'workflow.workflow_name.transition',
+ 'workflow.workflow_name.transition.a-b',
+ ];
+
+ $workflow->apply($subject, 'a-b', [
+ Workflow::DISABLE_LEAVE_EVENT => true,
+ Workflow::DISABLE_ENTER_EVENT => true,
+ Workflow::DISABLE_ENTERED_EVENT => true,
+ Workflow::DISABLE_COMPLETED_EVENT => true,
+ Workflow::DISABLE_ANNOUNCE_EVENT => true,
+ ]);
+
+ $this->assertSame($eventNameExpected, $eventDispatcher->dispatchedEvents);
+ }
+
+ public function testApplyDispatchesNoEventsWhenSpecifiedByDefinition()
+ {
+ $transitions[] = new Transition('a-b', 'a', 'b');
+ $transitions[] = new Transition('a-c', 'a', 'c');
+ $definition = new Definition(['a', 'b', 'c'], $transitions);
+
+ $subject = new Subject();
+ $eventDispatcher = new EventDispatcherMock();
+ $workflow = new Workflow($definition, new MethodMarkingStore(), $eventDispatcher, 'workflow_name', []);
+
+ $eventNameExpected = [
+ 'workflow.guard',
+ 'workflow.workflow_name.guard',
+ 'workflow.workflow_name.guard.a-b',
+ ];
+
+ $workflow->apply($subject, 'a-b');
+
+ $this->assertSame($eventNameExpected, $eventDispatcher->dispatchedEvents);
+ }
+
+ public function testApplyOnlyDispatchesEventsThatHaveBeenSpecifiedByDefinition()
+ {
+ $transitions[] = new Transition('a-b', 'a', 'b');
+ $transitions[] = new Transition('a-c', 'a', 'c');
+ $definition = new Definition(['a', 'b', 'c'], $transitions);
+
+ $subject = new Subject();
+ $eventDispatcher = new EventDispatcherMock();
+ $workflow = new Workflow($definition, new MethodMarkingStore(), $eventDispatcher, 'workflow_name', [WorkflowEvents::COMPLETED]);
+
+ $eventNameExpected = [
+ 'workflow.guard',
+ 'workflow.workflow_name.guard',
+ 'workflow.workflow_name.guard.a-b',
+ 'workflow.completed',
+ 'workflow.workflow_name.completed',
+ 'workflow.workflow_name.completed.a-b',
+ ];
+
+ $workflow->apply($subject, 'a-b');
+
+ $this->assertSame($eventNameExpected, $eventDispatcher->dispatchedEvents);
+ }
+
public function testApplyDoesNotTriggerExtraGuardWithEventDispatcher()
{
$transitions[] = new Transition('a-b', 'a', 'b');
diff --git a/src/Symfony/Component/Workflow/Workflow.php b/src/Symfony/Component/Workflow/Workflow.php
index 4220c4323391..00abecd4f153 100644
--- a/src/Symfony/Component/Workflow/Workflow.php
+++ b/src/Symfony/Component/Workflow/Workflow.php
@@ -34,20 +34,46 @@
*/
class Workflow implements WorkflowInterface
{
+ public const DISABLE_LEAVE_EVENT = 'workflow_disable_leave_event';
+ public const DISABLE_TRANSITION_EVENT = 'workflow_disable_transition_event';
+ public const DISABLE_ENTER_EVENT = 'workflow_disable_enter_event';
+ public const DISABLE_ENTERED_EVENT = 'workflow_disable_entered_event';
+ public const DISABLE_COMPLETED_EVENT = 'workflow_disable_completed_event';
public const DISABLE_ANNOUNCE_EVENT = 'workflow_disable_announce_event';
+
public const DEFAULT_INITIAL_CONTEXT = ['initial' => true];
+ private const DISABLE_EVENTS_MAPPING = [
+ WorkflowEvents::LEAVE => self::DISABLE_LEAVE_EVENT,
+ WorkflowEvents::TRANSITION => self::DISABLE_TRANSITION_EVENT,
+ WorkflowEvents::ENTER => self::DISABLE_ENTER_EVENT,
+ WorkflowEvents::ENTERED => self::DISABLE_ENTERED_EVENT,
+ WorkflowEvents::COMPLETED => self::DISABLE_COMPLETED_EVENT,
+ WorkflowEvents::ANNOUNCE => self::DISABLE_ANNOUNCE_EVENT,
+ ];
+
private $definition;
private $markingStore;
private $dispatcher;
private $name;
- public function __construct(Definition $definition, MarkingStoreInterface $markingStore = null, EventDispatcherInterface $dispatcher = null, string $name = 'unnamed')
+ /**
+ * When `null` fire all events (the default behaviour).
+ * Setting this to an empty array `[]` means no events are dispatched (except the Guard Event).
+ * Passing an array with WorkflowEvents will allow only those events to be dispatched plus
+ * the Guard Event.
+ *
+ * @var array|string[]|null
+ */
+ private $eventsToDispatch = null;
+
+ public function __construct(Definition $definition, MarkingStoreInterface $markingStore = null, EventDispatcherInterface $dispatcher = null, string $name = 'unnamed', array $eventsToDispatch = null)
{
$this->definition = $definition;
$this->markingStore = $markingStore ?: new MethodMarkingStore();
$this->dispatcher = $dispatcher;
$this->name = $name;
+ $this->eventsToDispatch = $eventsToDispatch;
}
/**
@@ -215,9 +241,7 @@ public function apply(object $subject, string $transitionName, array $context =
$this->completed($subject, $transition, $marking, $context);
- if (!($context[self::DISABLE_ANNOUNCE_EVENT] ?? false)) {
- $this->announce($subject, $transition, $marking, $context);
- }
+ $this->announce($subject, $transition, $marking, $context);
}
return $marking;
@@ -334,7 +358,7 @@ private function leave(object $subject, Transition $transition, Marking $marking
{
$places = $transition->getFroms();
- if (null !== $this->dispatcher) {
+ if ($this->shouldDispatchEvent(WorkflowEvents::LEAVE, $context)) {
$event = new LeaveEvent($subject, $marking, $transition, $this, $context);
$this->dispatcher->dispatch($event, WorkflowEvents::LEAVE);
@@ -352,7 +376,7 @@ private function leave(object $subject, Transition $transition, Marking $marking
private function transition(object $subject, Transition $transition, Marking $marking, array $context): array
{
- if (null === $this->dispatcher) {
+ if (!$this->shouldDispatchEvent(WorkflowEvents::TRANSITION, $context)) {
return $context;
}
@@ -369,7 +393,7 @@ private function enter(object $subject, Transition $transition, Marking $marking
{
$places = $transition->getTos();
- if (null !== $this->dispatcher) {
+ if ($this->shouldDispatchEvent(WorkflowEvents::ENTER, $context)) {
$event = new EnterEvent($subject, $marking, $transition, $this, $context);
$this->dispatcher->dispatch($event, WorkflowEvents::ENTER);
@@ -387,7 +411,7 @@ private function enter(object $subject, Transition $transition, Marking $marking
private function entered(object $subject, ?Transition $transition, Marking $marking, array $context): void
{
- if (null === $this->dispatcher) {
+ if (!$this->shouldDispatchEvent(WorkflowEvents::ENTERED, $context)) {
return;
}
@@ -403,7 +427,7 @@ private function entered(object $subject, ?Transition $transition, Marking $mark
private function completed(object $subject, Transition $transition, Marking $marking, array $context): void
{
- if (null === $this->dispatcher) {
+ if (!$this->shouldDispatchEvent(WorkflowEvents::COMPLETED, $context)) {
return;
}
@@ -416,7 +440,7 @@ private function completed(object $subject, Transition $transition, Marking $mar
private function announce(object $subject, Transition $initialTransition, Marking $marking, array $context): void
{
- if (null === $this->dispatcher) {
+ if (!$this->shouldDispatchEvent(WorkflowEvents::ANNOUNCE, $context)) {
return;
}
@@ -429,4 +453,25 @@ private function announce(object $subject, Transition $initialTransition, Markin
$this->dispatcher->dispatch($event, sprintf('workflow.%s.announce.%s', $this->name, $transition->getName()));
}
}
+
+ private function shouldDispatchEvent(string $eventName, array $context): bool
+ {
+ if (null === $this->dispatcher) {
+ return false;
+ }
+
+ if ($context[self::DISABLE_EVENTS_MAPPING[$eventName]] ?? false) {
+ return false;
+ }
+
+ if (null === $this->eventsToDispatch) {
+ return true;
+ }
+
+ if ([] === $this->eventsToDispatch) {
+ return false;
+ }
+
+ return \in_array($eventName, $this->eventsToDispatch, true);
+ }
}
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy