Added support for many inital places
This commit is contained in:
parent
fc826aac4c
commit
1af1bf29ef
|
@ -127,6 +127,27 @@ Security
|
|||
}
|
||||
```
|
||||
|
||||
Workflow
|
||||
--------
|
||||
|
||||
* `initial_place` is deprecated in favour of `initial_places`.
|
||||
|
||||
Before:
|
||||
```yaml
|
||||
framework:
|
||||
workflows:
|
||||
article:
|
||||
initial_place: draft
|
||||
```
|
||||
|
||||
After:
|
||||
```yaml
|
||||
framework:
|
||||
workflows:
|
||||
article:
|
||||
initial_places: [draft]
|
||||
```
|
||||
|
||||
Yaml
|
||||
----
|
||||
|
||||
|
|
|
@ -368,6 +368,7 @@ Workflow
|
|||
* `SupportStrategyInterface` has been removed, use `WorkflowSupportStrategyInterface` instead.
|
||||
* `ClassInstanceSupportStrategy` has been removed, use `InstanceOfSupportStrategy` instead.
|
||||
* `MarkingStoreInterface::setMarking()` has a third argument: `array $context = []`.
|
||||
* Removed support of `initial_place`. Use `initial_places` instead.
|
||||
|
||||
Yaml
|
||||
----
|
||||
|
|
|
@ -231,7 +231,7 @@ class Configuration implements ConfigurationInterface
|
|||
$workflows = [];
|
||||
}
|
||||
|
||||
if (1 === \count($workflows) && isset($workflows['workflows']) && array_keys($workflows['workflows']) !== range(0, \count($workflows) - 1) && !empty(array_diff(array_keys($workflows['workflows']), ['audit_trail', 'type', 'marking_store', 'supports', 'support_strategy', 'initial_place', 'places', 'transitions']))) {
|
||||
if (1 === \count($workflows) && isset($workflows['workflows']) && array_keys($workflows['workflows']) !== range(0, \count($workflows) - 1) && !empty(array_diff(array_keys($workflows['workflows']), ['audit_trail', 'type', 'marking_store', 'supports', 'support_strategy', 'initial_places', 'places', 'transitions']))) {
|
||||
$workflows = $workflows['workflows'];
|
||||
}
|
||||
|
||||
|
@ -258,6 +258,7 @@ class Configuration implements ConfigurationInterface
|
|||
->prototype('array')
|
||||
->fixXmlConfig('support')
|
||||
->fixXmlConfig('place')
|
||||
->fixXmlConfig('initial_place')
|
||||
->fixXmlConfig('transition')
|
||||
->children()
|
||||
->arrayNode('audit_trail')
|
||||
|
@ -312,8 +313,17 @@ class Configuration implements ConfigurationInterface
|
|||
->cannotBeEmpty()
|
||||
->end()
|
||||
->scalarNode('initial_place')
|
||||
->setDeprecated('The "%path%.%node%" configuration key has been deprecated in Symfony 4.3, use the "initial_places" configuration key instead.')
|
||||
->defaultNull()
|
||||
->end()
|
||||
->arrayNode('initial_places')
|
||||
->beforeNormalization()
|
||||
->ifTrue(function ($v) { return !\is_array($v); })
|
||||
->then(function ($v) { return [$v]; })
|
||||
->end()
|
||||
->defaultValue([])
|
||||
->prototype('scalar')->end()
|
||||
->end()
|
||||
->arrayNode('places')
|
||||
->beforeNormalization()
|
||||
->always()
|
||||
|
|
|
@ -615,14 +615,14 @@ class FrameworkExtension extends Extension
|
|||
|
||||
// Create places
|
||||
$places = array_column($workflow['places'], 'name');
|
||||
$initialPlace = $workflow['initial_place'] ?? null;
|
||||
$initialPlaces = $workflow['initial_places'] ?? $workflow['initial_place'] ?? [];
|
||||
|
||||
// Create a Definition
|
||||
$definitionDefinition = new Definition(Workflow\Definition::class);
|
||||
$definitionDefinition->setPublic(false);
|
||||
$definitionDefinition->addArgument($places);
|
||||
$definitionDefinition->addArgument($transitions);
|
||||
$definitionDefinition->addArgument($initialPlace);
|
||||
$definitionDefinition->addArgument($initialPlaces);
|
||||
$definitionDefinition->addArgument($metadataStoreDefinition);
|
||||
|
||||
// Create MarkingStore
|
||||
|
@ -670,7 +670,7 @@ class FrameworkExtension extends Extension
|
|||
->addTransitions(array_map(function (Reference $ref) use ($container): Workflow\Transition {
|
||||
return $container->get((string) $ref);
|
||||
}, $transitions))
|
||||
->setInitialPlace($initialPlace)
|
||||
->setInitialPlace($initialPlaces)
|
||||
->build()
|
||||
;
|
||||
$validator->validate($realDefinition, $name);
|
||||
|
|
|
@ -270,6 +270,7 @@
|
|||
|
||||
<xsd:complexType name="workflow">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="initial-place" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xsd:element name="marking-store" type="marking_store" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element name="support" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xsd:element name="place" type="place" minOccurs="0" maxOccurs="unbounded" />
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest;
|
||||
|
||||
$container->loadFromExtension('framework', [
|
||||
'workflows' => [
|
||||
'legacy' => [
|
||||
'type' => 'workflow',
|
||||
'supports' => [
|
||||
stdClass::class,
|
||||
],
|
||||
'initial_place' => 'draft',
|
||||
'places' => [
|
||||
'draft',
|
||||
'published',
|
||||
],
|
||||
'transitions' => [
|
||||
'publish' => [
|
||||
'from' => 'draft',
|
||||
'to' => 'published',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
|
@ -12,7 +12,7 @@ $container->loadFromExtension('framework', [
|
|||
'supports' => [
|
||||
FrameworkExtensionTest::class,
|
||||
],
|
||||
'initial_place' => 'draft',
|
||||
'initial_places' => ['draft'],
|
||||
'places' => [
|
||||
'draft',
|
||||
'wait_for_journalist',
|
||||
|
|
|
@ -12,7 +12,7 @@ $container->loadFromExtension('framework', [
|
|||
'supports' => [
|
||||
FrameworkExtensionTest::class,
|
||||
],
|
||||
'initial_place' => 'draft',
|
||||
'initial_places' => ['draft'],
|
||||
'places' => [
|
||||
'draft',
|
||||
'wait_for_journalist',
|
||||
|
|
|
@ -12,7 +12,7 @@ $container->loadFromExtension('framework', [
|
|||
'supports' => [
|
||||
FrameworkExtensionTest::class,
|
||||
],
|
||||
'initial_place' => 'draft',
|
||||
'initial_places' => ['draft'],
|
||||
'places' => [
|
||||
'draft',
|
||||
'wait_for_journalist',
|
||||
|
@ -47,7 +47,7 @@ $container->loadFromExtension('framework', [
|
|||
'supports' => [
|
||||
FrameworkExtensionTest::class,
|
||||
],
|
||||
'initial_place' => 'start',
|
||||
'initial_places' => ['start'],
|
||||
'metadata' => [
|
||||
'title' => 'workflow title',
|
||||
],
|
||||
|
|
|
@ -6,7 +6,7 @@ $container->loadFromExtension('framework', [
|
|||
'foo' => [
|
||||
'type' => 'workflow',
|
||||
'supports' => ['Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest'],
|
||||
'initial_place' => 'bar',
|
||||
'initial_places' => ['bar'],
|
||||
'places' => ['bar', 'baz'],
|
||||
'transitions' => [
|
||||
'bar_baz' => [
|
||||
|
|
|
@ -6,7 +6,7 @@ $container->loadFromExtension('framework', [
|
|||
'workflows' => [
|
||||
'type' => 'workflow',
|
||||
'supports' => ['Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest'],
|
||||
'initial_place' => 'bar',
|
||||
'initial_places' => ['bar'],
|
||||
'places' => ['bar', 'baz'],
|
||||
'transitions' => [
|
||||
'bar_baz' => [
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" ?>
|
||||
|
||||
<container xmlns="http://symfony.com/schema/dic/services"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:framework="http://symfony.com/schema/dic/symfony"
|
||||
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd
|
||||
http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
|
||||
|
||||
<framework:config>
|
||||
<framework:workflow name="legacy" type="workflow" initial-place="draft">
|
||||
<framework:support>stdClass</framework:support>
|
||||
<framework:place name="draft"></framework:place>
|
||||
<framework:place name="published"></framework:place>
|
||||
<framework:transition name="publish">
|
||||
<framework:from>draft</framework:from>
|
||||
<framework:to>published</framework:to>
|
||||
</framework:transition>
|
||||
</framework:workflow>
|
||||
</framework:config>
|
||||
</container>
|
|
@ -7,7 +7,8 @@
|
|||
http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
|
||||
|
||||
<framework:config>
|
||||
<framework:workflow name="article" type="workflow" initial-place="draft">
|
||||
<framework:workflow name="article" type="workflow">
|
||||
<framework:initial-place>draft</framework:initial-place>
|
||||
<framework:marking-store type="multiple_state">
|
||||
<framework:argument>a</framework:argument>
|
||||
<framework:argument>a</framework:argument>
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
|
||||
|
||||
<framework:config>
|
||||
<framework:workflow name="article" type="workflow" initial-place="draft">
|
||||
<framework:workflow name="article" type="workflow">
|
||||
<framework:initial-place>draft</framework:initial-place>
|
||||
<framework:marking-store type="multiple_state">
|
||||
<framework:argument>a</framework:argument>
|
||||
<framework:argument>a</framework:argument>
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
|
||||
|
||||
<framework:config>
|
||||
<framework:workflow name="article" type="workflow" initial-place="draft">
|
||||
<framework:workflow name="article" type="workflow">
|
||||
<framework:initial-place>draft</framework:initial-place>
|
||||
<framework:marking-store type="multiple_state">
|
||||
<framework:argument>a</framework:argument>
|
||||
<framework:argument>a</framework:argument>
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
|
||||
|
||||
<framework:config>
|
||||
<framework:workflow enabled="true" name="foo" type="workflow" initial-place="bar">
|
||||
<framework:workflow enabled="true" name="foo" type="workflow">
|
||||
<framework:initial-place>bar</framework:initial-place>
|
||||
<framework:support>Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest</framework:support>
|
||||
<framework:place>bar</framework:place>
|
||||
<framework:place>baz</framework:place>
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
|
||||
|
||||
<framework:config>
|
||||
<framework:workflow enabled="true" name="workflows" type="workflow" initial-place="bar">
|
||||
<framework:workflow enabled="true" name="workflows" type="workflow">
|
||||
<framework:initial-place>bar</framework:initial-place>
|
||||
<framework:support>Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest</framework:support>
|
||||
<framework:place>bar</framework:place>
|
||||
<framework:place>baz</framework:place>
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
framework:
|
||||
workflows:
|
||||
legacy:
|
||||
type: workflow
|
||||
initial_place: draft
|
||||
supports:
|
||||
- stdClass
|
||||
places:
|
||||
- draft
|
||||
- published
|
||||
transitions:
|
||||
publish:
|
||||
from: draft
|
||||
to: published
|
|
@ -6,7 +6,7 @@ framework:
|
|||
type: multiple_state
|
||||
supports:
|
||||
- Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest
|
||||
initial_place: draft
|
||||
initial_places: [draft]
|
||||
places:
|
||||
- draft
|
||||
- wait_for_journalist
|
||||
|
|
|
@ -6,7 +6,7 @@ framework:
|
|||
type: multiple_state
|
||||
supports:
|
||||
- Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest
|
||||
initial_place: draft
|
||||
initial_places: [draft]
|
||||
places:
|
||||
- draft
|
||||
- wait_for_journalist
|
||||
|
|
|
@ -6,7 +6,7 @@ framework:
|
|||
type: multiple_state
|
||||
supports:
|
||||
- Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest
|
||||
initial_place: draft
|
||||
initial_places: [draft]
|
||||
places:
|
||||
# simple format
|
||||
- draft
|
||||
|
@ -33,7 +33,7 @@ framework:
|
|||
type: single_state
|
||||
supports:
|
||||
- Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest
|
||||
initial_place: start
|
||||
initial_places: [start]
|
||||
metadata:
|
||||
title: workflow title
|
||||
places:
|
||||
|
|
|
@ -6,7 +6,7 @@ framework:
|
|||
type: workflow
|
||||
supports:
|
||||
- Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest
|
||||
initial_place: bar
|
||||
initial_places: [bar]
|
||||
places:
|
||||
- bar
|
||||
- baz
|
||||
|
|
|
@ -5,7 +5,7 @@ framework:
|
|||
type: workflow
|
||||
supports:
|
||||
- Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest
|
||||
initial_place: bar
|
||||
initial_places: [bar]
|
||||
places:
|
||||
- bar
|
||||
- baz
|
||||
|
|
|
@ -217,7 +217,7 @@ abstract class FrameworkExtensionTest extends TestCase
|
|||
'Places are passed to the workflow definition'
|
||||
);
|
||||
$this->assertCount(4, $workflowDefinition->getArgument(1));
|
||||
$this->assertSame('draft', $workflowDefinition->getArgument(2));
|
||||
$this->assertSame(['draft'], $workflowDefinition->getArgument(2));
|
||||
|
||||
$this->assertTrue($container->hasDefinition('state_machine.pull_request'), 'State machine is registered as a service');
|
||||
$this->assertSame('state_machine.abstract', $container->getDefinition('state_machine.pull_request')->getParent());
|
||||
|
@ -238,7 +238,7 @@ abstract class FrameworkExtensionTest extends TestCase
|
|||
'Places are passed to the state machine definition'
|
||||
);
|
||||
$this->assertCount(9, $stateMachineDefinition->getArgument(1));
|
||||
$this->assertSame('start', $stateMachineDefinition->getArgument(2));
|
||||
$this->assertSame(['start'], $stateMachineDefinition->getArgument(2));
|
||||
|
||||
$metadataStoreDefinition = $stateMachineDefinition->getArgument(3);
|
||||
$this->assertInstanceOf(Definition::class, $metadataStoreDefinition);
|
||||
|
@ -271,6 +271,28 @@ abstract class FrameworkExtensionTest extends TestCase
|
|||
$this->assertGreaterThan(0, \count($registryDefinition->getMethodCalls()));
|
||||
}
|
||||
|
||||
public function testWorkflowLegacy()
|
||||
{
|
||||
$container = $this->createContainerFromFile('workflow-legacy');
|
||||
|
||||
$this->assertTrue($container->hasDefinition('workflow.legacy'), 'Workflow is registered as a service');
|
||||
$this->assertSame('workflow.abstract', $container->getDefinition('workflow.legacy')->getParent());
|
||||
$this->assertTrue($container->hasDefinition('workflow.legacy.definition'), 'Workflow definition is registered as a service');
|
||||
|
||||
$workflowDefinition = $container->getDefinition('workflow.legacy.definition');
|
||||
|
||||
$this->assertSame(['draft'], $workflowDefinition->getArgument(2));
|
||||
|
||||
$this->assertSame(
|
||||
[
|
||||
'draft',
|
||||
'published',
|
||||
],
|
||||
$workflowDefinition->getArgument(0),
|
||||
'Places are passed to the workflow definition'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Workflow\Exception\InvalidDefinitionException
|
||||
* @expectedExceptionMessage A transition from a place/state must have an unique name. Multiple transitions named "go" from place/state "first" where found on StateMachine "my_workflow".
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
"symfony/twig-bundle": "~2.8|~3.2|~4.0",
|
||||
"symfony/validator": "^4.1",
|
||||
"symfony/var-dumper": "~3.4|~4.0",
|
||||
"symfony/workflow": "^4.1",
|
||||
"symfony/workflow": "^4.3",
|
||||
"symfony/yaml": "~3.4|~4.0",
|
||||
"symfony/property-info": "~3.4|~4.0",
|
||||
"symfony/lock": "~3.4|~4.0",
|
||||
|
@ -79,7 +79,7 @@
|
|||
"symfony/translation": "<4.3",
|
||||
"symfony/twig-bridge": "<4.1.1",
|
||||
"symfony/validator": "<4.1",
|
||||
"symfony/workflow": "<4.1"
|
||||
"symfony/workflow": "<4.3"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-apcu": "For best performance of the system caches",
|
||||
|
|
|
@ -26,6 +26,7 @@ CHANGELOG
|
|||
* Dispatch `EnteredEvent` on `workflow.entered`
|
||||
* Dispatch `CompletedEvent` on `workflow.completed`
|
||||
* Dispatch `AnnounceEvent` on `workflow.announce`
|
||||
* Added support for many `initialPlaces`
|
||||
|
||||
4.1.0
|
||||
-----
|
||||
|
|
|
@ -24,14 +24,15 @@ final class Definition
|
|||
{
|
||||
private $places = [];
|
||||
private $transitions = [];
|
||||
private $initialPlace;
|
||||
private $initialPlaces = [];
|
||||
private $metadataStore;
|
||||
|
||||
/**
|
||||
* @param string[] $places
|
||||
* @param Transition[] $transitions
|
||||
* @param string[] $places
|
||||
* @param Transition[] $transitions
|
||||
* @param string|string[]|null $initialPlaces
|
||||
*/
|
||||
public function __construct(array $places, array $transitions, string $initialPlace = null, MetadataStoreInterface $metadataStore = null)
|
||||
public function __construct(array $places, array $transitions, $initialPlaces = null, MetadataStoreInterface $metadataStore = null)
|
||||
{
|
||||
foreach ($places as $place) {
|
||||
$this->addPlace($place);
|
||||
|
@ -41,17 +42,33 @@ final class Definition
|
|||
$this->addTransition($transition);
|
||||
}
|
||||
|
||||
$this->setInitialPlace($initialPlace);
|
||||
$this->setInitialPlaces($initialPlaces);
|
||||
|
||||
$this->metadataStore = $metadataStore ?: new InMemoryMetadataStore();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 4.3. Use the getInitialPlaces() instead.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getInitialPlace()
|
||||
{
|
||||
return $this->initialPlace;
|
||||
@trigger_error(sprintf('Calling %s::getInitialPlace() is deprecated. Call %s::getInitialPlaces() instead.', __CLASS__, __CLASS__));
|
||||
|
||||
if (!$this->initialPlaces) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return reset($this->initialPlaces);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getInitialPlaces(): array
|
||||
{
|
||||
return $this->initialPlaces;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,23 +92,27 @@ final class Definition
|
|||
return $this->metadataStore;
|
||||
}
|
||||
|
||||
private function setInitialPlace(string $place = null)
|
||||
private function setInitialPlaces($places = null)
|
||||
{
|
||||
if (null === $place) {
|
||||
if (null === $places) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isset($this->places[$place])) {
|
||||
throw new LogicException(sprintf('Place "%s" cannot be the initial place as it does not exist.', $place));
|
||||
$places = (array) $places;
|
||||
|
||||
foreach ($places as $place) {
|
||||
if (!isset($this->places[$place])) {
|
||||
throw new LogicException(sprintf('Place "%s" cannot be the initial place as it does not exist.', $place));
|
||||
}
|
||||
}
|
||||
|
||||
$this->initialPlace = $place;
|
||||
$this->initialPlaces = $places;
|
||||
}
|
||||
|
||||
private function addPlace(string $place)
|
||||
{
|
||||
if (!\count($this->places)) {
|
||||
$this->initialPlace = $place;
|
||||
$this->initialPlaces = [$place];
|
||||
}
|
||||
|
||||
$this->places[$place] = $place;
|
||||
|
|
|
@ -69,7 +69,7 @@ class GraphvizDumper implements DumperInterface
|
|||
|
||||
foreach ($definition->getPlaces() as $place) {
|
||||
$attributes = [];
|
||||
if ($place === $definition->getInitialPlace()) {
|
||||
if (\in_array($place, $definition->getInitialPlaces(), true)) {
|
||||
$attributes['style'] = 'filled';
|
||||
}
|
||||
if ($marking && $marking->has($place)) {
|
||||
|
|
|
@ -199,7 +199,7 @@ class PlantUmlDumper implements DumperInterface
|
|||
$placeEscaped = $this->escape($place);
|
||||
|
||||
$output = "state $placeEscaped".
|
||||
($definition->getInitialPlace() === $place ? ' '.self::INITIAL : '').
|
||||
(\in_array($place, $definition->getInitialPlaces(), true) ? ' '.self::INITIAL : '').
|
||||
($marking && $marking->has($place) ? ' '.self::MARKED : '');
|
||||
|
||||
$backgroundColor = $workflowMetadata->getMetadata('bg_color', $place);
|
||||
|
|
|
@ -15,7 +15,7 @@ class DefinitionBuilderTest extends TestCase
|
|||
$builder->setInitialPlace('b');
|
||||
$definition = $builder->build();
|
||||
|
||||
$this->assertEquals('b', $definition->getInitialPlace());
|
||||
$this->assertEquals(['b'], $definition->getInitialPlaces());
|
||||
}
|
||||
|
||||
public function testAddTransition()
|
||||
|
|
|
@ -15,7 +15,7 @@ class DefinitionTest extends TestCase
|
|||
|
||||
$this->assertCount(5, $definition->getPlaces());
|
||||
|
||||
$this->assertEquals('a', $definition->getInitialPlace());
|
||||
$this->assertEquals(['a'], $definition->getInitialPlaces());
|
||||
}
|
||||
|
||||
public function testSetInitialPlace()
|
||||
|
@ -23,7 +23,15 @@ class DefinitionTest extends TestCase
|
|||
$places = range('a', 'e');
|
||||
$definition = new Definition($places, [], $places[3]);
|
||||
|
||||
$this->assertEquals($places[3], $definition->getInitialPlace());
|
||||
$this->assertEquals([$places[3]], $definition->getInitialPlaces());
|
||||
}
|
||||
|
||||
public function testSetInitialPlaces()
|
||||
{
|
||||
$places = range('a', 'e');
|
||||
$definition = new Definition($places, [], ['a', 'e']);
|
||||
|
||||
$this->assertEquals(['a', 'e'], $definition->getInitialPlaces());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -109,4 +109,32 @@ class StateMachineValidatorTest extends TestCase
|
|||
// | t2 | --> | c |
|
||||
// +----+ +----+
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Workflow\Exception\InvalidDefinitionException
|
||||
* @expectedExceptionMessage The state machine "foo" can not store many places. But the definition has 2 initial places. Only one is supported.
|
||||
*/
|
||||
public function testWithTooManyInitialPlaces()
|
||||
{
|
||||
$places = range('a', 'c');
|
||||
$transitions = [];
|
||||
$definition = new Definition($places, $transitions, ['a', 'b']);
|
||||
|
||||
(new StateMachineValidator())->validate($definition, 'foo');
|
||||
|
||||
// the test ensures that the validation does not fail (i.e. it does not throw any exceptions)
|
||||
$this->addToAssertionCount(1);
|
||||
|
||||
// The graph looks like:
|
||||
//
|
||||
// +----+ +----+ +---+
|
||||
// | a | --> | t1 | --> | b |
|
||||
// +----+ +----+ +---+
|
||||
// |
|
||||
// |
|
||||
// v
|
||||
// +----+ +----+
|
||||
// | t2 | --> | c |
|
||||
// +----+ +----+
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,20 @@ class WorkflowValidatorTest extends TestCase
|
|||
(new WorkflowValidator())->validate($definition, 'foo');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Workflow\Exception\InvalidDefinitionException
|
||||
* @expectedExceptionMessage The marking store of workflow "foo" can not store many places. But the definition has 2 initial places. Only one is supported.
|
||||
*/
|
||||
public function testWithTooManyInitialPlaces()
|
||||
{
|
||||
$places = range('a', 'c');
|
||||
$transitions = [];
|
||||
|
||||
$definition = new Definition($places, $transitions, ['a', 'b']);
|
||||
|
||||
(new WorkflowValidator(true))->validate($definition, 'foo');
|
||||
}
|
||||
|
||||
public function testSameTransitionNameButNotSamePlace()
|
||||
{
|
||||
$places = range('a', 'd');
|
||||
|
|
|
@ -16,6 +16,7 @@ use Symfony\Component\Workflow\Exception\InvalidDefinitionException;
|
|||
|
||||
/**
|
||||
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
|
||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||
*/
|
||||
interface DefinitionValidatorInterface
|
||||
{
|
||||
|
|
|
@ -37,10 +37,15 @@ class StateMachineValidator implements DefinitionValidatorInterface
|
|||
// Enforcing uniqueness of the names of transitions starting at each node
|
||||
$from = reset($froms);
|
||||
if (isset($transitionFromNames[$from][$transition->getName()])) {
|
||||
throw new InvalidDefinitionException(sprintf('A transition from a place/state must have an unique name. Multiple transitions named "%s" from place/state "%s" where found on StateMachine "%s". ', $transition->getName(), $from, $name));
|
||||
throw new InvalidDefinitionException(sprintf('A transition from a place/state must have an unique name. Multiple transitions named "%s" from place/state "%s" where found on StateMachine "%s".', $transition->getName(), $from, $name));
|
||||
}
|
||||
|
||||
$transitionFromNames[$from][$transition->getName()] = true;
|
||||
}
|
||||
|
||||
$initialPlaces = $definition->getInitialPlaces();
|
||||
if (2 <= count($initialPlaces)) {
|
||||
throw new InvalidDefinitionException(sprintf('The state machine "%s" can not store many places. But the definition has %s initial places. Only one is supported.', $name, \count($initialPlaces)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ use Symfony\Component\Workflow\Exception\InvalidDefinitionException;
|
|||
|
||||
/**
|
||||
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
|
||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||
*/
|
||||
class WorkflowValidator implements DefinitionValidatorInterface
|
||||
{
|
||||
|
@ -48,5 +49,10 @@ class WorkflowValidator implements DefinitionValidatorInterface
|
|||
throw new InvalidDefinitionException(sprintf('The marking store of workflow "%s" can not store many places. But the transition "%s" has too many output (%d). Only one is accepted.', $name, $transition->getName(), \count($transition->getTos())));
|
||||
}
|
||||
}
|
||||
|
||||
$initialPlaces = $definition->getInitialPlaces();
|
||||
if (2 <= count($initialPlaces)) {
|
||||
throw new InvalidDefinitionException(sprintf('The marking store of workflow "%s" can not store many places. But the definition has %s initial places. Only one is supported.', $name, \count($initialPlaces)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,10 +61,12 @@ class Workflow implements WorkflowInterface
|
|||
|
||||
// check if the subject is already in the workflow
|
||||
if (!$marking->getPlaces()) {
|
||||
if (!$this->definition->getInitialPlace()) {
|
||||
if (!$this->definition->getInitialPlaces()) {
|
||||
throw new LogicException(sprintf('The Marking is empty and there is no initial place for workflow "%s".', $this->name));
|
||||
}
|
||||
$marking->mark($this->definition->getInitialPlace());
|
||||
foreach ($this->definition->getInitialPlaces() as $place) {
|
||||
$marking->mark($place);
|
||||
}
|
||||
|
||||
// update the subject with the new marking
|
||||
$this->markingStore->setMarking($subject, $marking);
|
||||
|
|
Reference in New Issue