diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php index 1249406f79188..e50b7493308db 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php @@ -12,6 +12,8 @@ namespace Symfony\Bundle\FrameworkBundle\Command; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Completion\CompletionInput; +use Symfony\Component\Console\Completion\CompletionSuggestions; use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -32,6 +34,20 @@ class WorkflowDumpCommand extends Command { protected static $defaultName = 'workflow:dump'; protected static $defaultDescription = 'Dump a workflow'; + private $workflows = []; + + private const DUMP_FORMAT_OPTIONS = [ + 'puml', + 'mermaid', + 'dot', + ]; + + public function __construct(array $workflows) + { + parent::__construct(); + + $this->workflows = $workflows; + } /** * {@inheritdoc} @@ -43,7 +59,7 @@ protected function configure() new InputArgument('name', InputArgument::REQUIRED, 'A workflow name'), new InputArgument('marking', InputArgument::IS_ARRAY, 'A marking (a list of places)'), new InputOption('label', 'l', InputOption::VALUE_REQUIRED, 'Label a graph'), - new InputOption('dump-format', null, InputOption::VALUE_REQUIRED, 'The dump format [dot|puml]', 'dot'), + new InputOption('dump-format', null, InputOption::VALUE_REQUIRED, 'The dump format ['.implode('|', self::DUMP_FORMAT_OPTIONS).']', 'dot'), ]) ->setDescription(self::$defaultDescription) ->setHelp(<<<'EOF' @@ -63,19 +79,14 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output): int { - $container = $this->getApplication()->getKernel()->getContainer(); - $serviceId = $input->getArgument('name'); - - if ($container->has('workflow.'.$serviceId)) { - $workflow = $container->get('workflow.'.$serviceId); - $type = 'workflow'; - } elseif ($container->has('state_machine.'.$serviceId)) { - $workflow = $container->get('state_machine.'.$serviceId); - $type = 'state_machine'; - } else { - throw new InvalidArgumentException(sprintf('No service found for "workflow.%1$s" nor "state_machine.%1$s".', $serviceId)); + $workflowId = $input->getArgument('name'); + + if (!\in_array($workflowId, array_keys($this->workflows), true)) { + throw new InvalidArgumentException(sprintf('No service found for "workflow.%1$s" nor "state_machine.%1$s".', $workflowId)); } + $type = explode('.', $workflowId)[0]; + switch ($input->getOption('dump-format')) { case 'puml': $transitionType = 'workflow' === $type ? PlantUmlDumper::WORKFLOW_TRANSITION : PlantUmlDumper::STATEMACHINE_TRANSITION; @@ -98,15 +109,28 @@ protected function execute(InputInterface $input, OutputInterface $output): int $marking->mark($place); } + $workflow = $this->workflows[$workflowId]; + $options = [ - 'name' => $serviceId, + 'name' => $workflowId, 'nofooter' => true, 'graph' => [ 'label' => $input->getOption('label'), ], ]; - $output->writeln($dumper->dump($workflow->getDefinition(), $marking, $options)); + $output->writeln($dumper->dump($workflow, $marking, $options)); return 0; } + + public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void + { + if ($input->mustSuggestArgumentValuesFor('name')) { + $suggestions->suggestValues(array_keys($this->workflows)); + } + + if ($input->mustSuggestOptionValuesFor('dump-format')) { + $suggestions->suggestValues(self::DUMP_FORMAT_OPTIONS); + } + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index ac5b3126a6f86..12a7441895401 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -799,6 +799,8 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ $registryDefinition = $container->getDefinition('workflow.registry'); + $workflows = []; + foreach ($config['workflows'] as $name => $workflow) { $type = $workflow['type']; $workflowId = sprintf('%s.%s', $type, $name); @@ -886,6 +888,8 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ $definitionDefinition->addArgument($initialMarking); $definitionDefinition->addArgument(new Reference(sprintf('%s.metadata_store', $workflowId))); + $workflows[$workflowId] = $definitionDefinition; + // Create MarkingStore if (isset($workflow['marking_store']['type'])) { $markingStoreDefinition = new ChildDefinition('workflow.marking_store.method'); @@ -977,6 +981,9 @@ 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/Tests/Command/WorkflowDumpCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/WorkflowDumpCommandTest.php new file mode 100644 index 0000000000000..13a63b40d97fa --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/WorkflowDumpCommandTest.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Command; + +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\FrameworkBundle\Command\WorkflowDumpCommand; +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Tester\CommandCompletionTester; + +class WorkflowDumpCommandTest extends TestCase +{ + /** + * @dataProvider provideCompletionSuggestions + */ + public function testComplete(array $input, array $expectedSuggestions) + { + $application = new Application(); + $application->add(new WorkflowDumpCommand([])); + + $tester = new CommandCompletionTester($application->find('workflow:dump')); + $suggestions = $tester->complete($input, 2); + $this->assertSame($expectedSuggestions, $suggestions); + } + + public function provideCompletionSuggestions(): iterable + { + yield 'option --dump-format' => [['--dump-format', ''], ['puml', 'mermaid', 'dot']]; + } +}