bug #31584 [Workflow] Do not trigger extra guards (lyrixx)

This PR was merged into the 3.4 branch.

Discussion
----------

[Workflow] Do not trigger extra guards

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #31582
| License       | MIT
| Doc PR        |

---

With this patch, guards are executed only on wanted transitions

**Note for merger**: This is already fixed (in a different manner) in 4.2, So this patch should not be included in 4.2, instead take: #31585 or discard changes of Workflow class but keep tests

Commits
-------

ad0619748e [Workflow] Do not trigger extra guard
This commit is contained in:
Fabien Potencier 2019-05-27 07:53:57 +02:00
commit c562e71d29
2 changed files with 49 additions and 16 deletions

View File

@ -304,6 +304,45 @@ class WorkflowTest extends TestCase
$this->assertSame($eventNameExpected, $eventDispatcher->dispatchedEvents);
}
public function testApplyDoesNotTriggerExtraGuardWithEventDispatcher()
{
$transitions[] = new Transition('a-b', 'a', 'b');
$transitions[] = new Transition('a-c', 'a', 'c');
$definition = new Definition(['a', 'b', 'c'], $transitions);
$subject = new \stdClass();
$subject->marking = null;
$eventDispatcher = new EventDispatcherMock();
$workflow = new Workflow($definition, new MultipleStateMarkingStore(), $eventDispatcher, 'workflow_name');
$eventNameExpected = [
'workflow.guard',
'workflow.workflow_name.guard',
'workflow.workflow_name.guard.a-b',
'workflow.leave',
'workflow.workflow_name.leave',
'workflow.workflow_name.leave.a',
'workflow.transition',
'workflow.workflow_name.transition',
'workflow.workflow_name.transition.a-b',
'workflow.enter',
'workflow.workflow_name.enter',
'workflow.workflow_name.enter.b',
'workflow.entered',
'workflow.workflow_name.entered',
'workflow.workflow_name.entered.b',
'workflow.completed',
'workflow.workflow_name.completed',
'workflow.workflow_name.completed.a-b',
'workflow.announce',
'workflow.workflow_name.announce',
];
$marking = $workflow->apply($subject, 'a-b');
$this->assertSame($eventNameExpected, $eventDispatcher->dispatchedEvents);
}
public function testEventName()
{
$definition = $this->createComplexWorkflowDefinition();

View File

@ -125,22 +125,20 @@ class Workflow
*/
public function apply($subject, $transitionName)
{
$transitions = $this->getEnabledTransitions($subject);
$marking = $this->getMarking($subject);
$transitions = [];
// We can shortcut the getMarking method in order to boost performance,
// since the "getEnabledTransitions" method already checks the Marking
// state
$marking = $this->markingStore->getMarking($subject);
foreach ($this->definition->getTransitions() as $transition) {
if ($transitionName === $transition->getName() && $this->doCan($subject, $marking, $transition)) {
$transitions[] = $transition;
}
}
$applied = false;
if (!$transitions) {
throw new LogicException(sprintf('Unable to apply transition "%s" for workflow "%s".', $transitionName, $this->name));
}
foreach ($transitions as $transition) {
if ($transitionName !== $transition->getName()) {
continue;
}
$applied = true;
$this->leave($subject, $transition, $marking);
$this->transition($subject, $transition, $marking);
@ -156,10 +154,6 @@ class Workflow
$this->announce($subject, $transition, $marking);
}
if (!$applied) {
throw new LogicException(sprintf('Unable to apply transition "%s" for workflow "%s".', $transitionName, $this->name));
}
return $marking;
}