Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c6a786d

Browse filesBrowse files
committed
[Workflow] Cleaned the transition blocker implementations
1 parent edbcb6e commit c6a786d
Copy full SHA for c6a786d

9 files changed

+208
-357
lines changed

‎src/Symfony/Component/Workflow/Event/GuardEvent.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Workflow/Event/GuardEvent.php
+3-3Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,18 @@ public function __construct($subject, Marking $marking, Transition $transition,
3636

3737
public function isBlocked(): bool
3838
{
39-
return 0 !== count($this->transitionBlockerList);
39+
return !$this->transitionBlockerList->isEmpty();
4040
}
4141

4242
public function setBlocked(bool $blocked): void
4343
{
4444
if (!$blocked) {
45-
$this->transitionBlockerList = new TransitionBlockerList();
45+
$this->transitionBlockerList->reset();
4646

4747
return;
4848
}
4949

50-
$this->transitionBlockerList->add(TransitionBlocker::createUnknownReason($this->getTransition()->getName()));
50+
$this->transitionBlockerList->add(TransitionBlocker::createUnknown());
5151
}
5252

5353
public function getTransitionBlockerList(): TransitionBlockerList

‎src/Symfony/Component/Workflow/EventListener/GuardListener.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Workflow/EventListener/GuardListener.php
+6-2Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Symfony\Component\Validator\Validator\ValidatorInterface;
1919
use Symfony\Component\Workflow\Event\GuardEvent;
2020
use Symfony\Component\Workflow\Exception\InvalidTokenConfigurationException;
21+
use Symfony\Component\Workflow\TransitionBlocker;
2122

2223
/**
2324
* @author Grégoire Pineau <lyrixx@lyrixx.info>
@@ -49,8 +50,11 @@ public function onTransition(GuardEvent $event, $eventName)
4950
return;
5051
}
5152

52-
if (!$this->expressionLanguage->evaluate($this->configuration[$eventName], $this->getVariables($event))) {
53-
$event->setBlocked(true);
53+
$expression = $this->configuration[$eventName];
54+
55+
if (!$this->expressionLanguage->evaluate($expression, $this->getVariables($event))) {
56+
$blocker = TransitionBlocker::createBlockedByExpressionGuardListener($expression);
57+
$event->addTransitionBlocker($blocker);
5458
}
5559
}
5660

‎src/Symfony/Component/Workflow/Exception/BlockedTransitionException.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Workflow/Exception/BlockedTransitionException.php
-34Lines changed: 0 additions & 34 deletions
This file was deleted.

‎src/Symfony/Component/Workflow/Exception/UndefinedTransitionException.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Workflow/Exception/UndefinedTransitionException.php
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,13 @@
1313

1414
/**
1515
* Thrown by Workflow when an undefined transition is applied on a subject.
16+
*
17+
* @author Grégoire Pineau <lyrixx@lyrixx.info>
1618
*/
1719
class UndefinedTransitionException extends LogicException
1820
{
21+
public function __construct(string $transitionName, string $workflowName)
22+
{
23+
parent::__construct(sprintf('The transition "%s" is not defined for the workflow "%s".', $transitionName, $workflowName));
24+
}
1925
}

‎src/Symfony/Component/Workflow/Tests/WorkflowTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Workflow/Tests/WorkflowTest.php
+79-125Lines changed: 79 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use Symfony\Component\Workflow\Definition;
88
use Symfony\Component\Workflow\Event\Event;
99
use Symfony\Component\Workflow\Event\GuardEvent;
10-
use Symfony\Component\Workflow\Exception\BlockedTransitionException;
10+
use Symfony\Component\Workflow\Exception\UndefinedTransitionException;
1111
use Symfony\Component\Workflow\Marking;
1212
use Symfony\Component\Workflow\MarkingStore\MarkingStoreInterface;
1313
use Symfony\Component\Workflow\MarkingStore\MultipleStateMarkingStore;
@@ -164,20 +164,6 @@ public function testCanDoesNotTriggerGuardEventsForNotEnabledTransitions()
164164
$this->assertSame(array('workflow_name.guard.t3'), $dispatchedEvents);
165165
}
166166

167-
/**
168-
* @expectedException \Symfony\Component\Workflow\Exception\LogicException
169-
* @expectedExceptionMessage Unable to apply transition "t2" for workflow "unnamed".
170-
*/
171-
public function testApplyWithImpossibleTransition()
172-
{
173-
$definition = $this->createComplexWorkflowDefinition();
174-
$subject = new \stdClass();
175-
$subject->marking = null;
176-
$workflow = new Workflow($definition, new MultipleStateMarkingStore());
177-
178-
$workflow->apply($subject, 't2');
179-
}
180-
181167
public function testCanWithSameNameTransition()
182168
{
183169
$definition = $this->createWorkflowWithSameNameTransition();
@@ -195,6 +181,84 @@ public function testCanWithSameNameTransition()
195181
$this->assertTrue($workflow->can($subject, 'to_a'));
196182
}
197183

184+
public function testBuildTransitionBlockerListReturnsUndefinedTransition()
185+
{
186+
$definition = $this->createSimpleWorkflowDefinition();
187+
$subject = new \stdClass();
188+
$subject->marking = null;
189+
$workflow = new Workflow($definition);
190+
191+
try {
192+
$workflow->buildTransitionBlockerList($subject, 'not defined');
193+
194+
$this->fail('Workflow failed to throw undefined transition exception.');
195+
} catch (\Exception $e) {
196+
$this->assertInstanceOf(UndefinedTransitionException::class, $e);
197+
}
198+
199+
$this->assertSame('The transition "not defined" is not defined for the workflow "unnamed".', $e->getMessage());
200+
}
201+
202+
public function testBuildTransitionBlockerListReturnsReasonsProvidedByMarking()
203+
{
204+
$definition = $this->createComplexWorkflowDefinition();
205+
$subject = new \stdClass();
206+
$subject->marking = null;
207+
$workflow = new Workflow($definition, new MultipleStateMarkingStore());
208+
209+
$transitionBlockerList = $workflow->buildTransitionBlockerList($subject, 't2');
210+
$this->assertCount(1, $transitionBlockerList);
211+
$blockers = iterator_to_array($transitionBlockerList);
212+
$this->assertSame('The marking does not enabled the transition.', $blockers[0]->getMessage());
213+
$this->assertSame('19beefc8-6b1e-4716-9d07-a39bd6d16e34', $blockers[0]->getCode());
214+
}
215+
216+
public function testBuildTransitionBlockerListReturnsReasonsProvidedInGuards()
217+
{
218+
$definition = $this->createSimpleWorkflowDefinition();
219+
$subject = new \stdClass();
220+
$subject->marking = null;
221+
$dispatcher = new EventDispatcher();
222+
$workflow = new Workflow($definition, new MultipleStateMarkingStore(), $dispatcher);
223+
224+
$dispatcher->addListener('workflow.guard', function (GuardEvent $event) {
225+
$event->addTransitionBlocker(new TransitionBlocker('Transition blocker 1', 'blocker_1'));
226+
$event->addTransitionBlocker(new TransitionBlocker('Transition blocker 2', 'blocker_2'));
227+
});
228+
$dispatcher->addListener('workflow.guard', function (GuardEvent $event) {
229+
$event->addTransitionBlocker(new TransitionBlocker('Transition blocker 3', 'blocker_3'));
230+
});
231+
$dispatcher->addListener('workflow.guard', function (GuardEvent $event) {
232+
$event->setBlocked(true);
233+
});
234+
235+
$transitionBlockerList = $workflow->buildTransitionBlockerList($subject, 't1');
236+
$this->assertCount(4, $transitionBlockerList);
237+
$blockers = iterator_to_array($transitionBlockerList);
238+
$this->assertSame('Transition blocker 1', $blockers[0]->getMessage());
239+
$this->assertSame('blocker_1', $blockers[0]->getCode());
240+
$this->assertSame('Transition blocker 2', $blockers[1]->getMessage());
241+
$this->assertSame('blocker_2', $blockers[1]->getCode());
242+
$this->assertSame('Transition blocker 3', $blockers[2]->getMessage());
243+
$this->assertSame('blocker_3', $blockers[2]->getCode());
244+
$this->assertSame('Unknown reason.', $blockers[3]->getMessage());
245+
$this->assertSame('e8b5bbb9-5913-4b98-bfa6-65dbd228a82a', $blockers[3]->getCode());
246+
}
247+
248+
/**
249+
* @expectedException \Symfony\Component\Workflow\Exception\LogicException
250+
* @expectedExceptionMessage Unable to apply transition "t2" for workflow "unnamed".
251+
*/
252+
public function testApplyWithImpossibleTransition()
253+
{
254+
$definition = $this->createComplexWorkflowDefinition();
255+
$subject = new \stdClass();
256+
$subject->marking = null;
257+
$workflow = new Workflow($definition, new MultipleStateMarkingStore());
258+
259+
$workflow->apply($subject, 't2');
260+
}
261+
198262
public function testApply()
199263
{
200264
$definition = $this->createComplexWorkflowDefinition();
@@ -413,116 +477,6 @@ public function testGetEnabledTransitionsWithSameNameTransition()
413477
$this->assertSame('to_a', $transitions[1]->getName());
414478
$this->assertSame('to_a', $transitions[2]->getName());
415479
}
416-
417-
public function testWhyCannotReturnsReasonsProvidedInGuards()
418-
{
419-
$definition = $this->createSimpleWorkflowDefinition();
420-
$subject = new \stdClass();
421-
$subject->marking = null;
422-
$dispatcher = new EventDispatcher();
423-
$workflow = new Workflow($definition, new MultipleStateMarkingStore(), $dispatcher);
424-
425-
$guardsAddingTransitionBlockers = array(
426-
function (GuardEvent $event) {
427-
$event->addTransitionBlocker(new TransitionBlocker('Transition blocker 1', 'blocker_1'));
428-
$event->addTransitionBlocker(new TransitionBlocker('Transition blocker 2', 'blocker_2'));
429-
},
430-
function (GuardEvent $event) {
431-
$event->addTransitionBlocker(new TransitionBlocker('Transition blocker 3', 'blocker_3'));
432-
},
433-
);
434-
435-
foreach ($guardsAddingTransitionBlockers as $guard) {
436-
$dispatcher->addListener('workflow.guard', $guard);
437-
}
438-
439-
$transitionBlockerList = $workflow->buildTransitionBlockerList($subject, 't1');
440-
441-
$this->assertCount(3, $transitionBlockerList);
442-
443-
$assertTransitionBlockerPresentByCodeFn = function (string $code) use ($transitionBlockerList) {
444-
$this->assertNotNull(
445-
$transitionBlockerList->findByCode($code),
446-
sprintf('Workflow did not produce transition blocker with code "%s"', $code)
447-
);
448-
};
449-
450-
$assertTransitionBlockerPresentByCodeFn('blocker_1');
451-
$assertTransitionBlockerPresentByCodeFn('blocker_2');
452-
$assertTransitionBlockerPresentByCodeFn('blocker_3');
453-
}
454-
455-
public function testWhyCannotReturnsTransitionNotDefinedReason()
456-
{
457-
$definition = $this->createSimpleWorkflowDefinition();
458-
$subject = new \stdClass();
459-
$subject->marking = null;
460-
$workflow = new Workflow($definition);
461-
462-
$transitionBlockerList = $workflow->buildTransitionBlockerList($subject, 'undefined_transition_name');
463-
464-
$this->assertCount(1, $transitionBlockerList);
465-
$this->assertEquals(
466-
TransitionBlocker::REASON_TRANSITION_NOT_DEFINED,
467-
$transitionBlockerList->get(0)->getCode()
468-
);
469-
}
470-
471-
public function testWhyCannotReturnsTransitionNotApplicableReason()
472-
{
473-
$definition = $this->createSimpleWorkflowDefinition();
474-
$subject = new \stdClass();
475-
$subject->marking = null;
476-
$workflow = new Workflow($definition);
477-
478-
$transitionBlockerList = $workflow->buildTransitionBlockerList($subject, 't2');
479-
480-
$this->assertCount(1, $transitionBlockerList);
481-
$this->assertEquals(
482-
TransitionBlocker::REASON_TRANSITION_NOT_APPLICABLE,
483-
$transitionBlockerList->get(0)->getCode()
484-
);
485-
}
486-
487-
public function testApplyConveysTheTransitionBlockers()
488-
{
489-
$definition = $this->createSimpleWorkflowDefinition();
490-
$subject = new \stdClass();
491-
$subject->marking = null;
492-
$dispatcher = new EventDispatcher();
493-
$workflow = new Workflow($definition, new MultipleStateMarkingStore(), $dispatcher);
494-
495-
$dispatcher->addListener('workflow.guard', function (GuardEvent $event) {
496-
$event->addTransitionBlocker(new TransitionBlocker('Transition blocker 3', 'blocker_1'));
497-
});
498-
499-
try {
500-
$workflow->apply($subject, 't1');
501-
} catch (BlockedTransitionException $exception) {
502-
$this->assertNotNull(
503-
$exception->getTransitionBlockerList()->findByCode('blocker_1'),
504-
'Workflow failed to convey it could not transition subject because of expected blocker'
505-
);
506-
507-
return;
508-
}
509-
510-
$this->fail('Workflow failed to prevent a transition from happening');
511-
}
512-
513-
/**
514-
* @expectedException \Symfony\Component\Workflow\Exception\UndefinedTransitionException
515-
* @expectedExceptionMessage Transition "undefined_transition" is not defined in workflow "unnamed".
516-
*/
517-
public function testApplyWithUndefinedTransition()
518-
{
519-
$definition = $this->createSimpleWorkflowDefinition();
520-
$subject = new \stdClass();
521-
$subject->marking = null;
522-
$workflow = new Workflow($definition);
523-
524-
$workflow->apply($subject, 'undefined_transition');
525-
}
526480
}
527481

528482
class EventDispatcherMock implements \Symfony\Component\EventDispatcher\EventDispatcherInterface

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.