Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5d364bd

Browse files
committed
[Workflow] Cleaned the transition blocker implementations
1 parent edbcb6e commit 5d364bd

9 files changed

Lines changed: 206 additions & 355 deletions

File tree

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

Lines 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

Lines 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 <[email protected]>
@@ -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

Lines changed: 0 additions & 34 deletions
This file was deleted.

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

Lines 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 <[email protected]>
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

Lines 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)