diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
index 78ed8b3ac8b6a..eb1f3c43c92e3 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
@@ -473,27 +473,16 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode): void
throw new InvalidConfigurationException('The "places" option must be an array in workflow configuration.');
}
- // It's an indexed array of shape ['place1', 'place2']
- if (isset($places[0]) && \is_string($places[0])) {
- return array_map(function (string $place) {
- return ['name' => $place];
- }, $places);
- }
-
- // It's an indexed array, we let the validation occur
- if (isset($places[0]) && \is_array($places[0])) {
- return $places;
- }
-
- foreach ($places as $name => $place) {
- if (\is_array($place) && \array_key_exists('name', $place)) {
- continue;
+ $normalizedPlaces = [];
+ foreach ($places as $key => $value) {
+ if (!\is_array($value)) {
+ $value = ['name' => $value];
}
- $place['name'] = $name;
- $places[$name] = $place;
+ $value['name'] ??= $key;
+ $normalizedPlaces[] = $value;
}
- return array_values($places);
+ return $normalizedPlaces;
})
->end()
->isRequired()
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_complex_place_follow_by_simplistic_place_config.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_complex_place_follow_by_simplistic_place_config.php
new file mode 100644
index 0000000000000..99e319dc03b65
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_complex_place_follow_by_simplistic_place_config.php
@@ -0,0 +1,55 @@
+loadFromExtension('framework', [
+ 'annotations' => false,
+ 'http_method_override' => false,
+ 'handle_all_throwables' => true,
+ 'php_errors' => ['log' => true],
+ 'workflows' => [
+ 'article' => [
+ 'type' => 'workflow',
+ 'supports' => [
+ FrameworkExtensionTestCase::class,
+ ],
+ 'initial_marking' => ['draft'],
+ 'metadata' => [
+ 'title' => 'article workflow',
+ 'description' => 'workflow for articles',
+ ],
+ 'places' => [
+ 'draft' => [
+ 'metadata' => [
+ 'foo' => 'bar',
+ ],
+ ],
+ 'wait_for_journalist',
+ 'approved_by_journalist' => [
+ 'name' => 'approved_by_journalist',
+ ],
+ 'wait_for_spellchecker',
+ 'approved_by_spellchecker',
+ 'published',
+ ],
+ 'transitions' => [
+ 'request_review' => [
+ 'from' => 'draft',
+ 'to' => ['wait_for_journalist', 'wait_for_spellchecker'],
+ ],
+ 'journalist_approval' => [
+ 'from' => 'wait_for_journalist',
+ 'to' => 'approved_by_journalist',
+ ],
+ 'spellchecker_approval' => [
+ 'from' => 'wait_for_spellchecker',
+ 'to' => 'approved_by_spellchecker',
+ ],
+ 'publish' => [
+ 'from' => ['approved_by_journalist', 'approved_by_spellchecker'],
+ 'to' => 'published',
+ ],
+ ],
+ ],
+ ],
+]);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_simplistic_place_follow_by_complex_place_config.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_simplistic_place_follow_by_complex_place_config.php
new file mode 100644
index 0000000000000..d3579fee196d6
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_simplistic_place_follow_by_complex_place_config.php
@@ -0,0 +1,55 @@
+loadFromExtension('framework', [
+ 'annotations' => false,
+ 'http_method_override' => false,
+ 'handle_all_throwables' => true,
+ 'php_errors' => ['log' => true],
+ 'workflows' => [
+ 'article' => [
+ 'type' => 'workflow',
+ 'supports' => [
+ FrameworkExtensionTestCase::class,
+ ],
+ 'initial_marking' => ['draft'],
+ 'metadata' => [
+ 'title' => 'article workflow',
+ 'description' => 'workflow for articles',
+ ],
+ 'places' => [
+ 'draft',
+ 'wait_for_journalist' => [
+ 'metadata' => [
+ 'description' => 'The article is awaiting approval of an authorized journalist.',
+ ],
+ ],
+ 'approved_by_journalist' => [
+ 'name' => 'approved_by_journalist',
+ ],
+ 'wait_for_spellchecker',
+ 'approved_by_spellchecker',
+ 'published',
+ ],
+ 'transitions' => [
+ 'request_review' => [
+ 'from' => 'draft',
+ 'to' => ['wait_for_journalist', 'wait_for_spellchecker'],
+ ],
+ 'journalist_approval' => [
+ 'from' => 'wait_for_journalist',
+ 'to' => 'approved_by_journalist',
+ ],
+ 'spellchecker_approval' => [
+ 'from' => 'wait_for_spellchecker',
+ 'to' => 'approved_by_spellchecker',
+ ],
+ 'publish' => [
+ 'from' => ['approved_by_journalist', 'approved_by_spellchecker'],
+ 'to' => 'published',
+ ],
+ ],
+ ],
+ ],
+]);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_complex_place_follow_by_simplistic_place_config.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_complex_place_follow_by_simplistic_place_config.xml
new file mode 100644
index 0000000000000..364faa62feec0
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_complex_place_follow_by_simplistic_place_config.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+ draft
+ Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTestCase
+
+
+ bar
+
+
+ wait_for_journalist
+
+ wait_for_spellchecker
+ approved_by_spellchecker
+ published
+
+ draft
+ wait_for_journalist
+ wait_for_spellchecker
+
+
+ wait_for_journalist
+ approved_by_journalist
+
+
+ wait_for_spellchecker
+ approved_by_spellchecker
+
+
+ approved_by_journalist
+ approved_by_spellchecker
+ published
+
+
+ article workflow
+ workflow for articles
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_simplistic_place_follow_by_complex_place_config.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_simplistic_place_follow_by_complex_place_config.xml
new file mode 100644
index 0000000000000..81046a75b969f
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_simplistic_place_follow_by_complex_place_config.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+ draft
+ Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTestCase
+ draft
+
+
+ The article is awaiting approval of an authorized journalist.
+
+
+
+ wait_for_spellchecker
+ approved_by_spellchecker
+ published
+
+ draft
+ wait_for_journalist
+ wait_for_spellchecker
+
+
+ wait_for_journalist
+ approved_by_journalist
+
+
+ wait_for_spellchecker
+ approved_by_spellchecker
+
+
+ approved_by_journalist
+ approved_by_spellchecker
+ published
+
+
+ article workflow
+ workflow for articles
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_complex_place_follow_by_simplistic_place_config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_complex_place_follow_by_simplistic_place_config.yml
new file mode 100644
index 0000000000000..b5e184db55f62
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_complex_place_follow_by_simplistic_place_config.yml
@@ -0,0 +1,37 @@
+framework:
+ annotations: false
+ http_method_override: false
+ handle_all_throwables: true
+ php_errors:
+ log: true
+ workflows:
+ article:
+ type: workflow
+ supports:
+ - Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTestCase
+ initial_marking: [ draft ]
+ metadata:
+ title: article workflow
+ description: workflow for articles
+ places:
+ draft:
+ metadata:
+ foo: bar
+ wait_for_journalist: ~
+ approved_by_journalist: ~
+ wait_for_spellchecker: ~
+ approved_by_spellchecker: ~
+ published: ~
+ transitions:
+ request_review:
+ from: [ draft ]
+ to: [ wait_for_journalist, wait_for_spellchecker ]
+ journalist_approval:
+ from: [ wait_for_journalist ]
+ to: [ approved_by_journalist ]
+ spellchecker_approval:
+ from: [ wait_for_spellchecker ]
+ to: [ approved_by_spellchecker ]
+ publish:
+ from: [ approved_by_journalist, approved_by_spellchecker ]
+ to: [ published ]
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_complex_place_follow_by_simplistic_place_config_with_alternative_syntax.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_complex_place_follow_by_simplistic_place_config_with_alternative_syntax.yml
new file mode 100644
index 0000000000000..1f3131b9e632f
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_complex_place_follow_by_simplistic_place_config_with_alternative_syntax.yml
@@ -0,0 +1,37 @@
+framework:
+ annotations: false
+ http_method_override: false
+ handle_all_throwables: true
+ php_errors:
+ log: true
+ workflows:
+ article:
+ type: workflow
+ supports:
+ - Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTestCase
+ initial_marking: [ draft ]
+ metadata:
+ title: article workflow
+ description: workflow for articles
+ places:
+ - draft:
+ metadata:
+ foo: bar
+ - wait_for_journalist
+ - approved_by_journalist
+ - wait_for_spellchecker
+ - approved_by_spellchecker
+ - published
+ transitions:
+ request_review:
+ from: [ draft ]
+ to: [ wait_for_journalist, wait_for_spellchecker ]
+ journalist_approval:
+ from: [ wait_for_journalist ]
+ to: [ approved_by_journalist ]
+ spellchecker_approval:
+ from: [ wait_for_spellchecker ]
+ to: [ approved_by_spellchecker ]
+ publish:
+ from: [ approved_by_journalist, approved_by_spellchecker ]
+ to: [ published ]
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_simplistic_place_follow_by_complex_place_config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_simplistic_place_follow_by_complex_place_config.yml
new file mode 100644
index 0000000000000..bdd98fd713f08
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_simplistic_place_follow_by_complex_place_config.yml
@@ -0,0 +1,37 @@
+framework:
+ annotations: false
+ http_method_override: false
+ handle_all_throwables: true
+ php_errors:
+ log: true
+ workflows:
+ article:
+ type: workflow
+ supports:
+ - Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTestCase
+ initial_marking: [ draft ]
+ metadata:
+ title: article workflow
+ description: workflow for articles
+ places:
+ draft: ~
+ wait_for_journalist:
+ metadata:
+ description: The article is awaiting approval of an authorized journalist.
+ approved_by_journalist: ~
+ wait_for_spellchecker: ~
+ approved_by_spellchecker: ~
+ published: ~
+ transitions:
+ request_review:
+ from: [ draft ]
+ to: [ wait_for_journalist, wait_for_spellchecker ]
+ journalist_approval:
+ from: [ wait_for_journalist ]
+ to: [ approved_by_journalist ]
+ spellchecker_approval:
+ from: [ wait_for_spellchecker ]
+ to: [ approved_by_spellchecker ]
+ publish:
+ from: [ approved_by_journalist, approved_by_spellchecker ]
+ to: [ published ]
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_simplistic_place_follow_by_complex_place_config_with_alternative_syntax.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_simplistic_place_follow_by_complex_place_config_with_alternative_syntax.yml
new file mode 100644
index 0000000000000..ca033acb61b49
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_simplistic_place_follow_by_complex_place_config_with_alternative_syntax.yml
@@ -0,0 +1,37 @@
+framework:
+ annotations: false
+ http_method_override: false
+ handle_all_throwables: true
+ php_errors:
+ log: true
+ workflows:
+ article:
+ type: workflow
+ supports:
+ - Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTestCase
+ initial_marking: [ draft ]
+ metadata:
+ title: article workflow
+ description: workflow for articles
+ places:
+ - draft
+ - wait_for_journalist:
+ metadata:
+ description: The article is awaiting approval of an authorized journalist.
+ - approved_by_journalist
+ - wait_for_spellchecker
+ - approved_by_spellchecker
+ - published
+ transitions:
+ request_review:
+ from: [ draft ]
+ to: [ wait_for_journalist, wait_for_spellchecker ]
+ journalist_approval:
+ from: [ wait_for_journalist ]
+ to: [ approved_by_journalist ]
+ spellchecker_approval:
+ from: [ wait_for_spellchecker ]
+ to: [ approved_by_spellchecker ]
+ publish:
+ from: [ approved_by_journalist, approved_by_spellchecker ]
+ to: [ published ]
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php
index f34913f8a6b57..ba6ddba3ca71c 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php
@@ -414,6 +414,20 @@ public function testWorkflowShouldHaveOneOfSupportsAndSupportStrategy()
$this->createContainerFromFile('workflow_without_support_and_support_strategy');
}
+ public function testWorkflowWithSimplisticPlaceFollowedByComplexPlace()
+ {
+ $container = $this->createContainerFromFile('workflow_with_simplistic_place_follow_by_complex_place_config');
+
+ $this->assertTrue($container->hasDefinition('workflow.article'), 'Workflow is parsed and registered as a service');
+ }
+
+ public function testWorkflowWithComplexPlaceFollowedBySimplisticPlace()
+ {
+ $container = $this->createContainerFromFile('workflow_with_complex_place_follow_by_simplistic_place_config');
+
+ $this->assertTrue($container->hasDefinition('workflow.article'), 'Workflow is parsed and registered as a service');
+ }
+
public function testWorkflowMultipleTransitionsWithSameName()
{
$container = $this->createContainerFromFile('workflow_with_multiple_transitions_with_same_name');
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/YamlFrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/YamlFrameworkExtensionTest.php
index cb5a0a5e16f6f..6caa055dc7f7b 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/YamlFrameworkExtensionTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/YamlFrameworkExtensionTest.php
@@ -11,6 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection;
+use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
@@ -22,4 +23,18 @@ protected function loadFromFile(ContainerBuilder $container, $file)
$loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/Fixtures/yml'));
$loader->load($file.'.yml');
}
+
+ public function testWorkflowWithSimplisticPlaceFollowedByComplexPlaceWithAlternativeSyntax()
+ {
+ $this->expectException(InvalidConfigurationException::class);
+ $this->expectExceptionMessage('Unrecognized option "wait_for_journalist" under "framework.workflows.workflows.article.places.1". Available options are "metadata", "name".');
+ $this->createContainerFromFile('workflow_with_simplistic_place_follow_by_complex_place_config_with_alternative_syntax');
+ }
+
+ public function testWorkflowWithComplexPlaceFollowedBySimplisticPlaceWithAlternativeSyntax()
+ {
+ $this->expectException(InvalidConfigurationException::class);
+ $this->expectExceptionMessage('Unrecognized option "draft" under "framework.workflows.workflows.article.places.0". Available options are "metadata", "name".');
+ $this->createContainerFromFile('workflow_with_complex_place_follow_by_simplistic_place_config_with_alternative_syntax');
+ }
}