diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index f4269d157b..4a8fef38d3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -296,11 +296,33 @@ class Configuration implements ConfigurationInterface ->end() ->end() ->arrayNode('transitions') - ->useAttributeAsKey('name') + ->beforeNormalization() + ->always() + ->then(function ($transitions) { + // It's an indexed array, we let the validation occurs + if (isset($transitions[0])) { + return $transitions; + } + + foreach ($transitions as $name => $transition) { + if (array_key_exists('name', $transition)) { + continue; + } + $transition['name'] = $name; + $transitions[$name] = $transition; + } + + return $transitions; + }) + ->end() ->isRequired() ->requiresAtLeastOneElement() ->prototype('array') ->children() + ->scalarNode('name') + ->isRequired() + ->cannotBeEmpty() + ->end() ->arrayNode('from') ->beforeNormalization() ->ifString() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index dc2a172fc9..97b79bcd28 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -408,13 +408,13 @@ class FrameworkExtension extends Extension $type = $workflow['type']; $transitions = array(); - foreach ($workflow['transitions'] as $transitionName => $transition) { + foreach ($workflow['transitions'] as $transition) { if ($type === 'workflow') { - $transitions[] = new Definition(Workflow\Transition::class, array($transitionName, $transition['from'], $transition['to'])); + $transitions[] = new Definition(Workflow\Transition::class, array($transition['name'], $transition['from'], $transition['to'])); } elseif ($type === 'state_machine') { foreach ($transition['from'] as $from) { foreach ($transition['to'] as $to) { - $transitions[] = new Definition(Workflow\Transition::class, array($transitionName, $from, $to)); + $transitions[] = new Definition(Workflow\Transition::class, array($transition['name'], $from, $to)); } } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_multiple_transitions_with_same_name.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_multiple_transitions_with_same_name.php new file mode 100644 index 0000000000..2619a2dd43 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_multiple_transitions_with_same_name.php @@ -0,0 +1,49 @@ +loadFromExtension('framework', array( + 'workflows' => array( + 'article' => array( + 'type' => 'workflow', + 'marking_store' => array( + 'type' => 'multiple_state', + ), + 'supports' => array( + FrameworkExtensionTest::class, + ), + 'initial_place' => 'draft', + 'places' => array( + 'draft', + 'wait_for_journalist', + 'approved_by_journalist', + 'wait_for_spellchecker', + 'approved_by_spellchecker', + 'published', + ), + 'transitions' => array( + 'request_review' => array( + 'from' => 'draft', + 'to' => array('wait_for_journalist', 'wait_for_spellchecker'), + ), + 'journalist_approval' => array( + 'from' => 'wait_for_journalist', + 'to' => 'approved_by_journalist', + ), + 'spellchecker_approval' => array( + 'from' => 'wait_for_spellchecker', + 'to' => 'approved_by_spellchecker', + ), + 'publish' => array( + 'from' => array('approved_by_journalist', 'approved_by_spellchecker'), + 'to' => 'published', + ), + 'publish_editor_in_chief' => array( + 'name' => 'publish', + 'from' => 'draft', + 'to' => 'published', + ), + ), + ), + ), +)); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_multiple_transitions_with_same_name.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_multiple_transitions_with_same_name.xml new file mode 100644 index 0000000000..d52aed8c95 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_multiple_transitions_with_same_name.xml @@ -0,0 +1,46 @@ + + + + + + + + a + a + + Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest + draft + wait_for_journalist + approved_by_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 + + + draft + published + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_multiple_transitions_with_same_name.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_multiple_transitions_with_same_name.yml new file mode 100644 index 0000000000..36d00de465 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_multiple_transitions_with_same_name.yml @@ -0,0 +1,33 @@ +framework: + workflows: + article: + type: workflow + marking_store: + type: multiple_state + supports: + - Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest + initial_place: draft + places: + - draft + - 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] + publish_editor_in_chief: + name: publish + from: [draft] + to: [published] diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index 26792c6b1c..d283aa84a8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -190,6 +190,29 @@ abstract class FrameworkExtensionTest extends TestCase $this->createContainerFromFile('workflow_with_arguments_and_service'); } + public function testWorkflowMultipleTransitionsWithSameName() + { + $container = $this->createContainerFromFile('workflow_with_multiple_transitions_with_same_name'); + + $this->assertTrue($container->hasDefinition('workflow.article', 'Workflow is registered as a service')); + $this->assertTrue($container->hasDefinition('workflow.article.definition', 'Workflow definition is registered as a service')); + + $workflowDefinition = $container->getDefinition('workflow.article.definition'); + + $transitions = $workflowDefinition->getArgument(1); + + $this->assertCount(5, $transitions); + + $this->assertSame('request_review', $transitions[0]->getArgument(0)); + $this->assertSame('journalist_approval', $transitions[1]->getArgument(0)); + $this->assertSame('spellchecker_approval', $transitions[2]->getArgument(0)); + $this->assertSame('publish', $transitions[3]->getArgument(0)); + $this->assertSame('publish', $transitions[4]->getArgument(0)); + + $this->assertSame(array('approved_by_journalist', 'approved_by_spellchecker'), $transitions[3]->getArgument(1)); + $this->assertSame(array('draft'), $transitions[4]->getArgument(1)); + } + public function testRouter() { $container = $this->createContainerFromFile('full');