Skip to content

Commit d77697c

Browse files
committed
feature #43850 Add completion for DebugConfig name and path arguments (eclairia, Adrien Jourdier)
This PR was squashed before being merged into the 5.4 branch. Discussion ---------- Add completion for DebugConfig name and path arguments | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | Fix #43594 | License | MIT | Doc PR | - Adding Bash completion for debug:config command. Commits ------- 3bcffc2 Add completion for DebugConfig name and path arguments
2 parents 4bcd0a4 + 3bcffc2 commit d77697c

File tree

2 files changed

+81
-5
lines changed

2 files changed

+81
-5
lines changed

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

+54-5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
use Symfony\Component\Config\Definition\ConfigurationInterface;
1515
use Symfony\Component\Config\Definition\Processor;
16+
use Symfony\Component\Console\Completion\CompletionInput;
17+
use Symfony\Component\Console\Completion\CompletionSuggestions;
1618
use Symfony\Component\Console\Exception\LogicException;
1719
use Symfony\Component\Console\Input\InputArgument;
1820
use Symfony\Component\Console\Input\InputInterface;
@@ -94,11 +96,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
9496
$extensionAlias = $extension->getAlias();
9597
$container = $this->compileContainer();
9698

97-
$config = $container->resolveEnvPlaceholders(
98-
$container->getParameterBag()->resolveValue(
99-
$this->getConfigForExtension($extension, $container)
100-
)
101-
);
99+
$config = $this->getConfig($extension, $container);
102100

103101
if (null === $path = $input->getArgument('path')) {
104102
$io->title(
@@ -188,4 +186,55 @@ private function getConfigForExtension(ExtensionInterface $extension, ContainerB
188186

189187
return (new Processor())->processConfiguration($configuration, $configs);
190188
}
189+
190+
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
191+
{
192+
if ($input->mustSuggestArgumentValuesFor('name')) {
193+
$suggestions->suggestValues($this->getAvailableBundles(!preg_match('/^[A-Z]/', $input->getCompletionValue())));
194+
195+
return;
196+
}
197+
198+
if ($input->mustSuggestArgumentValuesFor('path') && null !== $name = $input->getArgument('name')) {
199+
try {
200+
$config = $this->getConfig($this->findExtension($name), $this->compileContainer());
201+
$paths = array_keys(self::buildPathsCompletion($config));
202+
$suggestions->suggestValues($paths);
203+
} catch (LogicException $e) {
204+
}
205+
}
206+
}
207+
208+
private function getAvailableBundles(bool $alias): array
209+
{
210+
$availableBundles = [];
211+
foreach ($this->getApplication()->getKernel()->getBundles() as $bundle) {
212+
$availableBundles[] = $alias ? $bundle->getContainerExtension()->getAlias() : $bundle->getName();
213+
}
214+
215+
return $availableBundles;
216+
}
217+
218+
private function getConfig(ExtensionInterface $extension, ContainerBuilder $container)
219+
{
220+
return $container->resolveEnvPlaceholders(
221+
$container->getParameterBag()->resolveValue(
222+
$this->getConfigForExtension($extension, $container)
223+
)
224+
);
225+
}
226+
227+
private static function buildPathsCompletion(array $paths, string $prefix = ''): array
228+
{
229+
$completionPaths = [];
230+
foreach ($paths as $key => $values) {
231+
if (\is_array($values)) {
232+
$completionPaths = $completionPaths + self::buildPathsCompletion($values, $prefix.$key.'.');
233+
} else {
234+
$completionPaths[$prefix.$key] = null;
235+
}
236+
}
237+
238+
return $completionPaths;
239+
}
191240
}

src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php

+27
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111

1212
namespace Symfony\Bundle\FrameworkBundle\Tests\Functional;
1313

14+
use Symfony\Bundle\FrameworkBundle\Command\ConfigDebugCommand;
1415
use Symfony\Bundle\FrameworkBundle\Console\Application;
1516
use Symfony\Component\Console\Input\ArrayInput;
1617
use Symfony\Component\Console\Output\NullOutput;
18+
use Symfony\Component\Console\Tester\CommandCompletionTester;
1719
use Symfony\Component\Console\Tester\CommandTester;
1820

1921
/**
@@ -111,6 +113,31 @@ public function testDumpThrowsExceptionWhenDefaultConfigFallbackIsImpossible()
111113
$tester->execute(['name' => 'ExtensionWithoutConfigTestBundle']);
112114
}
113115

116+
/**
117+
* @dataProvider provideCompletionSuggestions
118+
*/
119+
public function testComplete(array $input, array $expectedSuggestions)
120+
{
121+
$this->application->add(new ConfigDebugCommand());
122+
123+
$tester = new CommandCompletionTester($this->application->get('debug:config'));
124+
125+
$suggestions = $tester->complete($input);
126+
127+
foreach ($expectedSuggestions as $expectedSuggestion) {
128+
$this->assertContains($expectedSuggestion, $suggestions);
129+
}
130+
}
131+
132+
public function provideCompletionSuggestions(): \Generator
133+
{
134+
yield 'name' => [[''], ['default_config_test', 'extension_without_config_test', 'framework', 'test']];
135+
136+
yield 'name (started CamelCase)' => [['Fra'], ['DefaultConfigTestBundle', 'ExtensionWithoutConfigTestBundle', 'FrameworkBundle', 'TestBundle']];
137+
138+
yield 'name with existing path' => [['framework', ''], ['secret', 'router.resource', 'router.utf8', 'router.enabled', 'validation.enabled', 'default_locale']];
139+
}
140+
114141
private function createCommandTester(): CommandTester
115142
{
116143
$command = $this->application->find('debug:config');

0 commit comments

Comments
 (0)