8000 bug #53865 [Workflow]Fix Marking when it must contains more than one … · symfony/symfony@5ce412b · GitHub
[go: up one dir, main page]

Skip to content

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 5ce412b

Browse files
committed
bug #53865 [Workflow]Fix Marking when it must contains more than one tokens (lyrixx)
This PR was merged into the 5.4 branch. Discussion ---------- [Workflow]Fix Marking when it must contains more than one tokens | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Issues | Fix #53179 | License | MIT Commits ------- 02b54a1 [Workflow] Fix Marking when it must contains more than one tokens
2 parents 7dae80d + 02b54a1 commit 5ce412b

File tree

4 files changed

+192
-23
lines changed

4 files changed

+192
-23
lines changed

src/Symfony/Component/Workflow/Marking.php

Lines 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

Lines 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

Lines 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

Lines 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