Skip to content

Commit 7a215eb

Browse files
committed
Merge branch '5.4' into 6.0
* 5.4: (27 commits) feat: add completion for DebugAutowiring search argument [Routing] Add support for aliasing routes [DependencyInjection] only allow `ReflectionNamedType` for `ServiceSubscriberTrait` Fix CS [Console] Open CompleteCommand for custom outputs [Intl] Update the ICU data to 70.1 [Messenger] Add completion for failed messages commands. Fix tests Fixing missing full_stack variable that's needed by toolbar.html.twig [PropertyInfo] Bump phpstan/phpdoc-parser [Security] Backport type fixes [VarExporter] escape unicode chars involved in directionality [Framework] Add completion to debug:container [Messenger] Add completion to command messenger:consume [Intl] Update the ICU data to 70.1 Fix more generic types Default access_decision_manager.strategy option with merge. Fix typos Update validators.ca.xlf Add missing Validator translations for Estonian ... Signed-off-by: Alexander M. Turek <[email protected]>
2 parents 5284b7f + cfc68ad commit 7a215eb

File tree

5 files changed

+144
-2
lines changed

5 files changed

+144
-2
lines changed

Command/ContainerDebugCommand.php

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
use Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper;
1515
use Symfony\Component\Console\Attribute\AsCommand;
1616
use Symfony\Component\Console\Command\Command;
17+
use Symfony\Component\Console\Completion\CompletionInput;
18+
use Symfony\Component\Console\Completion\CompletionSuggestions;
1719
use Symfony\Component\Console\Exception\InvalidArgumentException;
1820
use Symfony\Component\Console\Input\InputArgument;
1921
use Symfony\Component\Console\Input\InputInterface;
@@ -188,6 +190,44 @@ protected function execute(InputInterface $input, OutputInterface $output): int
188190
return 0;
189191
}
190192

193+
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
194+
{
195+
if ($input->mustSuggestOptionValuesFor('format')) {
196+
$helper = new DescriptorHelper();
197+
$suggestions->suggestValues($helper->getFormats());
198+
199+
return;
200+
}
201+
202+
$kernel = $this->getApplication()->getKernel();
203+
$object = $this->getContainerBuilder($kernel);
204+
205+
if ($input->mustSuggestArgumentValuesFor('name')
206+
&& !$input->getOption('tag') && !$input->getOption('tags')
207+
&& !$input->getOption('parameter') && !$input->getOption('parameters')
208+
&& !$input->getOption('env-var') && !$input->getOption('env-vars')
209+
&& !$input->getOption('types') && !$input->getOption('deprecations')
210+
) {
211+
$suggestions->suggestValues($this->findServiceIdsContaining(
212+
$object,
213+
$input->getCompletionValue(),
214+
(bool) $input->getOption('show-hidden')
215+
));
216+
217+
return;
218+
}
219+
220+
if ($input->mustSuggestOptionValuesFor('tag')) {
221+
$suggestions->suggestValues($object->findTags());
222+
223+
return;
224+
}
225+
226+
if ($input->mustSuggestOptionValuesFor('parameter')) {
227+
$suggestions->suggestValues(array_keys($object->getParameterBag()->all()));
228+
}
229+
}
230+
191231
/**
192232
* Validates input arguments and options.
193233
*
@@ -243,7 +283,7 @@ private function findServiceIdsContaining(ContainerBuilder $builder, string $nam
243283
if (false !== stripos(str_replace('\\', '', $serviceId), $name)) {
244284
$foundServiceIdsIgnoringBackslashes[] = $serviceId;
245285
}
246-
if (false !== stripos($serviceId, $name)) {
286+
if ('' === $name || false !== stripos($serviceId, $name)) {
247287
$foundServiceIds[] = $serviceId;
248288
}
249289
}

Command/DebugAutowiringCommand.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
use Symfony\Bundle\FrameworkBundle\Console\Descriptor\Descriptor;
1515
use Symfony\Component\Console\Attribute\AsCommand;
16+
use Symfony\Component\Console\Completion\CompletionInput;
17+
use Symfony\Component\Console\Completion\CompletionSuggestions;
1618
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
1719
use Symfony\Component\Console\Input\InputArgument;
1820
use Symfony\Component\Console\Input\InputInterface;
@@ -79,7 +81,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int
7981
$serviceIds = array_filter($serviceIds, [$this, 'filterToServiceTypes']);
8082

8183
if ($search = $input->getArgument('search')) {
82-
$searchNormalized = preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', '', $search);
84+
$searchNormalized = preg_replace('/[^a-zA-Z0-9\x7f-\xff $]++/', '', $search);
85+
8386
$serviceIds = array_filter($serviceIds, function ($serviceId) use ($searchNormalized) {
8487
return false !== stripos(str_replace('\\', '', $serviceId), $searchNormalized) && !str_starts_with($serviceId, '.');
8588
});
@@ -160,4 +163,13 @@ private function getFileLink(string $class): string
160163

161164
return (string) $this->fileLinkFormatter->format($r->getFileName(), $r->getStartLine());
162165
}
166+
167+
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
168+
{
169+
if ($input->mustSuggestArgumentValuesFor('search')) {
170+
$builder = $this->getContainerBuilder($this->getApplication()->getKernel());
171+
172+
$suggestions->suggestValues(array_filter($builder->getServiceIds(), [$this, 'filterToServiceTypes']));
173+
}
174+
}
163175
}

Resources/config/console.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@
151151
service('logger')->nullOnInvalid(),
152152
[], // Receiver names
153153
service('messenger.listener.reset_services')->nullOnInvalid(),
154+
[], // Bus names
154155
])
155156
->tag('console.command')
156157
->tag('monolog.logger', ['channel' => 'messenger'])

Tests/Functional/ContainerDebugCommandTest.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Bundle\FrameworkBundle\Console\Application;
1515
use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\BackslashClass;
1616
use Symfony\Component\Console\Tester\ApplicationTester;
17+
use Symfony\Component\Console\Tester\CommandCompletionTester;
1718

1819
/**
1920
* @group functional
@@ -211,4 +212,68 @@ public function provideIgnoreBackslashWhenFindingService()
211212
['\\'.BackslashClass::class],
212213
];
213214
}
215+
216+
/**
217+
* @dataProvider provideCompletionSuggestions
218+
*/
219+
public function testComplete(array $input, array $expectedSuggestions, array $notExpectedSuggestions = [])
220+
{
221+
static::bootKernel(['test_case' => 'ContainerDebug', 'root_config' => 'config.yml', 'debug' => true]);
222+
223+
$application = new Application(static::$kernel);
224+
$tester = new CommandCompletionTester($application->find('debug:container'));
225+
$suggestions = $tester->complete($input);
226+
227+
foreach ($expectedSuggestions as $expectedSuggestion) {
228+
$this->assertContains($expectedSuggestion, $suggestions);
229+
}
230+
foreach ($notExpectedSuggestions as $notExpectedSuggestion) {
231+
$this->assertNotContains($notExpectedSuggestion, $suggestions);
232+
}
233+
}
234+
235+
public function provideCompletionSuggestions()
236+
{
237+
$serviceId = 'console.command.container_debug';
238+
$hiddenServiceId = '.console.command.container_debug.lazy';
239+
$interfaceServiceId = 'Symfony\Component\HttpKernel\HttpKernelInterface';
240+
241+
yield 'name' => [
242+
[''],
243+
[$serviceId, $interfaceServiceId],
244+
[$hiddenServiceId],
245+
];
246+
247+
yield 'name (with hidden)' => [
248+
['--show-hidden', ''],
249+
[$serviceId, $interfaceServiceId, $hiddenServiceId],
250+
];
251+
252+
yield 'name (with current value)' => [
253+
['--show-hidden', 'console'],
254+
[$serviceId, $hiddenServiceId],
255+
[$interfaceServiceId],
256+
];
257+
258+
yield 'name (no suggestion with --tags)' => [
259+
['--tags', ''],
260+
[],
261+
[$serviceId, $interfaceServiceId, $hiddenServiceId],
262+
];
263+
264+
yield 'option --tag' => [
265+
['--tag', ''],
266+
['console.command'],
267+
];
268+
269+
yield 'option --parameter' => [
270+
['--parameter', ''],
271+
['kernel.debug'],
272+
];
273+
274+
yield 'option --format' => [
275+
['--format', ''],
276+
['txt', 'xml', 'json', 'md'],
277+
];
278+
}
214279
}

Tests/Functional/DebugAutowiringCommandTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111

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

14+
use Symfony\Bundle\FrameworkBundle\Command\DebugAutowiringCommand;
1415
use Symfony\Bundle\FrameworkBundle\Console\Application;
1516
use Symfony\Component\Console\Tester\ApplicationTester;
17+
use Symfony\Component\Console\Tester\CommandCompletionTester;
1618

1719
/**
1820
* @group functional
@@ -109,4 +111,26 @@ public function testNotConfusedByClassAliases()
109111
$tester->run(['command' => 'debug:autowiring', 'search' => 'ClassAlias']);
110112
$this->assertStringContainsString('Symfony\Bundle\FrameworkBundle\Tests\Fixtures\ClassAliasExampleClass', $tester->getDisplay());
111113
}
114+
115+
/**
116+
* @dataProvider provideCompletionSuggestions
117+
*/
118+
public function testComplete(array $input, array $expectedSuggestions)
119+
{
120+
$kernel = static::bootKernel(['test_case' => 'ContainerDebug', 'root_config' => 'config.yml']);
121+
$command = (new Application($kernel))->add(new DebugAutowiringCommand());
122+
123+
$tester = new CommandCompletionTester($command);
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 'search' => [[''], ['SessionHandlerInterface', 'Psr\\Log\\LoggerInterface', 'Psr\\Container\\ContainerInterface $parameterBag']];
135+
}
112136
}

0 commit comments

Comments
 (0)