Skip to content

Commit 63aa0c5

Browse files
committed
Merge branch '5.4' into 6.0
* 5.4: [PropertyInfo] Support the list pseudo-type Add completion for DebugConfig name and path arguments Remove return types that confuse our types patching script
2 parents 7a215eb + fdf7907 commit 63aa0c5

File tree

2 files changed

+81
-5
lines changed

2 files changed

+81
-5
lines changed

Command/ConfigDebugCommand.php

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
use Symfony\Component\Config\Definition\ConfigurationInterface;
1515
use Symfony\Component\Config\Definition\Processor;
1616
use Symfony\Component\Console\Attribute\AsCommand;
17+
use Symfony\Component\Console\Completion\CompletionInput;
18+
use Symfony\Component\Console\Completion\CompletionSuggestions;
1719
use Symfony\Component\Console\Exception\LogicException;
1820
use Symfony\Component\Console\Input\InputArgument;
1921
use Symfony\Component\Console\Input\InputInterface;
@@ -92,11 +94,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
9294
$extensionAlias = $extension->getAlias();
9395
$container = $this->compileContainer();
9496

95-
$config = $container->resolveEnvPlaceholders(
96-
$container->getParameterBag()->resolveValue(
97-
$this->getConfigForExtension($extension, $container)
98-
)
99-
);
97+
$config = $this->getConfig($extension, $container);
10098

10199
if (null === $path = $input->getArgument('path')) {
102100
$io->title(
@@ -184,4 +182,55 @@ private function getConfigForExtension(ExtensionInterface $extension, ContainerB
184182

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

Tests/Functional/ConfigDebugCommandTest.php

Lines changed: 27 additions & 0 deletions
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)