Skip to content

Navigation Menu

Sign in
Appearance settings

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 0a86f50

Browse filesBrowse files
committed
[Worflow] Add partial support for marking with more than one token per place
1 parent 87186b2 commit 0a86f50
Copy full SHA for 0a86f50

File tree

6 files changed

+177
-10
lines changed
Filter options

6 files changed

+177
-10
lines changed

‎src/Symfony/Component/Workflow/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Component/Workflow/CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ CHANGELOG
1212
* Require explicit argument when calling `Definition::setInitialPlaces()`
1313
* `GuardEvent::getContext()` method has been removed. Method was not supposed to be called within guard event listeners as it always returned an empty array anyway.
1414
* Remove `GuardEvent::getContext()` method without replacement
15+
* Add partial support for marking with more than one token per place
1516

1617
6.4
1718
---

‎src/Symfony/Component/Workflow/Marking.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Workflow/Marking.php
+27-6Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,44 @@ class Marking
2727
public function __construct(array $representation = [])
2828
{
2929
foreach ($representation as $place => $nbToken) {
30-
$this->mark($place);
30+
$this->mark($place, $nbToken);
3131
}
3232
}
3333

34-
public function mark(string $place): void
34+
public function mark(string $place, int $nbToken = 1): void
3535
{
36-
$this->places[$place] = 1;
36+
if ($nbToken < 1) {
37+
throw new \LogicException(sprintf('The number of tokens must be greater than 0, "%s" given.', $nbToken));
38+
}
39+
40+
$this->places[$place] ??= 0;
41+
$this->places[$place] += $nbToken;
3742
}
3843

39-
public function unmark(string $place): void
44+
public function unmark(string $place, int $nbToken = 1): void
4045
{
41-
unset($this->places[$place]);
46+
if ($nbToken < 1) {
47+
throw new \LogicException(sprintf('The number of tokens must be greater than 0, "%s" given.', $nbToken));
48+
}
49+
50+
if (!$this->has($place)) {
51+
throw new \LogicException(sprintf('The place "%s" is not marked.', $place));
52+
}
53+
54+
$this->places[$place] -= $nbToken;
55+
56+
if (0 > $this->places[$place]) {
57+
throw new \LogicException(sprintf('The place "%s" could not contain a negative token number.', $place));
58+
}
59+
60+
if (0 === $this->places[$place]) {
61+
unset($this->places[$place]);
62+
}
4263
}
4364

4465
public function has(string $place): bool
4566
{
46-
return isset($this->places[$place]);
67+
return \array_key_exists($place, $this->places);
4768
}
4869

4970
public function getPlaces(): array

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Workflow/Tests/MarkingTest.php
+50-4Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,70 @@ public function testMarking()
2222

2323
$this->assertTrue($marking->has('a'));
2424
$this->assertFalse($marking->has('b'));
25-
$this->assertSame(['a' => 1], $marking->getPlaces());
25+
$this->assertPlaces(['a' => 1], $marking);
2626

2727
$marking->mark('b');
2828

2929
$this->assertTrue($marking->has('a'));
3030
$this->assertTrue($marking->has('b'));
31-
$this->assertSame(['a' => 1, 'b' => 1], $marking->getPlaces());
31+
$this->assertPlaces(['a' => 1, 'b' => 1], $marking);
3232

3333
$marking->unmark('a');
3434

3535
$this->assertFalse($marking->has('a'));
3636
$this->assertTrue($marking->has('b'));
37-
$this->assertSame(['b' => 1], $marking->getPlaces());
37+
$this->assertPlaces(['b' => 1], $marking);
3838

3939
$marking->unmark('b');
4040

4141
$this->assertFalse($marking->has('a'));
4242
$this->assertFalse($marking->has('b'));
43-
$this->assertSame([], $marking->getPlaces());
43+
$this->assertPlaces([], $marking);
44+
45+
$marking->mark('a');
46+
$this->assertPlaces(['a' => 1], $marking);
47+
48+
$marking->mark('a');
49+
$this->assertPlaces(['a' => 2], $marking);
50+
51+
$marking->unmark('a');
52+
$this->assertPlaces(['a' => 1], $marking);
53+
54+
$marking->unmark('a');
55+
$this->assertPlaces([], $marking);
56+
}
57+
58+
public function testGuardNotMarked()
59+
{
60+
$marking = new Marking([]);
61+
62+
$this->expectException(\LogicException::class);
63+
$this->expectExceptionMessage('The place "a" is not marked.');
64+
$marking->unmark('a');
65+
}
66+
67+
public function testGuardNotNbTokenLowerThanZero()
68+
{
69+
$marking = new Marking(['a' => 1]);
70+
71+
$this->expectException(\LogicException::class);
72+
$this->expectExceptionMessage('The place "a" could not contain a negative token number.');
73+
$marking->unmark('a', 2);
74+
}
75+
76+
public function testGuardNotNbTokenEquals0()
77+
{
78+
$marking = new Marking(['a' => 1]);
79+
80+
$this->expectException(\LogicException::class);
81+
$this->expectExceptionMessage('The number of tokens must be greater than 0, "0" given.');
82+
$marking->unmark('a', 0);
83+
}
84+
85+
private function assertPlaces(array $expected, Marking $marking)
86+
{
87+
$places = $marking->getPlaces();
88+
ksort($places);
89+
$this->assertSame($expected, $places);
4490
}
4591
}

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Workflow/Tests/WorkflowBuilderTrait.php
+39Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,4 +158,43 @@ private static function createComplexStateMachineDefinition(): Definition
158158
// | d | -------------+
159159
// +-----+
160160
}
161+
162+
private static function createWorkflowWithSameNameBackTransition(): Definition
163+
{
164+
$places = range('a', 'c');
165+
166+
$transitions = [];
167+
$transitions[] = new Transition('a_to_bc', 'a', ['b', 'c']);
168+
$transitions[] = new Transition('back1', 'b', 'a');
169+
$transitions[] = new Transition('back1', 'c', 'b');
170+
$transitions[] = new Transition('back2', 'c', 'b');
171+
$transitions[] = new Transition('back2', 'b', 'a');
172+
$transitions[] = new Transition('c_to_cb', 'c', ['b', 'c']);
173+
174+
return new Definition($places, $transitions);
175+
176+
// The graph looks like:
177+
// +-----------------------------------------------------------------+
178+
// | |
179+
// | |
180+
// | +---------------------------------------------+ |
181+
// v | v |
182+
// +---+ +---------+ +-------+ +---------+ +---+ +-------+
183+
// | a | --> | a_to_bc | --> | | --> | back2 | --> | | --> | back2 |
184+
// +---+ +---------+ | | +---------+ | | +-------+
185+
// ^ | | | |
186+
// | | c | <-----+ | b |
187+
// | | | | | |
188+
// | | | +---------+ | | +-------+
189+
// | | | --> | c_to_cb | --> | | --> | back1 |
190+
// | +-------+ +---------+ +---+ +-------+
191+
// | | ^ |
192+
// | | | |
193+
// | v | |
194+
// | +-------+ | |
195+
// | | back1 | ----------------------+ |
196+
// | +-------+ |
197+
// | |
198+
// +-----------------------------------------------------------------+
199+
}
161200
}

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Workflow/Tests/WorkflowTest.php
+57Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,63 @@ public function testGetEnabledTransitionsWithSameNameTransition()
776776
$this->assertSame('to_a', $transitions[1]->getName());
777777
$this->assertSame('to_a', $transitions[2]->getName());
778778
}
779+
780+
/**
781+
* @@testWith ["back1"]
782+
* ["back2"]
783+
*/
784+
public function testApplyWithSameNameBackTransition(string $transition)
785+
{
786+
$definition = $this->createWorkflowWithSameNameBackTransition();
787+
$workflow = new Workflow($definition, new MethodMarkingStore());
788+
789+
$subject = new Subject();
790+
791+
$marking = $workflow->apply($subject, 'a_to_bc');
792+
$this->assertPlaces([
793+
'b' => 1,
794+
'c' => 1,
795+
], $marking);
796+
797+
$marking = $workflow->apply($subject, $transition);
798+
$this->assertPlaces([
799+
'a' => 1,
800+
'b' => 1,
801+
], $marking);
802+
803+
$marking = $workflow->apply($subject, $transition);
804+
$this->assertPlaces([
805+
'a' => 2,
806+
], $marking);
807+
808+
$marking = $workflow->apply($subject, 'a_to_bc');
809+
$this->assertPlaces([
810+
'a' => 1,
811+
'b' => 1,
812+
'c' => 1,
813+
], $marking);
814+
815+
$marking = $workflow->apply($subject, 'c_to_cb');
816+
$this->assertPlaces([
817+
'a' => 1,
818+
'b' => 2,
819+
'c' => 1,
820+
], $marking);
821+
822+
$marking = $workflow->apply($subject, 'c_to_cb');
823+
$this->assertPlaces([
824+
'a' => 1,
825+
'b' => 3,
826+
'c' => 1,
827+
], $marking);
828+
}
829+
830+
private function assertPlaces(array $expected, Marking $marking)
831+
{
832+
$places = $marking->getPlaces();
833+
ksort($places);
834+
$this->assertSame($expected, $places);
835+
}
779836
}
780837

781838
class EventDispatcherMock implements \Symfony\Contracts\EventDispatcher\EventDispatcherInterface

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Workflow/Workflow.php
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,8 @@ private function leave(object $subject, Transition $transition, Marking $marking
340340
}
341341
}
342342

343+
dump(['leaves' => $places]);
344+
343345
foreach ($places as $place) {
344346
$marking->unmark($place);
345347
}
@@ -363,6 +365,7 @@ private function transition(object $subject, Transition $transition, Marking $ma
363365
private function enter(object $subject, Transition $transition, Marking $marking, array $context): void
364366
{
365367
$places = $transition->getTos();
368+
dump(['enter' => $places]);
366369

367370
if ($this->shouldDispatchEvent(WorkflowEvents::ENTER, $context)) {
368371
$event = new EnterEvent($subject, $marking, $transition, $this, $context);

0 commit comments

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