Skip to content

Commit f873074

Browse files
committed
[Workflow] Mark registry as internal and deprecate the service
Instead, all workflow services are tagged and can be injected with the following YAML syntax: ```yaml !tagged_locator { tag: workflow, index_by: name } ``` or PHP syntax: ```php tagged_locator('workflow', 'name') ``` Also, two others tags exists for each workflow types * `workflow.workflow` * `workflow.state_machine`
1 parent 4a22bcb commit f873074

File tree

13 files changed

+87
-21
lines changed

13 files changed

+87
-21
lines changed

UPGRADE-6.2.md

+10
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,13 @@ Validator
3737
---------
3838

3939
* Deprecate the `loose` e-mail validation mode, use `html5` instead
40+
41+
Workflow
42+
--------
43+
44+
* The `Registry` is marked as internal and should not be used directly. use a tagged locator instead
45+
```
46+
tagged_locator('workflow', 'name')
47+
```
48+
* The first argument of `WorkflowDumpCommand` should be a `ServiceLocator` of
49+
all workflows indexed by names

UPGRADE-7.0.md

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
UPGRADE FROM 6.4 to 7.0
2+
=======================
3+
4+
Workflow
5+
--------
6+
7+
* The first argument of `WorkflowDumpCommand` must be a `ServiceLocator` of all
8+
workflows indexed by names

src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ CHANGELOG
1212
`Symfony\Component\Serializer\Normalizer\NormalizerInterface` or implement `NormalizerAwareInterface` instead
1313
* Add service usages list to the `debug:container` command output
1414
* Add service and alias deprecation message to `debug:container [<name>]` output
15+
* Tag all workflows services with `workflow`, those with type=workflow are
16+
tagged with `workflow.workflow`, and those with type=state_machine with
17+
`workflow.state_machine`
1518

1619
6.1
1720
---

src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php

+32-10
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@
2020
use Symfony\Component\Console\Input\InputInterface;
2121
use Symfony\Component\Console\Input\InputOption;
2222
use Symfony\Component\Console\Output\OutputInterface;
23+
use Symfony\Component\DependencyInjection\ServiceLocator;
2324
use Symfony\Component\Workflow\Definition;
2425
use Symfony\Component\Workflow\Dumper\GraphvizDumper;
2526
use Symfony\Component\Workflow\Dumper\MermaidDumper;
2627
use Symfony\Component\Workflow\Dumper\PlantUmlDumper;
2728
use Symfony\Component\Workflow\Dumper\StateMachineGraphvizDumper;
2829
use Symfony\Component\Workflow\Marking;
30+
use Symfony\Component\Workflow\StateMachine;
2931

3032
/**
3133
* @author Grégoire Pineau <lyrixx@lyrixx.info>
@@ -40,19 +42,28 @@ class WorkflowDumpCommand extends Command
4042
*
4143
* @var array<string, Definition>
4244
*/
43-
private array $workflows = [];
45+
private array $definitions = [];
46+
47+
private ServiceLocator $workflows;
4448

4549
private const DUMP_FORMAT_OPTIONS = [
4650
'puml',
4751
'mermaid',
4852
'dot',
4953
];
5054

51-
public function __construct(array $workflows)
55+
public function __construct($workflows)
5256
{
5357
parent::__construct();
5458

55-
$this->workflows = $workflows;
59+
if ($workflows instanceof ServiceLocator) {
60+
$this->workflows = $workflows;
61+
} elseif (\is_array($workflows)) {
62+
$this->definitions = $workflows;
63+
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__);
64+
} else {
65+
throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be an array or a ServiceLocator, "%s" given.', __METHOD__, \gettype($workflows)));
66+
}
5667
}
5768

5869
/**
@@ -88,15 +99,22 @@ protected function execute(InputInterface $input, OutputInterface $output): int
8899

89100
$workflow = null;
90101

91-
if (isset($this->workflows['workflow.'.$workflowName])) {
92-
$workflow = $this->workflows['workflow.'.$workflowName];
102+
if (isset($this->workflows)) {
103+
if (!$this->workflows->has($workflowName)) {
104+
throw new InvalidArgumentException(sprintf('The workflow named "%s" cannot be found.', $workflowName));
105+
}
106+
$workflow = $this->workflows->get($workflowName);
107+
$type = $workflow instanceof StateMachine ? 'state_machine' : 'workflow';
108+
$definition = $workflow->getDefinition();
109+
} elseif (isset($this->definitions['workflow.'.$workflowName])) {
110+
$definition = $this->definitions['workflow.'.$workflowName];
93111
$type = 'workflow';
94-
} elseif (isset($this->workflows['state_machine.'.$workflowName])) {
95-
$workflow = $this->workflows['state_machine.'.$workflowName];
112+
} elseif (isset($this->definitions['state_machine.'.$workflowName])) {
113+
$definition = $this->definitions['state_machine.'.$workflowName];
96114
$type = 'state_machine';
97115
}
98116

99-
if (null === $workflow) {
117+
if (null === $definition) {
100118
throw new InvalidArgumentException(sprintf('No service found for "workflow.%1$s" nor "state_machine.%1$s".', $workflowName));
101119
}
102120

@@ -129,15 +147,19 @@ protected function execute(InputInterface $input, OutputInterface $output): int
129147
'label' => $input->getOption('label'),
130148
],
131149
];
132-
$output->writeln($dumper->dump($workflow, $marking, $options));
150+
$output->writeln($dumper->dump($definition, $marking, $options));
133151

134152
return 0;
135153
}
136154

137155
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
138156
{
139157
if ($input->mustSuggestArgumentValuesFor('name')) {
140-
$suggestions->suggestValues(array_keys($this->workflows));
158+
if (isset($this->workflows)) {
159+
$suggestions->suggestValues(array_keys($this->workflows->getProvidedServices()));
160+
} else {
161+
$suggestions->suggestValues(array_keys($this->definitions));
162+
}
141163
}
142164

143165
if ($input->mustSuggestOptionValuesFor('dump-format')) {

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php

+1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ class UnusedTagsPass implements CompilerPassInterface
9797
'validator.auto_mapper',
9898
'validator.constraint_validator',
9999
'validator.initializer',
100+
'workflow',
100101
];
101102

102103
public function process(ContainerBuilder $container)

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

+9-5
Original file line numberDiff line numberDiff line change
@@ -883,9 +883,9 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $
883883

884884
$loader->load('workflow.php');
885885

886-
$registryDefinition = $container->getDefinition('workflow.registry');
886+
$registryDefinition = $container->getDefinition('.workflow.registry');
887887

888-
$workflows = [];
888+
$workflow = [];
889889

890890
foreach ($config['workflows'] as $name => $workflow) {
891891
$type = $workflow['type'];
@@ -994,6 +994,13 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $
994994
$workflowDefinition->replaceArgument(3, $name);
995995
$workflowDefinition->replaceArgument(4, $workflow['events_to_dispatch']);
996996

997+
$workflowDefinition->addTag('workflow', ['name' => $name]);
998+
if ('workflow' === $type) {
999+
$workflowDefinition->addTag('workflow.workflow', ['name' => $name]);
1000+
} elseif ('state_machine' === $type) {
1001+
$workflowDefinition->addTag('workflow.state_machine', ['name' => $name]);
1002+
}
1003+
9971004
// Store to container
9981005
$container->setDefinition($workflowId, $workflowDefinition);
9991006
$container->setDefinition(sprintf('%s.definition', $workflowId), $definitionDefinition);
@@ -1063,9 +1070,6 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $
10631070
$container->setParameter('workflow.has_guard_listeners', true);
10641071
}
10651072
}
1066-
1067-
$commandDumpDefinition = $container->getDefinition('console.command.workflow_dump');
1068-
$commandDumpDefinition->setArgument(0, $workflows);
10691073
}
10701074

10711075
private function registerDebugConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader)

src/Symfony/Bundle/FrameworkBundle/Resources/config/console.php

+3
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,9 @@
282282
->tag('console.command', ['command' => 'translation:push'])
283283

284284
->set('console.command.workflow_dump', WorkflowDumpCommand::class)
285+
->args([
286+
tagged_locator('workflow', 'name'),
287+
])
285288
->tag('console.command')
286289

287290
->set('console.command.xliff_lint', XliffLintCommand::class)

src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow.php

+5-2
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,11 @@
3939
->abstract()
4040
->set('workflow.marking_store.method', MethodMarkingStore::class)
4141
->abstract()
42-
->set('workflow.registry', Registry::class)
43-
->alias(Registry::class, 'workflow.registry')
42+
->set('.workflow.registry', Registry::class)
43+
->alias(Registry::class, '.workflow.registry')
44+
->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.')
45+
->alias('workflow.registry', '.workflow.registry')
46+
->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.')
4447
->set('workflow.security.expression_language', ExpressionLanguage::class)
4548
;
4649
};

src/Symfony/Bundle/FrameworkBundle/Tests/Command/WorkflowDumpCommandTest.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Bundle\FrameworkBundle\Command\WorkflowDumpCommand;
1616
use Symfony\Component\Console\Application;
1717
use Symfony\Component\Console\Tester\CommandCompletionTester;
18+
use Symfony\Component\DependencyInjection\ServiceLocator;
1819

1920
class WorkflowDumpCommandTest extends TestCase
2021
{
@@ -24,7 +25,7 @@ class WorkflowDumpCommandTest extends TestCase
2425
public function testComplete(array $input, array $expectedSuggestions)
2526
{
2627
$application = new Application();
27-
$application->add(new WorkflowDumpCommand([]));
28+
$application->add(new WorkflowDumpCommand(new ServiceLocator([])));
2829

2930
$tester = new CommandCompletionTester($application->find('workflow:dump'));
3031
$suggestions = $tester->complete($input, 2);

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php

+6-2
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,8 @@ public function testWorkflows()
295295
$this->assertArrayHasKey('index_4', $args);
296296
$this->assertNull($args['index_4'], 'Workflows has eventsToDispatch=null');
297297

298+
$this->assertSame(['workflow' => [['name' => 'article']], 'workflow.workflow' => [['name' => 'article']]], $container->getDefinition('workflow.article')->getTags());
299+
298300
$this->assertTrue($container->hasDefinition('workflow.article.definition'), 'Workflow definition is registered as a service');
299301

300302
$workflowDefinition = $container->getDefinition('workflow.article.definition');
@@ -324,6 +326,8 @@ public function testWorkflows()
324326
$this->assertSame('state_machine.abstract', $container->getDefinition('state_machine.pull_request')->getParent());
325327
$this->assertTrue($container->hasDefinition('state_machine.pull_request.definition'), 'State machine definition is registered as a service');
326328

329+
$this->assertSame(['workflow' => [['name' => 'pull_request']], 'workflow.state_machine' => [['name' => 'pull_request']]], $container->getDefinition('state_machine.pull_request')->getTags());
330+
327331
$stateMachineDefinition = $container->getDefinition('state_machine.pull_request.definition');
328332

329333
$this->assertSame(
@@ -371,8 +375,8 @@ public function testWorkflows()
371375
$this->assertInstanceOf(Reference::class, $markingStoreRef);
372376
$this->assertEquals('workflow_service', (string) $markingStoreRef);
373377

374-
$this->assertTrue($container->hasDefinition('workflow.registry'), 'Workflow registry is registered as a service');
375-
$registryDefinition = $container->getDefinition('workflow.registry');
378+
$this->assertTrue($container->hasDefinition('.workflow.registry'), 'Workflow registry is registered as a service');
379+
$registryDefinition = $container->getDefinition('.workflow.registry');
376380
$this->assertGreaterThan(0, \count($registryDefinition->getMethodCalls()));
377381
}
378382

src/Symfony/Bundle/TwigBundle/Resources/config/twig.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@
141141
->tag('translation.extractor', ['alias' => 'twig'])
142142

143143
->set('workflow.twig_extension', WorkflowExtension::class)
144-
->args([service('workflow.registry')])
144+
->args([service('.workflow.registry')])
145145

146146
->set('twig.configurator.environment', EnvironmentConfigurator::class)
147147
->args([

src/Symfony/Component/Workflow/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
6.2
5+
---
6+
7+
* Mark `Symfony\Component\Workflow\Registry` as internal
8+
49
6.0
510
---
611

src/Symfony/Component/Workflow/Registry.php

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
/**
1818
* @author Fabien Potencier <fabien@symfony.com>
1919
* @author Grégoire Pineau <lyrixx@lyrixx.info>
20+
*
21+
* @internal since Symfony 6.2. Inject the workflow where you need it.
2022
*/
2123
class Registry
2224
{

0 commit comments

Comments
 (0)