diff --git a/UPGRADE-6.2.md b/UPGRADE-6.2.md index 015dde43b155f..8271d0843738a 100644 --- a/UPGRADE-6.2.md +++ b/UPGRADE-6.2.md @@ -37,3 +37,13 @@ Validator --------- * Deprecate the `loose` e-mail validation mode, use `html5` instead + +Workflow +-------- + + * The `Registry` is marked as internal and should not be used directly. use a tagged locator instead + ``` + tagged_locator('workflow', 'name') + ``` + * The first argument of `WorkflowDumpCommand` should be a `ServiceLocator` of + all workflows indexed by names diff --git a/UPGRADE-7.0.md b/UPGRADE-7.0.md new file mode 100644 index 0000000000000..587796bbb6e9f --- /dev/null +++ b/UPGRADE-7.0.md @@ -0,0 +1,8 @@ +UPGRADE FROM 6.4 to 7.0 +======================= + +Workflow +-------- + + * The first argument of `WorkflowDumpCommand` must be a `ServiceLocator` of all + workflows indexed by names diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index 6766dc5c57992..7c503eb35d52b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -12,6 +12,9 @@ CHANGELOG `Symfony\Component\Serializer\Normalizer\NormalizerInterface` or implement `NormalizerAwareInterface` instead * Add service usages list to the `debug:container` command output * Add service and alias deprecation message to `debug:container []` output + * Tag all workflows services with `workflow`, those with type=workflow are + tagged with `workflow.workflow`, and those with type=state_machine with + `workflow.state_machine` 6.1 --- diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php index eb96e65470ebf..14ea912a86bd9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php @@ -20,12 +20,14 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\DependencyInjection\ServiceLocator; use Symfony\Component\Workflow\Definition; use Symfony\Component\Workflow\Dumper\GraphvizDumper; use Symfony\Component\Workflow\Dumper\MermaidDumper; use Symfony\Component\Workflow\Dumper\PlantUmlDumper; use Symfony\Component\Workflow\Dumper\StateMachineGraphvizDumper; use Symfony\Component\Workflow\Marking; +use Symfony\Component\Workflow\StateMachine; /** * @author Grégoire Pineau @@ -40,7 +42,9 @@ class WorkflowDumpCommand extends Command * * @var array */ - private array $workflows = []; + private array $definitions = []; + + private ServiceLocator $workflows; private const DUMP_FORMAT_OPTIONS = [ 'puml', @@ -48,11 +52,18 @@ class WorkflowDumpCommand extends Command 'dot', ]; - public function __construct(array $workflows) + public function __construct($workflows) { parent::__construct(); - $this->workflows = $workflows; + if ($workflows instanceof ServiceLocator) { + $this->workflows = $workflows; + } elseif (\is_array($workflows)) { + $this->definitions = $workflows; + trigger_deprecation('symfony/framework-bundle', '6.2', 'Passing an array of definitions in "%s()" is deprecated. Inject a ServiceLocator filled with all workflows instead.', __METHOD__); + } else { + throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be an array or a ServiceLocator, "%s" given.', __METHOD__, \gettype($workflows))); + } } /** @@ -88,15 +99,22 @@ protected function execute(InputInterface $input, OutputInterface $output): int $workflow = null; - if (isset($this->workflows['workflow.'.$workflowName])) { - $workflow = $this->workflows['workflow.'.$workflowName]; + if (isset($this->workflows)) { + if (!$this->workflows->has($workflowName)) { + throw new InvalidArgumentException(sprintf('The workflow named "%s" cannot be found.', $workflowName)); + } + $workflow = $this->workflows->get($workflowName); + $type = $workflow instanceof StateMachine ? 'state_machine' : 'workflow'; + $definition = $workflow->getDefinition(); + } elseif (isset($this->definitions['workflow.'.$workflowName])) { + $definition = $this->definitions['workflow.'.$workflowName]; $type = 'workflow'; - } elseif (isset($this->workflows['state_machine.'.$workflowName])) { - $workflow = $this->workflows['state_machine.'.$workflowName]; + } elseif (isset($this->definitions['state_machine.'.$workflowName])) { + $definition = $this->definitions['state_machine.'.$workflowName]; $type = 'state_machine'; } - if (null === $workflow) { + if (null === $definition) { throw new InvalidArgumentException(sprintf('No service found for "workflow.%1$s" nor "state_machine.%1$s".', $workflowName)); } @@ -129,7 +147,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int 'label' => $input->getOption('label'), ], ]; - $output->writeln($dumper->dump($workflow, $marking, $options)); + $output->writeln($dumper->dump($definition, $marking, $options)); return 0; } @@ -137,7 +155,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void { if ($input->mustSuggestArgumentValuesFor('name')) { - $suggestions->suggestValues(array_keys($this->workflows)); + if (isset($this->workflows)) { + $suggestions->suggestValues(array_keys($this->workflows->getProvidedServices())); + } else { + $suggestions->suggestValues(array_keys($this->definitions)); + } } if ($input->mustSuggestOptionValuesFor('dump-format')) { diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php index 42edc57ffc816..02b59afad5e61 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php @@ -97,6 +97,7 @@ class UnusedTagsPass implements CompilerPassInterface 'validator.auto_mapper', 'validator.constraint_validator', 'validator.initializer', + 'workflow', ]; public function process(ContainerBuilder $container) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 706773fa60522..c5855b04cd992 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -883,9 +883,9 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ $loader->load('workflow.php'); - $registryDefinition = $container->getDefinition('workflow.registry'); + $registryDefinition = $container->getDefinition('.workflow.registry'); - $workflows = []; + $workflow = []; foreach ($config['workflows'] as $name => $workflow) { $type = $workflow['type']; @@ -994,6 +994,13 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ $workflowDefinition->replaceArgument(3, $name); $workflowDefinition->replaceArgument(4, $workflow['events_to_dispatch']); + $workflowDefinition->addTag('workflow', ['name' => $name]); + if ('workflow' === $type) { + $workflowDefinition->addTag('workflow.workflow', ['name' => $name]); + } elseif ('state_machine' === $type) { + $workflowDefinition->addTag('workflow.state_machine', ['name' => $name]); + } + // Store to container $container->setDefinition($workflowId, $workflowDefinition); $container->setDefinition(sprintf('%s.definition', $workflowId), $definitionDefinition); @@ -1063,9 +1070,6 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ $container->setParameter('workflow.has_guard_listeners', true); } } - - $commandDumpDefinition = $container->getDefinition('console.command.workflow_dump'); - $commandDumpDefinition->setArgument(0, $workflows); } private function registerDebugConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.php index cc51b12a0bf2c..9ca75d099e5f9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.php @@ -282,6 +282,9 @@ ->tag('console.command', ['command' => 'translation:push']) ->set('console.command.workflow_dump', WorkflowDumpCommand::class) + ->args([ + tagged_locator('workflow', 'name'), + ]) ->tag('console.command') ->set('console.command.xliff_lint', XliffLintCommand::class) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow.php index b6c784bdbeaa9..4b8875da73424 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow.php @@ -39,8 +39,11 @@ ->abstract() ->set('workflow.marking_store.method', MethodMarkingStore::class) ->abstract() - ->set('workflow.registry', Registry::class) - ->alias(Registry::class, 'workflow.registry') + ->set('.workflow.registry', Registry::class) + ->alias(Registry::class, '.workflow.registry') + ->deprecate('symfony/workflow', '6.2', 'The "%alias_id%" alias is deprecated since Symfony 6.2 and will be removed in Symfony 7.0. Inject the workflow directly.') + ->alias('workflow.registry', '.workflow.registry') + ->deprecate('symfony/workflow', '6.2', 'The "%alias_id%" service is deprecated since Symfony 6.2 and will be removed in Symfony 7.0. Inject the workflow directly.') ->set('workflow.security.expression_language', ExpressionLanguage::class) ; }; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/WorkflowDumpCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/WorkflowDumpCommandTest.php index 13a63b40d97fa..cefc5dacd8e50 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/WorkflowDumpCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/WorkflowDumpCommandTest.php @@ -15,6 +15,7 @@ use Symfony\Bundle\FrameworkBundle\Command\WorkflowDumpCommand; use Symfony\Component\Console\Application; use Symfony\Component\Console\Tester\CommandCompletionTester; +use Symfony\Component\DependencyInjection\ServiceLocator; class WorkflowDumpCommandTest extends TestCase { @@ -24,7 +25,7 @@ class WorkflowDumpCommandTest extends TestCase public function testComplete(array $input, array $expectedSuggestions) { $application = new Application(); - $application->add(new WorkflowDumpCommand([])); + $application->add(new WorkflowDumpCommand(new ServiceLocator([]))); $tester = new CommandCompletionTester($application->find('workflow:dump')); $suggestions = $tester->complete($input, 2); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index 85ceec55ac8ca..320483fb0dafc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -295,6 +295,8 @@ public function testWorkflows() $this->assertArrayHasKey('index_4', $args); $this->assertNull($args['index_4'], 'Workflows has eventsToDispatch=null'); + $this->assertSame(['workflow' => [['name' => 'article']], 'workflow.workflow' => [['name' => 'article']]], $container->getDefinition('workflow.article')->getTags()); + $this->assertTrue($container->hasDefinition('workflow.article.definition'), 'Workflow definition is registered as a service'); $workflowDefinition = $container->getDefinition('workflow.article.definition'); @@ -324,6 +326,8 @@ public function testWorkflows() $this->assertSame('state_machine.abstract', $container->getDefinition('state_machine.pull_request')->getParent()); $this->assertTrue($container->hasDefinition('state_machine.pull_request.definition'), 'State machine definition is registered as a service'); + $this->assertSame(['workflow' => [['name' => 'pull_request']], 'workflow.state_machine' => [['name' => 'pull_request']]], $container->getDefinition('state_machine.pull_request')->getTags()); + $stateMachineDefinition = $container->getDefinition('state_machine.pull_request.definition'); $this->assertSame( @@ -371,8 +375,8 @@ public function testWorkflows() $this->assertInstanceOf(Reference::class, $markingStoreRef); $this->assertEquals('workflow_service', (string) $markingStoreRef); - $this->assertTrue($container->hasDefinition('workflow.registry'), 'Workflow registry is registered as a service'); - $registryDefinition = $container->getDefinition('workflow.registry'); + $this->assertTrue($container->hasDefinition('.workflow.registry'), 'Workflow registry is registered as a service'); + $registryDefinition = $container->getDefinition('.workflow.registry'); $this->assertGreaterThan(0, \count($registryDefinition->getMethodCalls())); } diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.php b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.php index cf8540764c7c4..aa5c543b30f40 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.php +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.php @@ -141,7 +141,7 @@ ->tag('translation.extractor', ['alias' => 'twig']) ->set('workflow.twig_extension', WorkflowExtension::class) - ->args([service('workflow.registry')]) + ->args([service('.workflow.registry')]) ->set('twig.configurator.environment', EnvironmentConfigurator::class) ->args([ diff --git a/src/Symfony/Component/Workflow/CHANGELOG.md b/src/Symfony/Component/Workflow/CHANGELOG.md index b533107a8f9b8..758606b3eb68f 100644 --- a/src/Symfony/Component/Workflow/CHANGELOG.md +++ b/src/Symfony/Component/Workflow/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +6.2 +--- + + * Mark `Symfony\Component\Workflow\Registry` as internal + 6.0 --- diff --git a/src/Symfony/Component/Workflow/Registry.php b/src/Symfony/Component/Workflow/Registry.php index 1fbc76be487ac..a9c21af18a906 100644 --- a/src/Symfony/Component/Workflow/Registry.php +++ b/src/Symfony/Component/Workflow/Registry.php @@ -17,6 +17,8 @@ /** * @author Fabien Potencier * @author Grégoire Pineau + * + * @internal since Symfony 6.2. Inject the workflow where you need it. */ class Registry { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy