Skip to content

Commit 08dbffb

Browse files
committed
[Workflow] Made StateMachine supports only SingleStateMarkingStore
1 parent 62533f3 commit 08dbffb

28 files changed

+624
-304
lines changed

src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@
1515
use Symfony\Component\Console\Input\InputInterface;
1616
use Symfony\Component\Console\Output\OutputInterface;
1717
use Symfony\Component\Workflow\Dumper\GraphvizDumper;
18-
use Symfony\Component\Workflow\Marking;
19-
use Symfony\Component\Workflow\Workflow;
18+
use Symfony\Component\Workflow\MultipleStateMarking;
19+
use Symfony\Component\Workflow\SingleStateMarking;
20+
use Symfony\Component\Workflow\StateMachine;
2021

2122
/**
2223
* @author Grégoire Pineau <lyrixx@lyrixx.info>
@@ -67,7 +68,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
6768
}
6869

6970
$dumper = new GraphvizDumper();
70-
$marking = new Marking();
71+
$marking = $workflow instanceof StateMachine ? new SingleStateMarking() : new MultipleStateMarking();
7172

7273
foreach ($input->getArgument('marking') as $place) {
7374
$marking->mark($place);

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode)
244244
->children()
245245
->enumNode('type')
246246
->values(array('multiple_state', 'single_state'))
247+
->defaultValue('multiple_state')
247248
->end()
248249
->arrayNode('arguments')
249250
->beforeNormalization()

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -431,13 +431,16 @@ private function registerWorkflowConfiguration(array $workflows, ContainerBuilde
431431
));
432432

433433
// Create MarkingStore
434-
if (isset($workflow['marking_store']['type'])) {
435-
$markingStoreDefinition = new DefinitionDecorator('workflow.marking_store.'.$workflow['marking_store']['type']);
434+
if (isset($workflow['marking_store']['service'])) {
435+
$markingStoreDefinition = new Reference($workflow['marking_store']['service']);
436+
} else {
437+
$markingStoreDefinition = new DefinitionDecorator('workflow.marking_store.property_access');
436438
foreach ($workflow['marking_store']['arguments'] as $argument) {
437439
$markingStoreDefinition->addArgument($argument);
438440
}
439-
} elseif (isset($workflow['marking_store']['service'])) {
440-
$markingStoreDefinition = new Reference($workflow['marking_store']['service']);
441+
442+
$markingStrategy = 'state_machine' === $type ? 'single_state' : $workflow['marking_store']['type'];
443+
$markingStoreDefinition->replaceArgument(2, $markingStrategy);
441444
}
442445

443446
// Create Workflow

src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow.xml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@
1818
<argument /> <!-- name -->
1919
</service>
2020

21-
<service id="workflow.marking_store.multiple_state" class="Symfony\Component\Workflow\MarkingStore\MultipleStateMarkingStore" abstract="true" />
22-
<service id="workflow.marking_store.single_state" class="Symfony\Component\Workflow\MarkingStore\SingleStateMarkingStore" abstract="true" />
21+
<service id="workflow.marking_store.property_access" class="Symfony\Component\Workflow\MarkingStore\PropertyAccessMarkingStore" abstract="true" />
2322

2423
<service id="workflow.registry" class="Symfony\Component\Workflow\Registry" />
2524

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Workflow\Exception;
13+
14+
/**
15+
* An InvalidMarkingException is thrown when a Marking does not
16+
* match the current workflow.
17+
*
18+
* @author Jules Pietri <jules@heahprod.com>
19+
*/
20+
class InvalidMarkingException extends LogicException
21+
{
22+
/**
23+
* @param string $expectedClass
24+
* @param mixed $marking
25+
*/
26+
public function __construct($expectedClass, $marking)
27+
{
28+
$this->message = sprintf('Marking must be an instance of "%", but got "%"', $expectedClass, is_object($marking) ? get_class($marking) : gettype($marking));
29+
}
30+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Workflow\Exception;
13+
14+
/**
15+
* An InvalidMarkingStrategyException is thrown when the marking strategy
16+
* does not match the Marking instance.
17+
*
18+
* @author Jules Pietri <jules@heahprod.com>
19+
*/
20+
class InvalidMarkingStrategyException extends LogicException
21+
{
22+
/**
23+
* @param string $markingStoreClass
24+
*/
25+
public function __construct($markingStoreClass)
26+
{
27+
$this->message = sprintf('The marking store has no strategy set. Did you forgot to call "%::__construct()"?', $markingStoreClass);
28+
}
29+
}

src/Symfony/Component/Workflow/Marking.php

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,41 +12,45 @@
1212
namespace Symfony\Component\Workflow;
1313

1414
/**
15-
* Marking contains the place of every tokens.
15+
* A base Marking which contains the state of the
16+
* state of a Workflow or a StateMachine a representation
17+
* by places with tokens.
1618
*
1719
* @author Grégoire Pineau <lyrixx@lyrixx.info>
20+
* @author Jules Pietri <jules@heahprod.com>
1821
*/
19-
class Marking
22+
abstract class Marking
2023
{
21-
private $places = array();
24+
const STRATEGY_SINGLE_STATE = 'single_state';
25+
const STRATEGY_MULTIPLE_STATE = 'multiple_state';
26+
27+
protected $places = array();
2228

2329
/**
24-
* @param string[] $representation Keys are the place name and values should be 1
30+
* @param string $place
31+
*
32+
* @return bool
2533
*/
26-
public function __construct(array $representation = array())
27-
{
28-
foreach ($representation as $place => $nbToken) {
29-
$this->mark($place);
30-
}
31-
}
32-
33-
public function mark($place)
34-
{
35-
$this->places[$place] = 1;
36-
}
37-
38-
public function unmark($place)
39-
{
40-
unset($this->places[$place]);
41-
}
42-
43-
public function has($place)
34+
final public function has($place)
4435
{
4536
return isset($this->places[$place]);
4637
}
4738

48-
public function getPlaces()
39+
/**
40+
* @return int[] An array of places as keys and token counts as values.
41+
*/
42+
final public function getState()
4943
{
5044
return $this->places;
5145
}
46+
47+
/**
48+
* @param string $place
49+
*/
50+
abstract public function mark($place);
51+
52+
/**
53+
* @param string $place
54+
*/
55+
abstract public function unmark($place);
5256
}
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Workflow\MarkingStore;
13+
14+
use Symfony\Component\Workflow\Exception\InvalidArgumentException;
15+
use Symfony\Component\Workflow\Exception\InvalidMarkingException;
16+
use Symfony\Component\Workflow\Exception\InvalidMarkingStrategyException;
17+
use Symfony\Component\Workflow\Marking;
18+
use Symfony\Component\Workflow\MultipleStateMarking;
19+
use Symfony\Component\Workflow\SingleStateMarking;
20+
21+
/**
22+
* A MarkingStore is the interface between the Workflow Component and a
23+
* plain old PHP object: the subject.
24+
*
25+
* It converts the Marking into something understandable by the subject and vice
26+
* versa.
27+
*
28+
* @author Grégoire Pineau <lyrixx@lyrixx.info>
29+
* @author Jules Pietri <jules@heahprod.com>
30+
*/
31+
abstract class MarkingStore
32+
{
33+
private $strategy;
34+
35+
/**
36+
* @param string $strategy A Marking constant
37+
*/
38+
public function __construct($strategy = Marking::STRATEGY_MULTIPLE_STATE)
39+
{
40+
$strategies = array(Marking::STRATEGY_SINGLE_STATE, Marking::STRATEGY_MULTIPLE_STATE);
41+
if (!in_array($strategy, $strategies, true)) {
42+
throw new InvalidArgumentException(sprintf('Marking strategy must be one of "%s", but got "%".', implode('" or "', $strategies), $strategy));
43+
}
44+
45+
$this->strategy = $strategy;
46+
}
47+
48+
/**
49+
* Returns the strategy used for marking.
50+
*
51+
* @return string A Marking constant
52+
*/
53+
final public function getStrategy()
54+
{
55+
return $this->strategy;
56+
}
57+
58+
/**
59+
* Gets a Marking from a subject.
60+
*
61+
* @param object $subject A subject
62+
*
63+
* @return Marking The marking
64+
*
65+
* @throws InvalidMarkingException When the marking does not match the strategy
66+
* @throws InvalidMarkingStrategyException When the strategy in unknown
67+
*/
68+
public function getMarking($subject)
69+
{
70+
if (Marking::STRATEGY_MULTIPLE_STATE === $this->strategy) {
71+
$marking = $this->getMultipleStateMarking($subject);
72+
73+
if (!$marking instanceof MultipleStateMarking) {
74+
throw new InvalidMarkingException(MultipleStateMarking::class, $marking);
75+
}
76+
77+
return $marking;
78+
}
79+
80+
if (Marking::STRATEGY_SINGLE_STATE === $this->strategy) {
81+
$marking = $this->getSingleStateMarking($subject);
82+
83+
if (!$marking instanceof SingleStateMarking) {
84+
throw new InvalidMarkingException(SingleStateMarking::class, $marking);
85+
}
86+
87+
return $marking;
88+
}
89+
90+
throw new InvalidMarkingStrategyException(static::class);
91+
}
92+
93+
/**
94+
* Sets a Marking to a subject.
95+
*
96+
* Must return an
97+
*
98+
* @param object $subject A subject
99+
* @param Marking $marking A marking
100+
*
101+
* @throws InvalidMarkingException When the marking does not match the strategy
102+
* @throws InvalidMarkingStrategyException When the strategy in unknown
103+
*/
104+
public function setMarking($subject, Marking $marking)
105+
{
106+
if (Marking::STRATEGY_MULTIPLE_STATE === $this->strategy) {
107+
if (!$marking instanceof MultipleStateMarking) {
108+
throw new InvalidMarkingException(MultipleStateMarking::class, $marking);
109+
}
110+
111+
$this->setMultipleStateMarking($subject, $marking);
112+
113+
return;
114+
}
115+
116+
if (Marking::STRATEGY_SINGLE_STATE === $this->strategy) {
117+
if (!$marking instanceof SingleStateMarking) {
118+
throw new InvalidMarkingException(SingleStateMarking::class, $marking);
119+
}
120+
121+
$this->setSingleStateMarking($subject, $marking);
122+
123+
return;
124+
}
125+
126+
throw new InvalidMarkingStrategyException(static::class);
127+
}
128+
129+
/**
130+
* Gets a SingleStateMarking from a subject.
131+
*
132+
* @param object $subject A subject
133+
*
134+
* @return SingleStateMarking The marking
135+
*/
136+
abstract protected function getSingleStateMarking($subject);
137+
138+
/**
139+
* Sets a SingleStateMarking to a subject.
140+
*
141+
* @param object $subject
142+
* @param SingleStateMarking $marking
143+
*/
144+
abstract protected function setSingleStateMarking($subject, SingleStateMarking $marking);
145+
146+
/**
147+
* Gets a MultipleStateMarking from a subject.
148+
*
149+
* @param object $subject A subject
150+
*
151+
* @return MultipleStateMarking The marking
152+
*/
153+
abstract protected function getMultipleStateMarking($subject);
154+
155+
/**
156+
* Sets a MultipleStateMarking to a subject.
157+
*
158+
* @param object $subject
159+
* @param MultipleStateMarking $marking
160+
*/
161+
abstract protected function setMultipleStateMarking($subject, MultipleStateMarking $marking);
162+
}

src/Symfony/Component/Workflow/MarkingStore/MarkingStoreInterface.php

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

0 commit comments

Comments
 (0)