Skip to content

Commit

Permalink
[Workflow] Mark registry as internal and deprecate the service
Browse files Browse the repository at this point in the history
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`
  • Loading branch information
lyrixx committed Aug 12, 2022
1 parent 4a22bcb commit f873074
Show file tree
Hide file tree
Showing 13 changed files with 87 additions and 21 deletions.
10 changes: 10 additions & 0 deletions UPGRADE-6.2.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
8 changes: 8 additions & 0 deletions UPGRADE-7.0.md
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 [<name>]` 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
---
Expand Down
42 changes: 32 additions & 10 deletions src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 <lyrixx@lyrixx.info>
Expand All @@ -40,19 +42,28 @@ class WorkflowDumpCommand extends Command
*
* @var array<string, Definition>
*/
private array $workflows = [];
private array $definitions = [];

private ServiceLocator $workflows;

private const DUMP_FORMAT_OPTIONS = [
'puml',
'mermaid',
'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)));
}
}

/**
Expand Down Expand Up @@ -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));
}

Expand Down Expand Up @@ -129,15 +147,19 @@ 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;
}

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')) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ class UnusedTagsPass implements CompilerPassInterface
'validator.auto_mapper',
'validator.constraint_validator',
'validator.initializer',
'workflow',
];

public function process(ContainerBuilder $container)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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'];
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
;
};
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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()));
}

Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Bundle/TwigBundle/Resources/config/twig.php
Original file line number Diff line number Diff line change
Expand Up @@ -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([
Expand Down
5 changes: 5 additions & 0 deletions src/Symfony/Component/Workflow/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
CHANGELOG
=========

6.2
---

* Mark `Symfony\Component\Workflow\Registry` as internal

6.0
---

Expand Down
2 changes: 2 additions & 0 deletions src/Symfony/Component/Workflow/Registry.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
/**
* @author Fabien Potencier <fabien@symfony.com>
* @author Grégoire Pineau <lyrixx@lyrixx.info>
*
* @internal since Symfony 6.2. Inject the workflow where you need it.
*/
class Registry
{
Expand Down

0 comments on commit f873074

Please sign in to comment.