Skip to content

Commit

Permalink
feature #30468 [Workflow] Added support for many inital places (lyrixx)
Browse files Browse the repository at this point in the history
This PR was merged into the 4.3-dev branch.

Discussion
----------

[Workflow] Added support for many inital places

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | yes
| Tests pass?   | yes
| Fixed tickets | #30080
| License       | MIT
| Doc PR        |

Commits
-------

1af1bf2 Added support for many inital places
  • Loading branch information
lyrixx committed Mar 22, 2019
2 parents 522594a + 1af1bf2 commit 98045b1
Show file tree
Hide file tree
Showing 37 changed files with 250 additions and 45 deletions.
21 changes: 21 additions & 0 deletions UPGRADE-4.3.md
Expand Up @@ -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
----

Expand Down
1 change: 1 addition & 0 deletions UPGRADE-5.0.md
Expand Up @@ -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
----
Expand Down
Expand Up @@ -231,7 +231,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode)
$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'];
}

Expand All @@ -258,6 +258,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode)
->prototype('array')
->fixXmlConfig('support')
->fixXmlConfig('place')
->fixXmlConfig('initial_place')
->fixXmlConfig('transition')
->children()
->arrayNode('audit_trail')
Expand Down Expand Up @@ -312,8 +313,17 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode)
->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()
Expand Down
Expand Up @@ -621,14 +621,14 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $

// 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
Expand Down Expand Up @@ -676,7 +676,7 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $
->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);
Expand Down
Expand Up @@ -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" />
Expand Down
@@ -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',
],
],
],
],
]);
Expand Up @@ -12,7 +12,7 @@
'supports' => [
FrameworkExtensionTest::class,
],
'initial_place' => 'draft',
'initial_places' => ['draft'],
'places' => [
'draft',
'wait_for_journalist',
Expand Down
Expand Up @@ -12,7 +12,7 @@
'supports' => [
FrameworkExtensionTest::class,
],
'initial_place' => 'draft',
'initial_places' => ['draft'],
'places' => [
'draft',
'wait_for_journalist',
Expand Down
Expand Up @@ -12,7 +12,7 @@
'supports' => [
FrameworkExtensionTest::class,
],
'initial_place' => 'draft',
'initial_places' => ['draft'],
'places' => [
'draft',
'wait_for_journalist',
Expand Down Expand Up @@ -47,7 +47,7 @@
'supports' => [
FrameworkExtensionTest::class,
],
'initial_place' => 'start',
'initial_places' => ['start'],
'metadata' => [
'title' => 'workflow title',
],
Expand Down
Expand Up @@ -6,7 +6,7 @@
'foo' => [
'type' => 'workflow',
'supports' => ['Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest'],
'initial_place' => 'bar',
'initial_places' => ['bar'],
'places' => ['bar', 'baz'],
'transitions' => [
'bar_baz' => [
Expand Down
Expand Up @@ -6,7 +6,7 @@
'workflows' => [
'type' => 'workflow',
'supports' => ['Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest'],
'initial_place' => 'bar',
'initial_places' => ['bar'],
'places' => ['bar', 'baz'],
'transitions' => [
'bar_baz' => [
Expand Down
@@ -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>
Expand Up @@ -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>
Expand Down
Expand Up @@ -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>
Expand Down
Expand Up @@ -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>
Expand Down
Expand Up @@ -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>
Expand Down
Expand Up @@ -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>
Expand Down
@@ -0,0 +1,14 @@
framework:
workflows:
legacy:
type: workflow
initial_place: draft
supports:
- stdClass
places:
- draft
- published
transitions:
publish:
from: draft
to: published
Expand Up @@ -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
Expand Down
Expand Up @@ -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
Expand Down
Expand Up @@ -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
Expand All @@ -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:
Expand Down
Expand Up @@ -6,7 +6,7 @@ framework:
type: workflow
supports:
- Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest
initial_place: bar
initial_places: [bar]
places:
- bar
- baz
Expand Down
Expand Up @@ -5,7 +5,7 @@ framework:
type: workflow
supports:
- Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest
initial_place: bar
initial_places: [bar]
places:
- bar
- baz
Expand Down
Expand Up @@ -217,7 +217,7 @@ public function testWorkflows()
'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());
Expand All @@ -238,7 +238,7 @@ public function testWorkflows()
'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);
Expand Down Expand Up @@ -271,6 +271,28 @@ public function testWorkflows()
$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".
Expand Down
4 changes: 2 additions & 2 deletions src/Symfony/Bundle/FrameworkBundle/composer.json
Expand Up @@ -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",
Expand All @@ -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",
Expand Down
1 change: 1 addition & 0 deletions src/Symfony/Component/Workflow/CHANGELOG.md
Expand Up @@ -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
-----
Expand Down

0 comments on commit 98045b1

Please sign in to comment.