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 175a20b

Browse filesBrowse files
committed
[Workflow] Fix Marking when it must contains more than one tokens
1 parent 85d0165 commit 175a20b
Copy full SHA for 175a20b

File tree

4 files changed

+192
-23
lines changed
Filter options

4 files changed

+192
-23
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Workflow/Marking.php
+30-7Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,31 +19,54 @@
1919
class Marking
2020
{
2121
private $places = [];
22-
private $context = null;
22+
private $context;
2323

2424
/**
2525
* @param int[] $representation Keys are the place name and values should be 1
2626
*/
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)
34+
public function mark(string $place, int $nbToken = 1)
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+
if (!\array_key_exists($place, $this->places)) {
41+
$this->places[$place] = 0;
42+
}
43+
$this->places[$place] += $nbToken;
3744
}
3845

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

4467
public function has(string $place)
4568
{
46-
return isset($this->places[$place]);
69+
return \array_key_exists($place, $this->places);
4770
}
4871

4972
public function getPlaces()

‎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()
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
+73-12Lines changed: 73 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -330,28 +330,32 @@ public function testApplyWithSameNameTransition()
330330

331331
$marking = $workflow->apply($subject, 'a_to_bc');
332332

333-
$this->assertFalse($marking->has('a'));
334-
$this->assertTrue($marking->has('b'));
335-
$this->assertTrue($marking->has('c'));
333+
$this->assertPlaces([
334+
'b' => 1,
335+
'c' => 1,
336+
], $marking);
336337

337338
$marking = $workflow->apply($subject, 'to_a');
338339

339-
$this->assertTrue($marking->has('a'));
340-
$this->assertFalse($marking->has('b'));
341-
$this->assertFalse($marking->has('c'));
340+
// Two tokens in "a"
341+
$this->assertPlaces([
342+
'a' => 2,
343+
], $marking);
342344

343345
$workflow->apply($subject, 'a_to_bc');
344346
$marking = $workflow->apply($subject, 'b_to_c');
345347

346-
$this->assertFalse($marking->has('a'));
347-
$this->assertFalse($marking->has('b'));
348-
$this->assertTrue($marking->has('c'));
348+
$this->assertPlaces([
349+
'a' => 1,
350+
'c' => 2,
351+
], $marking);
349352

350353
$marking = $workflow->apply($subject, 'to_a');
351354

352-
$this->assertTrue($marking->has('a'));
353-
$this->assertFalse($marking->has('b'));
354-
$this->assertFalse($marking->has('c'));
355+
$this->assertPlaces([
356+
'a' => 2,
357+
'c' => 1,
358+
], $marking);
355359
}
356360

357361
public function testApplyWithSameNameTransition2()
@@ -785,6 +789,63 @@ public function testGetEnabledTransitionsWithSameNameTransition()
785789
$this->assertSame('to_a', $transitions[1]->getName());
786790
$this->assertSame('to_a', $transitions[2]->getName());
787791
}
792+
793+
/**
794+
* @@testWith ["back1"]
795+
* ["back2"]
796+
*/
797+
public function testApplyWithSameNameBackTransition(string $transition)
798+
{
799+
$definition = $this->createWorkflowWithSameNameBackTransition();
800+
$workflow = new Workflow($definition, new MethodMarkingStore());
801+
802+
$subject = new Subject();
803+
804+
$marking = $workflow->apply($subject, 'a_to_bc');
805+
$this->assertPlaces([
806+
'b' => 1,
807+
'c' => 1,
808+
], $marking);
809+
810+
$marking = $workflow->apply($subject, $transition);
811+
$this->assertPlaces([
812+
'a' => 1,
813+
'b' => 1,
814+
], $marking);
815+
816+
$marking = $workflow->apply($subject, $transition);
817+
$this->assertPlaces([
818+
'a' => 2,
819+
], $marking);
820+
821+
$marking = $workflow->apply($subject, 'a_to_bc');
822+
$this->assertPlaces([
823+
'a' => 1,
824+
'b' => 1,
825+
'c' => 1,
826+
], $marking);
827+
828+
$marking = $workflow->apply($subject, 'c_to_cb');
829+
$this->assertPlaces([
830+
'a' => 1,
831+
'b' => 2,
832+
'c' => 1,
833+
], $marking);
834+
835+
$marking = $workflow->apply($subject, 'c_to_cb');
836+
$this->assertPlaces([
837+
'a' => 1,
838+
'b' => 3,
839+
'c' => 1,
840+
], $marking);
841+
}
842+
843+
private function assertPlaces(array $expected, Marking $marking)
844+
{
845+
$places = $marking->getPlaces();
846+
ksort($places);
847+
$this->assertSame($expected, $places);
848+
}
788849
}
789850

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

0 commit comments

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