From eaa506f562281e4152aea2fbae79e38b1a5c7e82 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 3 Sep 2017 12:36:19 +0200 Subject: [PATCH] be able to enable workflow support explicitly --- .../DependencyInjection/Configuration.php | 250 ++++++++++-------- .../FrameworkExtension.php | 8 +- .../Resources/config/schema/symfony-1.0.xsd | 9 +- .../DependencyInjection/ConfigurationTest.php | 5 +- .../Fixtures/php/workflows_enabled.php | 5 + .../Fixtures/xml/workflows_enabled.xml | 11 + .../Fixtures/yml/workflows_enabled.yml | 2 + .../FrameworkExtensionTest.php | 10 + 8 files changed, 178 insertions(+), 122 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_enabled.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_enabled.xml create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_enabled.yml diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index fcc0e714c8cb6..66934aba6a419 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -247,141 +247,165 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode) ->fixXmlConfig('workflow') ->children() ->arrayNode('workflows') - ->useAttributeAsKey('name') - ->prototype('array') - ->fixXmlConfig('support') - ->fixXmlConfig('place') - ->fixXmlConfig('transition') - ->children() - ->arrayNode('audit_trail') - ->canBeEnabled() - ->end() - ->enumNode('type') - ->values(array('workflow', 'state_machine')) - ->end() - ->arrayNode('marking_store') - ->fixXmlConfig('argument') + ->canBeEnabled() + ->beforeNormalization() + ->always(function ($v) { + if (true === $v['enabled']) { + $workflows = $v; + unset($workflows['enabled']); + + if (count($workflows) === 1 && isset($workflows[0]['enabled'])) { + $workflows = array(); + } + + $v = array( + 'enabled' => true, + 'workflows' => $workflows, + ); + } + + return $v; + }) + ->end() + ->children() + ->arrayNode('workflows') + ->useAttributeAsKey('name') + ->prototype('array') + ->fixXmlConfig('support') + ->fixXmlConfig('place') + ->fixXmlConfig('transition') ->children() + ->arrayNode('audit_trail') + ->canBeEnabled() + ->end() ->enumNode('type') - ->values(array('multiple_state', 'single_state')) + ->values(array('workflow', 'state_machine')) + ->end() + ->arrayNode('marking_store') + ->fixXmlConfig('argument') + ->children() + ->enumNode('type') + ->values(array('multiple_state', 'single_state')) + ->end() + ->arrayNode('arguments') + ->beforeNormalization() + ->ifString() + ->then(function ($v) { return array($v); }) + ->end() + ->requiresAtLeastOneElement() + ->prototype('scalar') + ->end() + ->end() + ->scalarNode('service') + ->cannotBeEmpty() + ->end() + ->end() + ->validate() + ->ifTrue(function ($v) { return isset($v['type']) && isset($v['service']); }) + ->thenInvalid('"type" and "service" cannot be used together.') + ->end() + ->validate() + ->ifTrue(function ($v) { return !empty($v['arguments']) && isset($v['service']); }) + ->thenInvalid('"arguments" and "service" cannot be used together.') + ->end() ->end() - ->arrayNode('arguments') + ->arrayNode('supports') ->beforeNormalization() ->ifString() ->then(function ($v) { return array($v); }) ->end() - ->requiresAtLeastOneElement() ->prototype('scalar') + ->cannotBeEmpty() + ->validate() + ->ifTrue(function ($v) { return !class_exists($v); }) + ->thenInvalid('The supported class %s does not exist.') + ->end() ->end() ->end() - ->scalarNode('service') + ->scalarNode('support_strategy') ->cannotBeEmpty() ->end() - ->end() - ->validate() - ->ifTrue(function ($v) { return isset($v['type']) && isset($v['service']); }) - ->thenInvalid('"type" and "service" cannot be used together.') - ->end() - ->validate() - ->ifTrue(function ($v) { return !empty($v['arguments']) && isset($v['service']); }) - ->thenInvalid('"arguments" and "service" cannot be used together.') - ->end() - ->end() - ->arrayNode('supports') - ->beforeNormalization() - ->ifString() - ->then(function ($v) { return array($v); }) - ->end() - ->prototype('scalar') - ->cannotBeEmpty() - ->validate() - ->ifTrue(function ($v) { return !class_exists($v); }) - ->thenInvalid('The supported class %s does not exist.') + ->scalarNode('initial_place') + ->defaultNull() ->end() - ->end() - ->end() - ->scalarNode('support_strategy') - ->cannotBeEmpty() - ->end() - ->scalarNode('initial_place') - ->defaultNull() - ->end() - ->arrayNode('places') - ->isRequired() - ->requiresAtLeastOneElement() - ->prototype('scalar') - ->cannotBeEmpty() - ->end() - ->end() - ->arrayNode('transitions') - ->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() - ->scalarNode('guard') + ->arrayNode('places') + ->isRequired() + ->requiresAtLeastOneElement() + ->prototype('scalar') ->cannotBeEmpty() - ->info('An expression to block the transition') - ->example('is_fully_authenticated() and has_role(\'ROLE_JOURNALIST\') and subject.getTitle() == \'My first article\'') ->end() - ->arrayNode('from') - ->beforeNormalization() - ->ifString() - ->then(function ($v) { return array($v); }) - ->end() - ->requiresAtLeastOneElement() - ->prototype('scalar') - ->cannotBeEmpty() - ->end() + ->end() + ->arrayNode('transitions') + ->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() - ->arrayNode('to') - ->beforeNormalization() - ->ifString() - ->then(function ($v) { return array($v); }) - ->end() - ->requiresAtLeastOneElement() - ->prototype('scalar') - ->cannotBeEmpty() + ->isRequired() + ->requiresAtLeastOneElement() + ->prototype('array') + ->children() + ->scalarNode('name') + ->isRequired() + ->cannotBeEmpty() + ->end() + ->scalarNode('guard') + ->cannotBeEmpty() + ->info('An expression to block the transition') + ->example('is_fully_authenticated() and has_role(\'ROLE_JOURNALIST\') and subject.getTitle() == \'My first article\'') + ->end() + ->arrayNode('from') + ->beforeNormalization() + ->ifString() + ->then(function ($v) { return array($v); }) + ->end() + ->requiresAtLeastOneElement() + ->prototype('scalar') + ->cannotBeEmpty() + ->end() + ->end() + ->arrayNode('to') + ->beforeNormalization() + ->ifString() + ->then(function ($v) { return array($v); }) + ->end() + ->requiresAtLeastOneElement() + ->prototype('scalar') + ->cannotBeEmpty() + ->end() + ->end() ->end() ->end() ->end() ->end() + ->validate() + ->ifTrue(function ($v) { + return $v['supports'] && isset($v['support_strategy']); + }) + ->thenInvalid('"supports" and "support_strategy" cannot be used together.') + ->end() + ->validate() + ->ifTrue(function ($v) { + return !$v['supports'] && !isset($v['support_strategy']); + }) + ->thenInvalid('"supports" or "support_strategy" should be configured.') + ->end() ->end() ->end() - ->validate() - ->ifTrue(function ($v) { - return $v['supports'] && isset($v['support_strategy']); - }) - ->thenInvalid('"supports" and "support_strategy" cannot be used together.') - ->end() - ->validate() - ->ifTrue(function ($v) { - return !$v['supports'] && !isset($v['support_strategy']); - }) - ->thenInvalid('"supports" or "support_strategy" should be configured.') - ->end() ->end() ->end() ->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index f54b74abb6051..2d382712911ef 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -530,13 +530,13 @@ private function registerProfilerConfiguration(array $config, ContainerBuilder $ /** * Loads the workflow configuration. * - * @param array $workflows A workflow configuration array + * @param array $config A workflow configuration array * @param ContainerBuilder $container A ContainerBuilder instance * @param XmlFileLoader $loader An XmlFileLoader instance */ - private function registerWorkflowConfiguration(array $workflows, ContainerBuilder $container, XmlFileLoader $loader) + private function registerWorkflowConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) { - if (!$workflows) { + if (!$config['enabled']) { if (!class_exists(Workflow\Workflow::class)) { $container->removeDefinition(WorkflowDumpCommand::class); } @@ -552,7 +552,7 @@ private function registerWorkflowConfiguration(array $workflows, ContainerBuilde $registryDefinition = $container->getDefinition('workflow.registry'); - foreach ($workflows as $name => $workflow) { + foreach ($config['workflows'] as $name => $workflow) { if (!array_key_exists('type', $workflow)) { $workflow['type'] = 'workflow'; @trigger_error(sprintf('The "type" option of the "framework.workflows.%s" configuration entry must be defined since Symfony 3.3. The default value will be "state_machine" in Symfony 4.0.', $name), E_USER_DEPRECATED); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd index d6138133cf2ea..481c469e36164 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd @@ -254,15 +254,16 @@ - + - - + + - + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index 0d2578db040af..1835625da8611 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -331,7 +331,10 @@ protected static function getBundleDefaultConfig() 'default_redis_provider' => 'redis://localhost', 'default_memcached_provider' => 'memcached://localhost', ), - 'workflows' => array(), + 'workflows' => array( + 'enabled' => false, + 'workflows' => array(), + ), 'php_errors' => array( 'log' => true, 'throw' => true, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_enabled.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_enabled.php new file mode 100644 index 0000000000000..9a2fe9136a4b3 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_enabled.php @@ -0,0 +1,5 @@ +loadFromExtension('framework', array( + 'workflows' => null, +)); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_enabled.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_enabled.xml new file mode 100644 index 0000000000000..51da644be1f9e --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_enabled.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_enabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_enabled.yml new file mode 100644 index 0000000000000..2a716ff0a1b14 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_enabled.yml @@ -0,0 +1,2 @@ +framework: + workflows: ~ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index d63a74c874f02..991eda1ea6ac6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection; use Doctrine\Common\Annotations\Annotation; +use Symfony\Bundle\FrameworkBundle\Command\WorkflowDumpCommand; use Symfony\Bundle\FullStack; use Symfony\Bundle\FrameworkBundle\Tests\TestCase; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddAnnotationsCachedReaderPass; @@ -42,6 +43,7 @@ use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer; use Symfony\Component\Translation\DependencyInjection\TranslatorPass; use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass; +use Symfony\Component\Workflow\Registry; abstract class FrameworkExtensionTest extends TestCase { @@ -307,6 +309,14 @@ public function testWorkflowMultipleTransitionsWithSameName() $this->assertSame(array('draft'), $transitions[4]->getArgument(1)); } + public function testWorkflowServicesCanBeEnabled() + { + $container = $this->createContainerFromFile('workflows_enabled'); + + $this->assertTrue($container->has(Registry::class)); + $this->assertTrue($container->hasDefinition(WorkflowDumpCommand::class)); + } + public function testRouter() { $container = $this->createContainerFromFile('full');